Flutter第八期-控件總結(jié)篇

????最近寫(xiě)前端,沒(méi)有總結(jié)flutter的學(xué)習(xí)進(jìn)程,現(xiàn)在來(lái)總結(jié)一下,關(guān)于動(dòng)畫(huà),布局,登錄,首頁(yè),路由,json格式化,下拉刷新,圖片加載預(yù)覽,歡迎頁(yè),焦點(diǎn)問(wèn)題,?;?,上傳圖片,頁(yè)面信息傳遞,這些知識(shí)點(diǎn)。由于官方文檔給的知識(shí)點(diǎn)很少,大部分是一些零零散散的API,所以只能通過(guò)一些大神的總結(jié)去剝離功能性的寫(xiě)法,如果理解不了的話就google,記不住的話就看demo,寫(xiě)多了就記住了,前期國(guó)內(nèi)資源有限大家可以慢慢的學(xué),但是要學(xué),如果你還想做APP的話,flutter以后肯定會(huì)有一片天地的,畢竟一套代碼三個(gè)平臺(tái),企業(yè)老板會(huì)因?yàn)槌杀径喽嗌偕偾嗖A的,所以加油~

成都創(chuàng)新互聯(lián)是工信部頒發(fā)資質(zhì)IDC服務(wù)器商,為用戶提供優(yōu)質(zhì)的成都多線服務(wù)器托管服務(wù)

????附:效果圖因?yàn)閐emo有點(diǎn)多,會(huì)慢慢補(bǔ)齊,寫(xiě)了三個(gè)小時(shí),感謝大家支持

