flutter進行tab頁的設計與改造

yuezheyue123發表於2018-10-31

使用tab頁官網地址:
https://flutterchina.club/catalog/samples/AppBar_index/

我們對於其中的顯示的樣式並不夠滿意,其實我們可以檢視原始碼,借用裡面的邏輯進行自身需要的改造。下面的是將第一種tab頁進行改造

import ‘package:flutter/material.dart’;

class AppBarBottomSample extends StatefulWidget {
@override
_AppBarBottomSampleState createState() => new _AppBarBottomSampleState();
}

class _AppBarBottomSampleState extends State
with SingleTickerProviderStateMixin {
TabController _tabController;

@override
void initState() {
super.initState();
_tabController = new TabController(vsync: this, length: choices.length);
}

@override
void dispose() {
_tabController.dispose();
super.dispose();
}

void _nextPage(int delta) {
final int newIndex = _tabController.index + delta;
if (newIndex < 0 || newIndex >= _tabController.length) return;
_tabController.animateTo(newIndex);
}

@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text(‘AppBar Bottom Widget’),
leading: new IconButton(
tooltip: ‘Previous choice’,
icon: const Icon(Icons.arrow_back),
onPressed: () {
_nextPage(-1);
},
),
actions: [
new IconButton(
icon: const Icon(Icons.arrow_forward),
tooltip: ‘Next choice’,
onPressed: () {
_nextPage(1);
},
),
],
//這裡進行固定了tabbar,如果想跟隨滾動,那麼就要使用TabBar控制元件
bottom: new PreferredSize(
preferredSize: const Size.fromHeight(48.0),
child: new Container(
height: 48.0,
alignment: Alignment.center,
child: new MyTabPageSelector(
controller: _tabController,
color: Colors.red,
selectedColor: Colors.yellowAccent,
),
),
),
),
body: new TabBarView(
controller: _tabController,
children: choices.map((Choice choice) {
return new Padding(
padding: const EdgeInsets.all(16.0),
child: new ChoiceCard(choice: choice),
);
}).toList(),
),
),
);
}
}

class Choice {
const Choice({this.title, this.icon});

final String title;
final IconData icon;
}

const List choices = const [
const Choice(title: ‘CAR’, icon: Icons.directions_car),
const Choice(title: ‘BICYCLE’, icon: Icons.directions_bike),
const Choice(title: ‘BOAT’, icon: Icons.directions_boat),
const Choice(title: ‘BUS’, icon: Icons.directions_bus),
const Choice(title: ‘TRAIN’, icon: Icons.directions_railway),
const Choice(title: ‘WALK’, icon: Icons.directions_walk),
];

class ChoiceCard extends StatelessWidget {
const ChoiceCard({Key key, this.choice}) : super(key: key);

final Choice choice;

@override
Widget build(BuildContext context) {
final TextStyle textStyle = Theme.of(context).textTheme.display1;
return new Card(
color: Colors.white,
child: new Center(
child: new Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
new Icon(choice.icon, size: 128.0, color: textStyle.color),
new Text(choice.title, style: textStyle),
],
),
),
);
}
}

void main() {
runApp(new AppBarBottomSample());
}

class MyTabPageSelectorIndicator extends StatelessWidget {
/// Creates an indicator used by [TabPageSelector].
///
/// The [backgroundColor], [borderColor], and [size] parameters must not be null.
const MyTabPageSelectorIndicator({
Key key,
this.backgroundColor,
this.borderColor,
this.size,
})
: assert(backgroundColor != null),
assert(borderColor != null),
assert(size != null),
super(key: key);

/// The indicator circle’s background color.
final Color backgroundColor;

/// The indicator circle’s border color.
final Color borderColor;

/// The indicator circle’s diameter.
final double size;

@override
Widget build(BuildContext context) {
return new Container(
width: 50.0,
height: 30.0,
child: new Text(“啦啦”,style: new TextStyle(color: backgroundColor),),
margin: const EdgeInsets.all(4.0),
// decoration: new BoxDecoration(
// color: backgroundColor,
// border: new Border.all(color: borderColor),
// shape: BoxShape.rectangle,
// ),
);
}
}

double _indexChangeProgress(TabController controller) {
final double controllerValue = controller.animation.value;
final double previousIndex = controller.previousIndex.toDouble();
final double currentIndex = controller.index.toDouble();

// The controller’s offset is changing because the user is dragging the
// TabBarView’s PageView to the left or right.
if (!controller.indexIsChanging)
return (currentIndex - controllerValue).abs().clamp(0.0, 1.0);

// The TabController animation’s value is changing from previousIndex to currentIndex.
return (controllerValue - currentIndex).abs() /
(currentIndex - previousIndex).abs();
}

class MyTabPageSelector extends StatelessWidget {
const MyTabPageSelector({
Key key,
this.controller,
this.indicatorSize: 12.0,
this.color,
this.selectedColor,
})
: assert(indicatorSize != null && indicatorSize > 0.0),
super(key: key);

final TabController controller;

final double indicatorSize;

final Color color;

final Color selectedColor;

Widget _buildTabIndicator(
int tabIndex,
TabController tabController,
ColorTween selectedColorTween,
ColorTween previousColorTween,
) {
Color background;
if (tabController.indexIsChanging) {
// The selection’s animation is animating from previousValue to value.
final double t = 1.0 - _indexChangeProgress(tabController);
if (tabController.index == tabIndex)
background = selectedColorTween.lerp(t);
else if (tabController.previousIndex == tabIndex)
background = previousColorTween.lerp(t);
else
background = selectedColorTween.begin;
} else {
// The selection’s offset reflects how far the TabBarView has / been dragged
// to the previous page (-1.0 to 0.0) or the next page (0.0 to 1.0).
final double offset = tabController.offset;
if (tabController.index == tabIndex) {
background = selectedColorTween.lerp(1.0 - offset.abs());
} else if (tabController.index == tabIndex - 1 && offset > 0.0) {
background = selectedColorTween.lerp(offset);
} else if (tabController.index == tabIndex + 1 && offset < 0.0) {
background = selectedColorTween.lerp(-offset);
} else {
background = selectedColorTween.begin;
}
}
return new MyTabPageSelectorIndicator(
backgroundColor: background,
borderColor: selectedColorTween.end,
size: indicatorSize,
);
}

@override
Widget build(BuildContext context) {
final Color fixColor = color ?? Colors.transparent;
final Color fixSelectedColor =
selectedColor ?? Theme.of(context).accentColor;
final ColorTween selectedColorTween =
new ColorTween(begin: fixColor, end: fixSelectedColor);
final ColorTween previousColorTween =
new ColorTween(begin: fixSelectedColor, end: fixColor);
final TabController tabController =
controller ?? DefaultTabController.of(context);
assert(() {
if (tabController == null) {
throw new FlutterError("");
}
return true;
}());
final Animation animation = new CurvedAnimation(
parent: tabController.animation,
curve: Curves.fastOutSlowIn,
);
return new AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget child) {
return new Semantics(
label: ‘Page ${tabController.index + 1} of ${tabController.length}’,
child: new Row(
mainAxisSize: MainAxisSize.min,
children: new List.generate(tabController.length,
(int tabIndex) {
return _buildTabIndicator(tabIndex, tabController,
selectedColorTween, previousColorTween);
}).toList(),
),
);
});
}
}

相關文章