Provider
了官方说好用,那么用就是了~bash
使用provider
是为了更好的进行状态管理,为何要进行状态管理?固然你怕你组件多了本身瞎搞,乱成一锅粥~markdown
没图啊,效果图再贴一遍吧,狗带 less
double
)了,才能作出相应的改变/// 色盘: 写两个意思一下,十二个月,应该有十二个。。
static const List<List<Color>> linerColor = [
[
Color.fromARGB(255, 87, 211, 255),
Color.fromARGB(255, 86, 173, 254),
],
[
Color.fromARGB(255, 86, 173, 254),
Color.fromARGB(255, 82, 118, 254),
],
];
复制代码
build
build
,只要我build
的足够快,你的眼睛就跟不上我。。。动画也不是这么搞的嘛,笑摸我狗头~provider
走起来有了上面的分析,咱们的provider
只要通知page
就够了,ide
/// 哇靠,怎么和官方的写法有差异!!
class HomeState with ChangeNotifier {
HomeState(this._ctrl) : assert(_ctrl != null) {
_ctrl.addListener(() {
_curPage = _ctrl.page.floor();
notifyListeners();
});
}
final PageController _ctrl;
int get curPage => _curPage;
double get value => _ctrl?.page ?? 0;
int _curPage = 0;
void setPage(int index) {
_curPage = index;
notifyListeners();
}
void buildChild() {
notifyListeners();
}
}
复制代码
哇靠,怎么和官方的写法有差异!!其实没什么差异,只是咱们有一个addListener
的操做,而咱们的PageController
不是由HomeState
来管理的。(实际上是能够放在HomeState
管理,当时有一个什么顾虑,我如今想不起来了,可怕。。继续)动画
这里我能够看到,只要滚动卡片就会buildChild
。ui
刚开始的时候,咱们的页面都堆在一个页面里,看起来及其凶残,如今外面来拆分一下,this
_FloatBtnWidget
悬浮的添加按钮class _FloatBtnWidget extends StatelessWidget {
_FloatBtnWidget(this._homeProvider);
final HomeState _homeProvider;
@override
Widget build(BuildContext context) {
double cil = _homeProvider.value - _homeProvider.value.floor();
double lerp = cil == 0 ? 1 : cil;
return Container(
width: 56,
height: 56,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color.lerp(
StaticStyle.linerColor[_homeProvider.curPage][0],
StaticStyle.linerColor[_homeProvider.value.ceil()][0],
lerp,
),
Color.lerp(
StaticStyle.linerColor[_homeProvider.curPage][1],
StaticStyle.linerColor[_homeProvider.value.ceil()][1],
lerp,
),
],
),
boxShadow: [
BoxShadow(
color: Color.fromARGB(100, 87, 211, 255),
blurRadius: 8,
)
],
),
child: Icon(Icons.add, color: Colors.white),
);
}
}
复制代码
_BottomNavWidget
底部导航栏class _BottomNavWidget extends StatelessWidget {
_BottomNavWidget(this._homeProvider, this.tabState);
final TabState tabState;
final HomeState _homeProvider;
@override
Widget build(BuildContext context) {
double cil = _homeProvider.value - _homeProvider.value.floor();
double lerp = cil == 0 ? 1 : cil;
final Gradient gradient = LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Colors.black54,
Colors.black,
],
);
final Gradient selectedGradient = LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color.lerp(
StaticStyle.linerColor[_homeProvider.curPage][0],
StaticStyle.linerColor[_homeProvider.value.ceil()][0],
lerp,
),
Color.lerp(
StaticStyle.linerColor[_homeProvider.curPage][1],
StaticStyle.linerColor[_homeProvider.value.ceil()][1],
lerp,
),
],
);
return DecoratedBox(
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: Color.fromARGB(100, 200, 200, 200),
blurRadius: 8,
)
]),
child: ClipRRect(
borderRadius: BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)),
child: BottomAppBar(
elevation: 0,
notchMargin: 6,
shape: CircularNotchedRectangle(),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
GradientIconBtn(
Icons.note_add,
key: ValueKey('page-index-0'),
iconSize: 26,
gradient: gradient,
selectedGradient: selectedGradient,
selected: tabState.tabIndex == 0,
onPress: () {
tabState.setTab(0);
},
),
Text(''),
GradientIconBtn(
Icons.person,
key: ValueKey('page-index-1'),
iconSize: 26,
gradient: gradient,
selectedGradient: selectedGradient,
selected: tabState.tabIndex == 1,
onPress: () {
tabState.setTab(1);
},
),
],
),
),
),
);
}
}
复制代码
导航栏的菜单也进行的封装GradientIconBtn
:spa
class GradientIconBtn extends StatelessWidget {
GradientIconBtn(
this.icon, {
Key key,
@required this.onPress,
this.iconSize,
this.gradient,
this.selectedGradient,
this.selected = false,
}) : super(key: key);
final VoidCallback onPress;
final IconData icon;
final double iconSize;
final Gradient gradient;
final Gradient selectedGradient;
final bool selected;
@override
Widget build(BuildContext context) {
return IconButton(
onPressed: onPress,
icon: gradient == null
? Icon(icon, size: iconSize)
: GradientText(
iconData: icon,
iconSize: iconSize,
gradient: selected ? selectedGradient : gradient,
),
);
}
}
复制代码
ChangeNotifierProvider
:ChangeNotifierProvider<HomeState>(
builder: (_) => HomeState(_pageController),
child: Consumer<HomeState>(
child: IndexedStack(
index: widget.tabState.tabIndex,
children: <Widget>[
NoteYearViewPage(_pageController),
MinePage(),
],
),
builder: (_, HomeState homeProvider, Widget child) => Scaffold(
body: child,
floatingActionButton: _FloatBtnWidget(homeProvider),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: _BottomNavWidget(homeProvider, widget.tabState),
),
),
)
复制代码
NoteYearViewPage
是卡片页面,比较简单,写死的渐变。MinePage
是个人页面,空荡荡。。code
能够看到,咱们使用了ChangeNotifierProvider
,当收到buildChild
事件后,就会build
一个Scaffold
而咱们的child
则会原封不动的放进Scaffold
中,避免了从新build
。cdn
好像完成了,呵呵呵~贴代码真是爽,整个过程只要28分钟。。 中间有一些小细节可能没有说明,想了解的小伙伴能够查看源码: gayhub