????1.animated_container(放大 縮小github:https://github.com/geeklx/flutter_app2/tree/master/app2/animated_container):AnimationContainer使用要點(diǎn),必須傳入Duration告訴動(dòng)畫(huà)的播放時(shí)間,當(dāng)animationContainer接收到一個(gè)新的值的時(shí)候,會(huì)根據(jù)老值進(jìn)行補(bǔ)間動(dòng)畫(huà),例如開(kāi)始寬高為100,然后給了新值0并setState后,AnimationContainer會(huì)讓寬高從100逐漸變化到0,其中變化曲線由Curve決定,默認(rèn)為Curves.linear。其實(shí)動(dòng)畫(huà)大部分都是封裝好的,多寫(xiě)寫(xiě)就會(huì)了,實(shí)在記不住就看demo,好記性不如個(gè)爛筆頭。

Flutter第八期 - 控件總結(jié)篇?Flutter第八期 - 控件總結(jié)篇

import?'package:flutter/material.dart';
import?'animated_container_demo.dart';

void?main()?=>?runApp(new?MyApp());

class?MyApp?extends?StatelessWidget?{
??//?This?widget?is?the?root?of?your?application.
??@override
??Widget?build(BuildContext?context)?{
????return?new?MaterialApp(
??????title:?'Flutter?Demo',
??????theme:?new?ThemeData(
????????primarySwatch:?Colors.blue,
??????),
??????home:?AnimatedContainerDemo(),
????);
??}
}


/**
?*?AnimationContainer使用要點(diǎn)
?*?必須傳入Duration告訴動(dòng)畫(huà)的播放時(shí)間
?*?當(dāng)animationContainer接收到一個(gè)新的值的時(shí)候
?*?會(huì)根據(jù)老值進(jìn)行補(bǔ)間動(dòng)畫(huà)
?*?例如開(kāi)始寬高為100,然后給了新值0并setState后
?*?AnimationContainer會(huì)讓寬高從100逐漸變化到0
?*?其中變化曲線由Curve決定,默認(rèn)為Curves.linear
?*/
import?'package:flutter/material.dart';

class?AnimatedContainerDemo?extends?StatefulWidget?{
??@override
??_AnimatedContainerDemoState?createState()?=>?_AnimatedContainerDemoState();
}

class?_AnimatedContainerDemoState?extends?State<AnimatedContainerDemo>?{
??double?_value?=?255.0;

??_changeValue()?=>?setState(()?{
????????_value?=?_value?==?255.0???80.0?:?255.0;
????????print(_value);
??????});

??@override
??Widget?build(BuildContext?context)?{
????return?Center(
??????child:?GestureDetector(
????????onTap:?_changeValue,?//放大?縮小
????????child:?AnimatedContainer(
??????????curve:?Curves.decelerate,
??????????duration:?Duration(seconds:?1),
??????????width:?_value,
??????????height:?_value,
??????????child:?FlutterLogo(),
????????),
??????),
????);
??}
}

????2.animated_cross_fade(橫豎轉(zhuǎn)向動(dòng)畫(huà)github:https://github.com/geeklx/flutter_app2/tree/master/app2/animated_cross_fade):

Flutter第八期 - 控件總結(jié)篇?Flutter第八期 - 控件總結(jié)篇

import?'package:flutter/material.dart';

class?AnimatedCrossFadeDemo?extends?StatefulWidget?{
??@override
??_AnimatedCrossFadeDemoState?createState()?=>?_AnimatedCrossFadeDemoState();
}

class?_AnimatedCrossFadeDemoState?extends?State<AnimatedCrossFadeDemo>?{
??bool?_first?=?false;

??change()?{
????setState(()?{
??????_first?=?_first???false?:?true;
????});
??}

??@override
??Widget?build(BuildContext?context)?{
????return?Center(
??????child:?GestureDetector(
????????onTap:?change,?//?橫豎轉(zhuǎn)向動(dòng)畫(huà)
????????child:?AnimatedCrossFade(
??????????duration:?const?Duration(seconds:?2),
??????????firstChild:?const?FlutterLogo(
????????????style:?FlutterLogoStyle.horizontal,
????????????size:?200.0,
??????????),
??????????secondChild:?const?FlutterLogo(
????????????style:?FlutterLogoStyle.stacked,
????????????size:?200.0,
??????????),
??????????crossFadeState:
??????????????_first???CrossFadeState.showFirst?:?CrossFadeState.showSecond,
????????),
??????),
????);
??}
}

????3.animated_floating_action_bar(懸浮按鈕github:https://github.com/geeklx/flutter_app2/tree/master/app2/animated_floating_action_bar):這個(gè)是官方的demo

?Flutter第八期 - 控件總結(jié)篇

import?'package:flutter/material.dart';

void?main()?=>?runApp(MyApp());

class?MyApp?extends?StatelessWidget?{
??//?This?widget?is?the?root?of?your?application.
??@override
??Widget?build(BuildContext?context)?{
????return?MaterialApp(
??????title:?'Flutter?Demo',
??????theme:?ThemeData(
????????//?This?is?the?theme?of?your?application.
????????//
????????//?Try?running?your?application?with?"flutter?run".?You'll?see?the
????????//?application?has?a?blue?toolbar.?Then,?without?quitting?the?app,?try
????????//?changing?the?primarySwatch?below?to?Colors.green?and?then?invoke
????????//?"hot?reload"?(press?"r"?in?the?console?where?you?ran?"flutter?run",
????????//?or?simply?save?your?changes?to?"hot?reload"?in?a?Flutter?IDE).
????????//?Notice?that?the?counter?didn't?reset?back?to?zero;?the?application
????????//?is?not?restarted.
????????primarySwatch:?Colors.blue,
??????),
??????home:?MyHomePage(title:?'Flutter?Demo?Home?Page'),
????);
??}
}

class?MyHomePage?extends?StatefulWidget?{
??MyHomePage({Key?key,?this.title})?:?super(key:?key);

??//?This?widget?is?the?home?page?of?your?application.?It?is?stateful,?meaning
??//?that?it?has?a?State?object?(defined?below)?that?contains?fields?that?affect
??//?how?it?looks.

??//?This?class?is?the?configuration?for?the?state.?It?holds?the?values?(in?this
??//?case?the?title)?provided?by?the?parent?(in?this?case?the?App?widget)?and
??//?used?by?the?build?method?of?the?State.?Fields?in?a?Widget?subclass?are
??//?always?marked?"final".

??final?String?title;

??@override
??_MyHomePageState?createState()?=>?_MyHomePageState();
}

class?_MyHomePageState?extends?State<MyHomePage>?{
??int?_counter?=?0;

??void?_incrementCounter()?{
????setState(()?{
??????//?This?call?to?setState?tells?the?Flutter?framework?that?something?has
??????//?changed?in?this?State,?which?causes?it?to?rerun?the?build?method?below
??????//?so?that?the?display?can?reflect?the?updated?values.?If?we?changed
??????//?_counter?without?calling?setState(),?then?the?build?method?would?not?be
??????//?called?again,?and?so?nothing?would?appear?to?happen.
??????_counter++;
????});
??}

??@override
??Widget?build(BuildContext?context)?{
????//?This?method?is?rerun?every?time?setState?is?called,?for?instance?as?done
????//?by?the?_incrementCounter?method?above.
????//
????//?The?Flutter?framework?has?been?optimized?to?make?rerunning?build?methods
????//?fast,?so?that?you?can?just?rebuild?anything?that?needs?updating?rather
????//?than?having?to?individually?change?instances?of?widgets.
????return?Scaffold(
??????appBar:?AppBar(
????????//?Here?we?take?the?value?from?the?MyHomePage?object?that?was?created?by
????????//?the?App.build?method,?and?use?it?to?set?our?appbar?title.
????????title:?Text(widget.title),
??????),
??????body:?Center(
????????//?Center?is?a?layout?widget.?It?takes?a?single?child?and?positions?it
????????//?in?the?middle?of?the?parent.
????????child:?Column(
??????????//?Column?is?also?layout?widget.?It?takes?a?list?of?children?and
??????????//?arranges?them?vertically.?By?default,?it?sizes?itself?to?fit?its
??????????//?children?horizontally,?and?tries?to?be?as?tall?as?its?parent.
??????????//
??????????//?Invoke?"debug?painting"?(press?"p"?in?the?console,?choose?the
??????????//?"Toggle?Debug?Paint"?action?from?the?Flutter?Inspector?in?Android
??????????//?Studio,?or?the?"Toggle?Debug?Paint"?command?in?Visual?Studio?Code)
??????????//?to?see?the?wireframe?for?each?widget.
??????????//
??????????//?Column?has?various?properties?to?control?how?it?sizes?itself?and
??????????//?how?it?positions?its?children.?Here?we?use?mainAxisAlignment?to
??????????//?center?the?children?vertically;?the?main?axis?here?is?the?vertical
??????????//?axis?because?Columns?are?vertical?(the?cross?axis?would?be
??????????//?horizontal).
??????????mainAxisAlignment:?MainAxisAlignment.center,
??????????children:?<Widget>[
????????????Text(
??????????????'You?have?pushed?the?button?this?many?times:',
????????????),
????????????Text(
??????????????'$_counter',
??????????????style:?Theme.of(context).textTheme.display1,
????????????),
??????????],
????????),
??????),
??????floatingActionButton:?FloatingActionButton(
????????onPressed:?_incrementCounter,
????????tooltip:?'Increment',
????????child:?Icon(Icons.add),
??????),?//?This?trailing?comma?makes?auto-formatting?nicer?for?build?methods.
????);
??}
}

????4.animation_challenge(github:https://github.com/geeklx/flutter_app2/tree/master/app2/animation_challenge):

Flutter第八期 - 控件總結(jié)篇

????home: HeroDemo(),// 添加list item

import?'package:flutter/material.dart';
import?'package:flutter/scheduler.dart'?show?timeDilation;

class?HeroDemo?extends?StatefulWidget?{
??@override
??_HeroDemoState?createState()?=>?_HeroDemoState();
}

class?_HeroDemoState?extends?State<HeroDemo>?{
??List<String>?list;

??@override
??void?initState()?{
????super.initState();
????list?=?List.generate(20,?(index)?=>?"This?is?no.$index");
??}

??@override
??Widget?build(BuildContext?context)?{
????timeDilation?=?2.0;
????return?Scaffold(
??????appBar:?AppBar(
????????title:?Text('Demo1'),
??????),
??????body:?ListView.builder(
??????????itemCount:?list.length,
??????????itemBuilder:?(context,?index)?{
????????????return?ListTile(
??????????????title:?Text(list[index]),
????????????);
??????????}),
??????floatingActionButtonLocation:?FloatingActionButtonLocation.centerFloat,
??????floatingActionButton:?Hero(
????????tag:?"FloatingActionButton",
????????child:?FloatingActionButton(
??????????backgroundColor:?Colors.blue,
??????????onPressed:?()?=>?Navigator.of(context)
??????????????.push(MaterialPageRoute(builder:?(context)?=>?SecondPage())),
??????????child:?Icon(Icons.add),
????????),
??????),
????);
??}
}

class?SecondPage?extends?StatefulWidget?{
??@override
??_SecondPageState?createState()?=>?_SecondPageState();
}

class?_SecondPageState?extends?State<SecondPage>?{
??final?FocusNode?focusNode?=?FocusNode();

??@override
??Widget?build(BuildContext?context)?{
????return?Scaffold(
??????appBar:?AppBar(
????????backgroundColor:?Colors.transparent,
????????elevation:?0.0,
????????iconTheme:?IconThemeData(
??????????color:?Colors.black,
????????),
??????),
??????body:?Column(
????????crossAxisAlignment:?CrossAxisAlignment.stretch,
????????mainAxisSize:?MainAxisSize.max,
????????children:?<Widget>[
??????????ListView(
????????????shrinkWrap:?true,
????????????padding:?const?EdgeInsets.symmetric(horizontal:?20.0),
????????????children:?<Widget>[
??????????????TextField(
????????????????autofocus:?true,
????????????????focusNode:?focusNode,
????????????????maxLines:?5,
????????????????decoration:?InputDecoration.collapsed(
????????????????????hintText:?'What?do?you?want?to?add?now??'),
??????????????),
????????????],
??????????),
????????],
??????),
??????floatingActionButtonLocation:?FloatingActionButtonLocation.centerFloat,
??????floatingActionButton:?Hero(
??????????tag:?"FloatingActionButton",
??????????child:?Padding(
????????????padding:
????????????????const?EdgeInsets.only(left:?12.0,?right:?12.0,?bottom:?6.0),
????????????child:?ButtonTheme(
??????????????height:?48.0,
??????????????minWidth:?double.infinity,
??????????????child:?RaisedButton(
????????????????color:?Colors.lightBlue,
????????????????onPressed:?()?{},
????????????????elevation:?10.0,
????????????????child:?Icon(
??????????????????Icons.add,
??????????????????color:?Colors.white,
????????????????),
??????????????),
????????????),
??????????)),
????);
??}
}

????home: HideBottomBarDemo(),// 滾動(dòng)隱藏底部導(dǎo)航 動(dòng)畫(huà)

import?'package:flutter/material.dart';
import?'package:flutter/rendering.dart';

class?HideBottomBarDemo?extends?StatefulWidget?{
??@override
??_HideBottomBarDemoState?createState()?=>?_HideBottomBarDemoState();
}

class?_HideBottomBarDemoState?extends?State<HideBottomBarDemo>
????with?SingleTickerProviderStateMixin?{
??AnimationController?_animationController;
??Animation?_animation;
??ScrollController?_scrollController;

??void?_judgeScroll()?{
????if?(_scrollController.position.userScrollDirection?==
????????ScrollDirection.reverse)?{
??????_animationController.forward();
????}
????if?(_scrollController.position.userScrollDirection?==
????????ScrollDirection.forward)?{
??????_animationController.reverse();
????}
??}

??@override
??void?initState()?{
????super.initState();
????_animationController?=
????????AnimationController(vsync:?this,?duration:?Duration(milliseconds:?300));
????_animation?=?Tween(begin:?0.0,?end:?-100.0).animate(CurvedAnimation(
????????parent:?_animationController,?curve:?Curves.fastOutSlowIn));
????_scrollController?=?ScrollController(keepScrollOffset:?true)
??????..addListener(_judgeScroll);
??}

??@override
??void?dispose()?{
????//?TODO:?implement?dispose
????_animationController?.dispose();
????_scrollController..removeListener(_judgeScroll);
????//?如果銷毀ScrollController,keepScrollOffset將置空
????//?_scrollController?.dispose();
????super.dispose();
??}

??@override
??Widget?build(BuildContext?context)?{
????return?Scaffold(
??????appBar:?AppBar(
????????title:?Text('Immersive?BottomNavigationBar'),
??????),
??????body:?_buildListView(),
??????bottomNavigationBar:?_buildBottomNavigationBar(context),
????);
??}

??Widget?_buildBottomNavigationBar(BuildContext?context)?{
????return?AnimatedBuilder(
??????animation:?_animation,
??????builder:?(context,?child)?{
????????return?Container(
??????????height:?0.0,
??????????child:?Stack(
????????????overflow:?Overflow.visible,
????????????children:?<Widget>[
??????????????Positioned(
??????????????????bottom:?_animation.value,?left:?0.0,?right:?0.0,?child:?child)
????????????],
??????????),
????????);
??????},
??????child:?BottomNavigationBar(
????????items:?[
??????????BottomNavigationBarItem(icon:?Icon(Icons.title),?title:?Text("home")),
??????????BottomNavigationBarItem(icon:?Icon(Icons.title),?title:?Text("home")),
??????????BottomNavigationBarItem(icon:?Icon(Icons.title),?title:?Text("home")),
??????????BottomNavigationBarItem(icon:?Icon(Icons.title),?title:?Text("home")),
????????],
????????type:?BottomNavigationBarType.fixed,
??????),
????);
??}

??Widget?_buildListView()?=>?ListView.builder(
??????controller:?_scrollController,
??????itemBuilder:?(context,?index)?=>?ListTile(
????????????leading:?Icon(Icons.access_alarm),
????????????title:?Text("this?is?index:?$index"),
??????????));

}

????home: AudioScreen(),// 倒計(jì)時(shí) 暫時(shí)不好寫(xiě) 沒(méi)理解(官方demo需要后續(xù)去看看寫(xiě)法很巧妙)

import?'dart:async';

import?'package:flutter/material.dart';
import?'package:flutter_spinkit/flutter_spinkit.dart';

class?AudioScreen?extends?StatefulWidget?{
??@override
??_AudioScreenState?createState()?=>?_AudioScreenState();
}

class?_AudioScreenState?extends?State<AudioScreen>?{
??Stopwatch?stopwatch?=?Stopwatch();

??@override
??Widget?build(BuildContext?context)?{
????return?Scaffold(
??????body:?Container(
????????color:?Colors.orangeAccent.withOpacity(0.2),
????????child:?Column(
??????????mainAxisAlignment:?MainAxisAlignment.center,
??????????children:?<Widget>[
????????????_buildRecordingStatus(),
????????????_buildTimerText(),
????????????_buildButtonRow(context),
??????????],
????????),
??????),
????);
??}

??void?_stopButtonPressed()?{
????setState(()?{
??????stopwatch
????????..stop()
????????..reset();
????});
??}

??void?_rightButtonPressed()?{
????setState(()?{
??????if?(stopwatch.isRunning)?{
????????stopwatch.stop();
??????}?else?{
????????stopwatch.start();
??????}
????});
??}

??Widget?_buildTimerText()?{
????return?Container(
????????height:?200.0,
????????child:?Center(
??????????child:?TimerText(stopwatch:?stopwatch),
????????));
??}

??Widget?_buildRecordingStatus()?{
????return?Container(
????????height:?100.0,
????????width:?100.0,
????????child:?stopwatch.isRunning
??????????????Center(
????????????????child:?SpinKitWave(
????????????????????color:?Colors.black87.withOpacity(0.7),
????????????????????type:?SpinKitWaveType.start),
??????????????)
????????????:?Image.asset("assets/recorder.png"));
??}

??Widget?_buildButtonRow(BuildContext?context)?{
????return?Row(children:?<Widget>[
??????_buildButton(_stopButtonPressed,?Colors.redAccent,?context,?Icons.stop),
??????_buildButton(_rightButtonPressed,?Colors.blueAccent,?context,
??????????stopwatch.isRunning???Icons.pause?:?Icons.play_arrow),
????]);
??}

??Widget?_buildButton(
??????VoidCallback?callback,?Color?color,?BuildContext?context,?IconData?icon)?{
????Size?size?=?MediaQuery.of(context).size;
????return?Container(
????????width:?size.width?*?0.5,
????????alignment:?Alignment.center,
????????child:?RaisedButton(
??????????elevation:?0.0,
??????????shape:
??????????????RoundedRectangleBorder(borderRadius:?BorderRadius.circular(36.0)),
??????????color:?color,
??????????onPressed:?callback,
??????????child:?Container(
????????????width:?size.width?*?0.5?-?80.0,
????????????height:?MediaQuery.of(context).size.width?*?0.15,
????????????child:?Icon(
??????????????icon,
??????????????color:?Colors.white,
??????????????size:?32.0,
????????????),
??????????),
????????));
??}
}

class?TimerText?extends?StatefulWidget?{
??TimerText({this.stopwatch});
??final?Stopwatch?stopwatch;

??TimerTextState?createState()?=>?TimerTextState(stopwatch:?stopwatch);
}

class?TimerTextState?extends?State<TimerText>?{
??Timer?timer;
??final?Stopwatch?stopwatch;

??TimerTextState({this.stopwatch})?{
????timer?=?Timer.periodic(Duration(milliseconds:?30),?callback);
??}

??void?callback(Timer?timer)?{
????if?(stopwatch.isRunning)?{
??????setState(()?{});
????}
??}

??@override
??Widget?build(BuildContext?context)?{
????final?double?width?=?MediaQuery.of(context).size.width;
????final?TextStyle?timerTextStyle?=?const?TextStyle(
??????fontSize:?60.0,
??????fontFamily:?"Open?Sans",
??????fontWeight:?FontWeight.w300,
??????color:?Colors.black87,
????);
????List<String>?formattedTime?=
????????TimerTextFormatter.format(stopwatch.elapsedMilliseconds);
????return?Row(
??????mainAxisAlignment:?MainAxisAlignment.center,
??????children:?<Widget>[
????????Container(
??????????child:?Text(
????????????"${formattedTime[0]}:",
????????????style:?timerTextStyle,
??????????),
??????????width:?width?/?4.0,
????????),
????????Container(
??????????child:?Text(
????????????"${formattedTime[1]}:",
????????????style:?timerTextStyle,
??????????),
??????????width:?width?/?4.1,
????????),
????????Container(
??????????child:?Text(
????????????"${formattedTime[2]}",
????????????style:?timerTextStyle,
??????????),
??????????width:?width?/?4.6,
????????),
??????],
????);
??}
}

class?TimerTextFormatter?{
??static?List<String>?format(int?milliseconds)?{
????int?hundreds?=?(milliseconds?/?10).truncate();
????int?seconds?=?(hundreds?/?100).truncate();
????int?minutes?=?(seconds?/?60).truncate();

????String?minutesStr?=?(minutes?%?60).toString().padLeft(2,?'0');
????String?secondsStr?=?(seconds?%?60).toString().padLeft(2,?'0');
????String?hundredsStr?=?(hundreds?%?100).toString().padLeft(2,?'0');

????return?[minutesStr,?secondsStr,?hundredsStr];
//????return?"$minutesStr:$secondsStr:$hundredsStr";
??}
}

????home: ImScreen(),// IM 聊天 這里需要注意的是listview滾動(dòng)會(huì)因?yàn)閕tem的增加卡頓,目前布局這塊沒(méi)有好的方案,期待官方。

import?'dart:async';

import?'package:flutter/material.dart';

class?ImScreen?extends?StatefulWidget?{
??@override
??_ImScreenState?createState()?=>?_ImScreenState();
}

class?_ImScreenState?extends?State<ImScreen>?{
??StreamController?_messageController;
??TextEditingController?_textController;
??List?_myMessages;
??final?_myName?=?"Vadaski";

??@override
??void?initState()?{
????//?TODO:?implement?initState
????super.initState();
????_messageController?=?StreamController();
????_textController?=?TextEditingController();
????_myMessages?=?List();
??}

??@override
??void?dispose()?{
????_textController.dispose();
????_messageController.close();
????super.dispose();
??}

??@override
??Widget?build(BuildContext?context)?{
????return?Scaffold(
??????appBar:?AppBar(
????????title:?Text('IM?Challenge'),
????????centerTitle:?true,
??????),
??????body:?SafeArea(
????????child:?Column(
??????????children:?<Widget>[
????????????Flexible(
????????????????child:?ListView.builder(
????????????????????reverse:?true,
????????????????????itemCount:?_myMessages.length,
????????????????????itemBuilder:?(context,?index)?{
??????????????????????return?_buildMessageWidget(_myMessages[index],?context);
????????????????????})),
????????????Divider(
??????????????height:?1.0,
????????????),
????????????_buildInputWidget(context),
??????????],
????????),
??????),
????);
??}

??Widget?_buildInputWidget(BuildContext?context)?{
????return?SizedBox(
??????child:?Padding(
????????padding:?const?EdgeInsets.only(left:?8.0,?right:?8.0),
????????child:?Row(
??????????children:?<Widget>[
????????????Flexible(
????????????????child:?TextField(
??????????????decoration:
??????????????????InputDecoration.collapsed(hintText:?"Send?your?message"),
??????????????controller:?_textController,
??????????????onChanged:?onMessageChanged,
??????????????onSubmitted:?onMessageSubmit,
????????????)),
????????????Container(
??????????????margin:?const?EdgeInsets.symmetric(horizontal:?4.0),
??????????????child:?StreamBuilder(
????????????????initialData:?"",
????????????????stream:?_messageController.stream,
????????????????builder:?(context,?snapshot)?{
??????????????????return?IconButton(
????????????????????icon:?Icon(
??????????????????????Icons.send,
??????????????????????color:?snapshot.data?==?""
????????????????????????????Colors.grey
??????????????????????????:?Theme.of(context).accentColor,
????????????????????),
????????????????????onPressed:?()?=>?onMessageSubmit(_textController.text),
??????????????????);
????????????????},
??????????????),
????????????)
??????????],
????????),
??????),
????);
??}

??Widget?_buildMessageWidget(String?text,?BuildContext?context)?{
????return?Container(
??????margin:?const?EdgeInsets.symmetric(vertical:?10.0),
??????width:?MediaQuery.of(context).size.width?/?2,
??????child:?Row(
????????crossAxisAlignment:?CrossAxisAlignment.start,
????????children:?<Widget>[
??????????SizedBox(
????????????width:?MediaQuery.of(context).size.width?/?4,
??????????),
??????????Expanded(
????????????child:?Column(
??????????????crossAxisAlignment:?CrossAxisAlignment.end,
??????????????children:?<Widget>[
????????????????Text(_myName,?style:?Theme.of(context).textTheme.subhead),
????????????????Container(
??????????????????decoration:?BoxDecoration(
??????????????????????borderRadius:?BorderRadius.circular(12.0),
??????????????????????color:?Colors.blue.withOpacity(0.2)),
??????????????????margin:?const?EdgeInsets.only(top:?5.0),
??????????????????child:?Padding(
????????????????????padding:?const?EdgeInsets.all(8.0),
????????????????????child:?Text(
??????????????????????text,
??????????????????????overflow:?TextOverflow.fade,
??????????????????????softWrap:?true,
????????????????????),
??????????????????),
????????????????)
??????????????],
????????????),
??????????),
??????????Container(
????????????margin:?const?EdgeInsets.only(right:?16.0,?left:?8.0),
????????????child:?CircleAvatar(
??????????????child:?Text(_myName[0]),
????????????),
??????????),
????????],
??????),
????);
??}

??onMessageChanged(String?message)?{
????_messageController.sink.add(message);
??}

??onMessageSubmit(String?message)?{
????_textController.clear();
????if?(message?!=?"")?{
??????setState(()?{
????????_myMessages.insert(0,?message);
??????});
????}
????onMessageChanged("");
??}
}

????home: RotatingScreen(),//

import 'package:flutter/material.dart';

import '../widgets/rotating_bar.dart';

class RotatingScreen extends StatelessWidget {
?@override
?Widget build(BuildContext context) {
? ?final size = MediaQuery.of(context).size;

? ?return Scaffold(
? ? ? ?body: Stack(
? ? ?children: <Widget>[
? ? ? ?Positioned(
? ? ? ? ?left: size.width / 5,
? ? ? ? ?top: size.height / 3,
? ? ? ? ?child: RotatingBar(
? ? ? ? ? ?getBackCenter: true,
? ? ? ? ? ?dx: size.width / 5,
? ? ? ? ? ?dy: size.height / 3,
? ? ? ? ? ?style: Style.Touch,
? ? ? ? ? ?getAngle: (angle) {
? ? ? ? ? ? ?print(angle);
? ? ? ? ? ?},
? ? ? ? ?),
? ? ? ?)
? ? ?],
? ?));
?}
}

????home: ScrollBackToTop(),// 滾動(dòng)到頂部 這個(gè)比較常用

import 'package:flutter/material.dart';

class ScrollBackToTop extends StatefulWidget {
?@override
?_ScrollBackToTopState createState() => _ScrollBackToTopState();
}

class _ScrollBackToTopState extends State<ScrollBackToTop>
? ?with SingleTickerProviderStateMixin {
?ScrollController _controller;

?@override
?void initState() {
? ?super.initState();
? ?_controller = ScrollController();
?}

?@override
?void dispose() {
? ?_controller.dispose();
? ?super.dispose();
?}

?@override
?Widget build(BuildContext context) {
? ?return Scaffold(
? ? ?appBar: AppBar(
? ? ? ?title: Text('Scroll Back To Top Demo'),
? ? ? ?centerTitle: true,
? ? ?),
? ? ?body: ListView.builder(
? ? ? ? ?controller: _controller,
? ? ? ? ?itemCount: 100,
? ? ? ? ?itemBuilder: (context, index) {
? ? ? ? ? ?return ListTile(
? ? ? ? ? ? ?title: Center(
? ? ? ? ? ? ? ? ?child: Text(
? ? ? ? ? ? ? ?'This is no $index',
? ? ? ? ? ? ? ?style: TextStyle(fontSize: 24),
? ? ? ? ? ? ?)),
? ? ? ? ? ?);
? ? ? ? ?}),
? ? ?floatingActionButton: FloatingActionButton(
? ? ? ?onPressed: backToTop,
? ? ? ?child: Icon(Icons.vertical_align_top),
? ? ?),
? ?);
?}

?backToTop() {
? ?if (_controller.offset != 0)
? ? ?_controller.animateTo(
? ? ? ?0,
? ? ? ?duration: Duration(milliseconds: 500),
? ? ? ?curve: Curves.easeIn,
? ? ?);
?}
}

????5.animation_demo(總結(jié)一下各種目前能用的場(chǎng)景化動(dòng)畫(huà)github:https://github.com/geeklx/flutter_app2/tree/master/app2/animation_demo):由于篇幅有限代碼就不說(shuō)了,地址附上?Flutter第八期 - 控件總結(jié)篇?Flutter第八期 - 控件總結(jié)篇

????6.beaytiful_search_bar_demo(搜索欄):https://github.com/geeklx/flutter_app2/tree/master/app2/beaytiful_search_bar_demo

Flutter第八期 - 控件總結(jié)篇

import 'package:flutter/material.dart';
import 'asset.dart';

class SearchBarDemo extends StatefulWidget {
?@override
?_SearchBarDemoState createState() => _SearchBarDemoState();
}

class _SearchBarDemoState extends State<SearchBarDemo> {
?@override
?Widget build(BuildContext context) {
? ?return Scaffold(
? ? ?appBar: AppBar(
? ? ? ?title: Text('SearchBarDemo'),
? ? ? ?actions: <Widget>[
? ? ? ? ?IconButton(
? ? ? ? ? ? ?icon: Icon(Icons.search),
? ? ? ? ? ? ?onPressed: () =>
? ? ? ? ? ? ? ? ?showSearch(context: context, delegate: SearchBarDelegate())),
? ? ? ?],
? ? ?),
? ?);
?}
}

const searchList = [
?"ChengDu",
?"ShangHai",
?"BeiJing",
?"TianJing",
?"NanJing",
?"ShenZheng"
];

const recentSuggest = [
?"suggest1",
?"suggest2"
];

class SearchBarDelegate extends SearchDelegate<String> {
?@override
?List<Widget> buildActions(BuildContext context) {
? ?return [IconButton(icon: Icon(Icons.clear), onPressed: () => query = "")];
?}

?@override
?Widget buildLeading(BuildContext context) {
? ?return IconButton(
? ? ? ?icon: AnimatedIcon(
? ? ? ? ? ?icon: AnimatedIcons.menu_arrow, progress: transitionAnimation),
? ? ? ?onPressed: () => close(context, null));
?}

?@override
?Widget buildResults(BuildContext context) {
? ?return Center(child: Container(
? ? ?width: 100.0,
? ? ?height: 100.0,
? ? ?child: Card(
? ? ? ?color: Colors.redAccent,
? ? ? ?child: Center(
? ? ? ? ?child: Text(query),
? ? ? ?),
? ? ?),
? ?),);
?}

?@override
?Widget buildSuggestions(BuildContext context) {
? ?final suggestionList = query.isEmpty
? ? ? ?? recentSuggest
? ? ? ?: searchList.where((input) => input.startsWith(query)).toList();
? ?return ListView.builder(
? ? ? ?itemCount: suggestionList.length,
? ? ? ?itemBuilder: (context, index) => ListTile(

? ? ? ? ?onTap: (){
? ? ? ? ? ?query = suggestionList[index];
? ? ? ? ? ?showResults(context);},

? ? ? ? ? ? ?title: RichText(
? ? ? ? ? ? ? ? ?text: TextSpan(
? ? ? ? ? ? ? ? ? ? ?text: suggestionList[index].substring(0, query.length),
? ? ? ? ? ? ? ? ? ? ?style: TextStyle(
? ? ? ? ? ? ? ? ? ? ? ? ?color: Colors.black, fontWeight: FontWeight.bold),
? ? ? ? ? ? ? ? ? ? ?children: [
? ? ? ? ? ? ? ? ? ?TextSpan(
? ? ? ? ? ? ? ? ? ? ? ?text: suggestionList[index].substring(query.length),
? ? ? ? ? ? ? ? ? ? ? ?style: TextStyle(color: Colors.grey))
? ? ? ? ? ? ? ? ?])),
? ? ? ? ? ?));
?}
}

????7.bloc_provider_pattern(監(jiān)聽(tīng)私有方法調(diào)用寫(xiě)法):https://github.com/geeklx/flutter_app2/tree/master/app2/bloc_provider_pattern

Flutter第八期 - 控件總結(jié)篇

import 'dart:async';

import './bloc_base.dart';

class IncrementBloc implements BlocBase {
?int _counter;

?StreamController<int> _counterPipe = StreamController<int>();
?Stream<int> get outCounter => _counterPipe.stream;

?IncrementBloc() {
? ?_counter = 0;
? ?//_counterPipe 用于StreamBuilder,已經(jīng)自動(dòng)加了listen
?}

?incrementCounter() {
? ?_counter = _counter + 1;
? ?_counterPipe.sink.add(_counter);
?}

?void dispose() {
? ?print('bloc disposed!');
? ?_counterPipe.close();
?}
}


import 'package:flutter/material.dart';

// Generic Interface for all BLoCs
abstract class BlocBase {
?void dispose();
}

// Generic BLoC provider
class BlocProvider<T extends BlocBase> extends StatefulWidget {
?BlocProvider({
? ?Key key,
? ?@required this.child,
? ?@required this.bloc,
?}) : super(key: key);

?final T bloc;
?final Widget child;

?@override
?_BlocProviderState<T> createState() => _BlocProviderState<T>();

?static T of<T extends BlocBase>(BuildContext context) {
? ?final type = _typeOf<BlocProvider<T>>();
? ?BlocProvider<T> provider = context.ancestorWidgetOfExactType(type);
? ?return provider.bloc;
?}

?static Type _typeOf<T>() => T;
}

class _BlocProviderState<T> extends State<BlocProvider<BlocBase>> {
?@override
?void dispose() {
? ?widget.bloc.dispose();
? ?super.dispose();
?}

?@override
?Widget build(BuildContext context) {
? ?return widget.child;
?}
}
//EOP

????8.bottom_appbar_demo(底部導(dǎo)航 比較常用的base寫(xiě)法):https://github.com/geeklx/flutter_app2/tree/master/app2/bottom_appbar_demo

Flutter第八期 - 控件總結(jié)篇

import 'package:flutter/material.dart';

class EachView extends StatefulWidget {
?String _title;
?EachView(this._title);
?@override
?_EachViewState createState() => _EachViewState();
}

class _EachViewState extends State<EachView> {
?@override
?Widget build(BuildContext context) {
? ?return Scaffold(
? ? ?appBar: AppBar(title: Text(widget._title),),
? ?);
?}
}

import 'package:flutter/material.dart';
import 'each_view.dart';

class BottomAppBarDemo extends StatefulWidget {
?@override
?_BottomAppBarDemoState createState() => _BottomAppBarDemoState();
}

class _BottomAppBarDemoState extends State<BottomAppBarDemo> {
?List<Widget> _eachView;
?int _index = 0;

?@override
?void initState() {
? ?// TODO: implement initState
? ?super.initState();
? ?_eachView = List();
? ?_eachView..add(EachView('home'))..add(EachView('me'));
?}

?@override
?Widget build(BuildContext context) {
? ?return new Scaffold(
? ? ?body: _eachView[_index],
? ? ?floatingActionButton: new FloatingActionButton(
? ? ? ?onPressed: () {
? ? ? ? ?Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context){
? ? ? ? ? ?return EachView('New Page');
? ? ? ? ?}));
? ? ? ?},
? ? ? ?tooltip: 'Increment',
? ? ? ?child: new Icon(Icons.add),
? ? ?), // T
? ? ?floatingActionButtonLocation:
? ? ? ? ?FloatingActionButtonLocation.centerDocked, // his
? ? ?bottomNavigationBar: BottomAppBar(
? ? ? ?color: Colors.lightBlue,
? ? ? ?shape: CircularNotchedRectangle(),
? ? ? ?child: Row(
? ? ? ? ?mainAxisSize: MainAxisSize.max,
? ? ? ? ?mainAxisAlignment: MainAxisAlignment.spaceAround,
? ? ? ? ?children: <Widget>[
? ? ? ? ? ?IconButton(
? ? ? ? ? ? ?icon: Icon(Icons.near_me),
? ? ? ? ? ? ?color: Colors.white,
? ? ? ? ? ? ?onPressed: () {
? ? ? ? ? ? ? ?setState(() {
? ? ? ? ? ? ? ? ?_index = 0;
? ? ? ? ? ? ? ?});
? ? ? ? ? ? ?},
? ? ? ? ? ?),
? ? ? ? ? ?IconButton(
? ? ? ? ? ? ?icon: Icon(Icons.edit_location),
? ? ? ? ? ? ?color: Colors.white,
? ? ? ? ? ? ?onPressed: () {
? ? ? ? ? ? ? ?setState(() {
? ? ? ? ? ? ? ? ?_index = 1;
? ? ? ? ? ? ? ?});
? ? ? ? ? ? ?},
? ? ? ? ? ?),
? ? ? ? ?],
? ? ? ?),
? ? ?),
? ?);
?}
}

????9.chip_demo(勾選擇view的各種效果):https://github.com/geeklx/flutter_app2/tree/master/app2/chip_demo

Flutter第八期 - 控件總結(jié)篇

import 'package:chip_demo/input_chip.dart';
/**
* 請(qǐng)通過(guò)切換home的注釋分別查看
*/
import 'package:flutter/material.dart';

import 'choice_chip.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
?@override
?Widget build(BuildContext context) {
? ?return new MaterialApp(
? ? ?title: 'Flutter Demo',
? ? ?theme: new ThemeData.light(),
// ? ? ?home: ChipDemo(),
// ? ? ?home: ActionChipDemo(),
// ? ? ?home: FilterChipDemo(),// 勾選狀態(tài)
// ? ? ?home: ChoiceChipDemo(), // 選中狀態(tài) 常用的
? ? ?home: InputChipDemo(),
? ?);
?}
}

????10.custom_router_transition(標(biāo)準(zhǔn)的路由寫(xiě)法):https://github.com/geeklx/flutter_app2/tree/master/app2/custom_router_transition

/**
* Navigator.of(context).push自定義的route
*/
import 'package:flutter/material.dart';
import 'custome_router.dart';

class FirstPage extends StatelessWidget {
?@override
?Widget build(BuildContext context) {
? ?return Scaffold(
? ? ?backgroundColor: Colors.blue,
? ? ?appBar: AppBar(
? ? ? ?title: Text(
? ? ? ? ?'FirstPage',
? ? ? ? ?style: TextStyle(fontSize: 36.0),
? ? ? ?),
? ? ? ?elevation: 0.0,
? ? ?),
? ? ?body: Center(
? ? ? ?child: MaterialButton(
? ? ? ? ? ?child: Icon(
? ? ? ? ? ? ?Icons.navigate_next,
? ? ? ? ? ? ?color: Colors.white,
? ? ? ? ? ? ?size: 64.0,
? ? ? ? ? ?),
? ? ? ? ? ?onPressed: () =>
? ? ? ? ? ? ? ?Navigator.of(context).push(
? ? ? ? ? ? ? ? ? ?CustomRoute(SecondPage()))),
? ? ?),
? ?);
?}
}

class SecondPage extends StatelessWidget {
?@override
?Widget build(BuildContext context) {
? ?return Scaffold(
? ? ?backgroundColor: Colors.pinkAccent,
? ? ?appBar: AppBar(
? ? ? ?title: Text('SecondPage',style: TextStyle(fontSize: 36.0),),
? ? ? ?backgroundColor: Colors.pinkAccent,
? ? ? ?leading: Container(),
? ? ? ?elevation: 0.0,
? ? ?),
? ? ?body: Center(
? ? ? ?child: MaterialButton(
? ? ? ? ? ?child: Icon(
? ? ? ? ? ? ?Icons.navigate_before,
? ? ? ? ? ? ?color: Colors.white,
? ? ? ? ? ? ?size: 64.0,
? ? ? ? ? ?),
? ? ? ? ? ?onPressed: () => Navigator.of(context).pop()),
? ? ?),
? ?);
?}
}


提供幾個(gè)過(guò)度動(dòng)畫(huà)
/**
* 通過(guò)自定義transitionsBuilder實(shí)現(xiàn)路由過(guò)渡動(dòng)畫(huà)
*
* 請(qǐng)切換不同注釋分別查看
*/
import 'package:flutter/material.dart';

class CustomRoute extends PageRouteBuilder {
?final Widget widget;
?CustomRoute(this.widget)
? ? ?: super(
? ? ? ? ?transitionDuration: const Duration(seconds: 2),
? ? ? ? ?pageBuilder: (BuildContext context, Animation<double> animation,
? ? ? ? ? ? ?Animation<double> secondaryAnimation) {
? ? ? ? ? ?return widget;
? ? ? ? ?},
? ? ? ? ?transitionsBuilder: (BuildContext context,
? ? ? ? ? ? ?Animation<double> animation,
? ? ? ? ? ? ?Animation<double> secondaryAnimation,
? ? ? ? ? ? ?Widget child) {
? ? ? ? ? ?//淡出過(guò)渡路由
? ? ? ? ?return FadeTransition(
? ? ? ? ? ? ?opacity: Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
? ? ? ? ? ? ? ? ?parent: animation, curve: Curves.fastOutSlowIn)),
? ? ? ? ? ? ?child: child,
? ? ? ? ? ? ?);

? ? ? ? ? ?//比例轉(zhuǎn)換路由
// ? ? ? ? ?return ScaleTransition(
// ? ? ? ? ? ?scale: Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
// ? ? ? ? ? ? ? ?parent: animation, curve: Curves.fastOutSlowIn)),
// ? ? ? ? ? ?child: child,
// ? ? ? ? ? ?);

? ? ? ? ? ?//旋轉(zhuǎn)+比例轉(zhuǎn)換路由
// ? ? ? ? ? ?return RotationTransition(
// ? ? ? ? ? ? ?turns: Tween(begin: -1.0, end: 1.0).animate(CurvedAnimation(
// ? ? ? ? ? ? ? ? ?parent: animation, curve: Curves.fastOutSlowIn)),
// ? ? ? ? ? ? ?child: ScaleTransition(
// ? ? ? ? ? ? ? ?scale: Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
// ? ? ? ? ? ? ? ? ? ?parent: animation, curve: Curves.fastOutSlowIn)),
// ? ? ? ? ? ? ? ?child: child,
// ? ? ? ? ? ? ?),
// ? ? ? ? ? ?);

? ? ? ? ? ?//幻燈片路由
// ? ? ? ? ? ?return SlideTransition(
// ? ? ? ? ? ? ?position:
// ? ? ? ? ? ? ? ? ?Tween<Offset>(begin: Offset(0.0, -1.0), end: Offset(0.0, 0.0))
// ? ? ? ? ? ? ? ? ? ? ?.animate(CurvedAnimation(
// ? ? ? ? ? ? ? ? ? ? ? ? ?parent: animation, curve: Curves.fastOutSlowIn)),
// ? ? ? ? ? ? ?child: child,
// ? ? ? ? ? ?);
? ? ? ? ?},
? ? ? ?);
}

????11.event_bus_demo(利用eventbus同步頁(yè)面數(shù)據(jù)局部刷新 比較常用):https://github.com/geeklx/flutter_app2/tree/master/app2/event_bus_demo

import 'package:flutter/material.dart';
import 'tools/bus.dart';
import 'events/count_events.dart';
import 'sceeens/first_screen.dart';

void main(){
?runApp(App());
?behaviorBus.fire(CountEvent(0));
}

class App extends StatelessWidget {
?@override
?Widget build(BuildContext context) {
? ?return MaterialApp(
? ? ?title: 'Flutter Demo',
? ? ?theme: ThemeData.dark(),
? ? ?home: FirstScreen(),

? ?);
?}
}

????12.expansion_demo(級(jí)聯(lián)listview 目前這塊官方?jīng)]有demo 只找到郭神的一個(gè)寫(xiě)法 視圖刷新很卡 目前也只能這樣 后續(xù)跟進(jìn)):https://github.com/geeklx/flutter_app2/tree/master/app2/expansion_demo

Flutter第八期 - 控件總結(jié)篇

1.
/**
?*最基礎(chǔ)的展開(kāi)小部件expansion?tile
?*?用法很簡(jiǎn)單,將需要被展開(kāi)的部件放在children中即可
?*?其他用法和list?tile很相似
?*?當(dāng)expansion?tile?被展開(kāi)時(shí),我們可以看到background?color
?*?會(huì)進(jìn)行一個(gè)transition動(dòng)畫(huà)進(jìn)行過(guò)渡
?*?expansion?tile還有一個(gè)trailing屬性,代表右邊的小箭頭
?*?可以自行替換
?*?initiallyExpanded代表最初的狀態(tài)是否被展開(kāi)
?*?默認(rèn)為false,也就是不展開(kāi)
?*
?*?當(dāng)一個(gè)list?view中由多個(gè)expansion?tile的時(shí)候
?*?需要給每一個(gè)expansion?tile指定唯一的[PageStorageKey]
?*?以保證在滑動(dòng)的過(guò)程中,能夠記住expansion?tile的開(kāi)關(guān)狀態(tài)
?*/

import?'package:flutter/material.dart';

class?ExpansionTileDemo?extends?StatelessWidget?{
??@override
??Widget?build(BuildContext?context)?{
????return?Scaffold(
??????appBar:?AppBar(title:?Text('expansion?tile?demo'),),
??????body:?Center(
????????child:?ExpansionTile(
????????????title:?Text('Expansion?Tile'),
????????????leading:?Icon(Icons.ac_unit),
????????????backgroundColor:?Colors.white12,
????????????children:?<Widget>[
??????????????ListTile(
????????????????title:?Text('list?tile'),
????????????????subtitle:?Text('subtitle'),
??????????????),
????????????],
//??????????initiallyExpanded:?true,
????????),
??????),
????);
??}
}

2.
/**
?*??說(shuō)實(shí)話,我覺(jué)得expansion?panel?list一點(diǎn)都不好用
?*??所以不想寫(xiě)注釋。
?*??這里樣例代碼來(lái)自于flutter開(kāi)發(fā)者
?*??他會(huì)經(jīng)常更新一些flutter教程,寫(xiě)的挺不錯(cuò)的,有興趣自己去看看吧
?*??https://mp.weixin.qq.com/s/Qv08V42LgEr8IATUSfVVHg
?*
?*??需要注意幾點(diǎn):
?*??ExpansionPanelList必須放在可滑動(dòng)組件中使用
?*??ExpansionPanel只能在ExpansionPanelList中使用
?*??除了ExpansionPanel還有一種特殊的ExpansionPanelRadio
?*??也是只能在ExpansionPanelList中使用的
?*/

import?'package:flutter/material.dart';

class?ExpansionPanelListDemo?extends?StatefulWidget?{
??@override
??_ExpansionPanelListDemoState?createState()?=>?_ExpansionPanelListDemoState();
}

class?_ExpansionPanelListDemoState?extends?State<ExpansionPanelListDemo>?{
??var?currentPanelIndex?=?-1;

??List<int>?mList;
??//用來(lái)保存expansionPanel的狀態(tài)
??List<ExpandStateBean>?expandStateList;

??_ExpansionPanelListDemoState()?{
????mList?=?new?List();
????expandStateList?=?new?List();
????for?(int?i?=?0;?i?<?10;?i++)?{
??????mList.add(i);
??????expandStateList.add(ExpandStateBean(i,?false));
????}
??}

??_setCurrentIndex(int?index,?isExpand)?{
????setState(()?{
??????expandStateList.forEach((item)?{
????????if?(item.index?==?index)?{
??????????item.isOpen?=?!isExpand;
????????}
??????});
????});
??}

??@override
??Widget?build(BuildContext?context)?{
????return?Scaffold(
????????appBar:?AppBar(
??????????title:?Text("expansion?panel?list"),
????????),
????????body:?SingleChildScrollView(
??????????child:?ExpansionPanelList(
????????????expansionCallback:?(index,?bol)?{
??????????????_setCurrentIndex(index,?bol);
????????????},
????????????children:?mList.map((index)?{
??????????????return?new?ExpansionPanel(
????????????????headerBuilder:?(context,?isExpanded)?{
??????????????????return?new?ListTile(
????????????????????title:?new?Text('This?is?NO.?$index'),
??????????????????);
????????????????},
????????????????body:?ListTile(
??????????????????title:?Text('expansion?no.$index'),
????????????????),
????????????????isExpanded:?expandStateList[index].isOpen,
??????????????);
????????????}).toList(),
??????????),
????????));
??}
}

class?ExpandStateBean?{
??var?isOpen;
??var?index;
??ExpandStateBean(this.index,?this.isOpen);
}

????13.flutter_bottomnavigationbar(底部導(dǎo)航標(biāo)準(zhǔn)寫(xiě)法支持?;睿篽ttps://github.com/geeklx/flutter_app2/tree/master/app2/flutter_bottomnavigationbar

Flutter第八期 - 控件總結(jié)篇

1.
import?'package:flutter/material.dart';

class?AirPlayScreen?extends?StatefulWidget?{
??@override
??_AirPlayScreenState?createState()?=>?_AirPlayScreenState();
}

class?_AirPlayScreenState?extends?State<AirPlayScreen>
????with?AutomaticKeepAliveClientMixin?{
??@override
??//?TODO:?implement?wantKeepAlive
??bool?get?wantKeepAlive?=>?true;

??int?_counter?=?0;

??void?_incrementCounter()?{
????setState(()?{
??????_counter++;
????});
??}

??@override
??Widget?build(BuildContext?context)?{
????return?Scaffold(
??????appBar:?AppBar(
????????title:?Text('AirPlayScreen'),
??????),
??????body:?new?Center(
????????child:?new?Column(
??????????mainAxisAlignment:?MainAxisAlignment.center,
??????????children:?<Widget>[
????????????new?Text(
??????????????'You?have?pushed?the?button?this?many?times:',
????????????),
????????????new?Text(
??????????????'$_counter',
??????????????style:?Theme.of(context).textTheme.display1,
????????????),
??????????],
????????),
??????),
??????floatingActionButton:?new?FloatingActionButton(
????????onPressed:?_incrementCounter,
????????tooltip:?'Increment',
????????child:?new?Icon(Icons.add),
??????),
????);
??}
}

2.
import?'package:flutter/material.dart';
import?'package:flutter_bottomnavigationbar/pages_keep_alive/airplay_screen.dart';
import?'package:flutter_bottomnavigationbar/pages_keep_alive/email_screen.dart';
import?'package:flutter_bottomnavigationbar/pages_keep_alive/home_screen.dart';
import?'package:flutter_bottomnavigationbar/pages_keep_alive/pages_screen.dart';

class?NavigationKeepAlive?extends?StatefulWidget?{
??@override
??_NavigationKeepAliveState?createState()?=>?_NavigationKeepAliveState();
}

class?_NavigationKeepAliveState?extends?State<NavigationKeepAlive>
????with?SingleTickerProviderStateMixin?{

??final?_bottomNavigationColor?=?Colors.blue;
??int?_currentIndex?=?0;
??var?_controller?=?PageController(
????initialPage:?0,
??);

??@override
??void?dispose()?{
????super.dispose();
????_controller.dispose();
??}

??@override
??Widget?build(BuildContext?context)?{
????return?Scaffold(
??????body:?PageView(
????????controller:?_controller,
????????children:?<Widget>[
??????????AirPlayScreen(),
??????????EmailScreen(),
??????????HomeScreen(),
??????????PagesScreen()
????????],
????????physics:?NeverScrollableScrollPhysics(),
??????),
??????bottomNavigationBar:?BottomNavigationBar(
????????currentIndex:?_currentIndex,
//??????????onTap:?(index)=>?_controller.animateToPage(index,?duration:?Duration(milliseconds:?500),?curve:?Curves.fastOutSlowIn),
????????onTap:?(index)?{
??????????_controller.jumpToPage(index);
??????????setState(()?{
????????????_currentIndex?=?index;
??????????});
????????},
????????type:?BottomNavigationBarType.fixed,
????????items:?[
??????????BottomNavigationBarItem(
??????????????icon:?Icon(
????????????????Icons.home,
????????????????color:?_bottomNavigationColor,
??????????????),
??????????????title:?Text(
????????????????'HOME',
????????????????style:?TextStyle(color:?_bottomNavigationColor),
??????????????)),
??????????BottomNavigationBarItem(
??????????????icon:?Icon(
????????????????Icons.email,
????????????????color:?_bottomNavigationColor,
??????????????),
??????????????title:?Text(
????????????????'Email',
????????????????style:?TextStyle(color:?_bottomNavigationColor),
??????????????)),
??????????BottomNavigationBarItem(
??????????????icon:?Icon(
????????????????Icons.pages,
????????????????color:?_bottomNavigationColor,
??????????????),
??????????????title:?Text(
????????????????'PAGES',
????????????????style:?TextStyle(color:?_bottomNavigationColor),
??????????????)),
??????????BottomNavigationBarItem(
??????????????icon:?Icon(
????????????????Icons.airplay,
????????????????color:?_bottomNavigationColor

文章標(biāo)題:Flutter第八期-控件總結(jié)篇
網(wǎng)站鏈接:http://muchs.cn/article42/gdechc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、商城網(wǎng)站網(wǎng)站內(nèi)鏈、企業(yè)建站、全網(wǎng)營(yíng)銷推廣網(wǎng)站收錄

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)