当前位置:   article > 正文

40个flutter入门实例详解(七)_flutter_foreground_task

flutter_foreground_task

35.监听滚动事件

  1. class ScrollControllerTestRoute extends StatefulWidget {
  2. @override
  3. ScrollControllerTestRouteState createState() {
  4. return new ScrollControllerTestRouteState();
  5. }
  6. }
  7. class ScrollControllerTestRouteState extends State<ScrollControllerTestRoute> {
  8. ScrollController _controller = new ScrollController();
  9. bool showToTopBtn = false; //是否显示“返回到顶部”按钮
  10. @override
  11. void initState() {
  12. super.initState();
  13. //监听滚动事件,打印滚动位置
  14. _controller.addListener(() {
  15. print(_controller.offset); //打印滚动位置
  16. //当偏移量小于1000像素,不显示按钮
  17. //这里后面之所以&&showToTopBtn,是因为可以通过判断它是truefalse省得不断地调用setState,影响性能
  18. if (_controller.offset < 1000 && showToTopBtn) {
  19. setState(() {
  20. showToTopBtn = false;
  21. });
  22. //当偏移量大于等于1000像素,显示按钮
  23. //&&showToTopBtn的理由同上
  24. } else if (_controller.offset >= 1000 && showToTopBtn == false) {
  25. setState(() {
  26. showToTopBtn = true;
  27. });
  28. }
  29. });
  30. }
  31. @override
  32. void dispose() {
  33. //为了避免内存泄露,需要调用_controller.dispose
  34. _controller.dispose();
  35. super.dispose();
  36. }
  37. @override
  38. Widget build(BuildContext context) {
  39. return Scaffold(
  40. appBar: AppBar(title: Text("滚动控制")),
  41. body: Scrollbar(//滚动条
  42. child: ListView.builder(
  43. itemCount: 100,//滚动的总条数
  44. itemExtent: 50.0, //列表项高度固定时,显式指定高度是一个好习惯(性能消耗小)
  45. controller: _controller,//添加已加入监听功能的控制器
  46. itemBuilder: (context, index) {
  47. return ListTile(title: Text("$index"),);//显示文本
  48. }
  49. ),
  50. ),
  51. //通过判断showToTopBtn的值来显示按钮
  52. floatingActionButton: !showToTopBtn ? null : FloatingActionButton(
  53. child: Icon(Icons.arrow_upward),
  54. onPressed: () {
  55. //执行动画返回到顶部
  56. _controller.animateTo(.0,
  57. duration: Duration(milliseconds: 200),
  58. curve: Curves.ease
  59. );
  60. }
  61. ),
  62. );
  63. }
  64. }

效果:

36.根组件数据共享给子组件

  1. class InheritedWidgetTestRoute extends StatefulWidget {
  2. @override
  3. _InheritedWidgetTestRouteState createState() => new _InheritedWidgetTestRouteState();
  4. }
  5. class _InheritedWidgetTestRouteState extends State<InheritedWidgetTestRoute> {
  6. //state的数据
  7. int count = 0;
  8. @override
  9. Widget build(BuildContext context) {
  10. return Center(
  11. //根组件,用于共享数据给它的子组件
  12. child: ShareDataWidget( //使用ShareDataWidget
  13. //构建根组件要用到的参数data
  14. data: count,
  15. //根组件的子组件
  16. child: Column(
  17. //垂直水平方向居中
  18. mainAxisAlignment: MainAxisAlignment.center,
  19. children: <Widget>[
  20. Padding(
  21. padding: const EdgeInsets.only(bottom: 20.0),
  22. //根组件的子组件的子组件...
  23. child: _TestWidget(),//子widget中依赖ShareDataWidget
  24. ),
  25. RaisedButton(
  26. child: Text("Increment"),
  27. //每点击一次,将count自增,然后重新build,ShareDataWidget的data将被更新
  28. onPressed: () => setState(() => ++count),
  29. )
  30. ],
  31. ),
  32. ),
  33. );
  34. }
  35. }
  1. class _TestWidget extends StatefulWidget {
  2. @override
  3. __TestWidgetState createState() => new __TestWidgetState();
  4. }
  5. class __TestWidgetState extends State<_TestWidget> {
  6. @override
  7. Widget build(BuildContext context) {
  8. //使用ShareDataWidget中的共享数据
  9. return Text(ShareDataWidget
  10. .of(context)
  11. .data
  12. .toString());
  13. }
  14. @override
  15. void didChangeDependencies() {
  16. super.didChangeDependencies();
  17. //父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用。
  18. //如果build中没有依赖InheritedWidget,则此回调不会被调用。
  19. print("Dependencies change");
  20. }
  21. }
  1. class ShareDataWidget extends InheritedWidget {
  2. ShareDataWidget({
  3. //接收_InheritedWidgetTestRouteState组件build时传入的两个参数
  4. @required this.data,
  5. Widget child
  6. }) :super(child: child);
  7. final int data; //需要在子树中共享的数据,保存点击次数
  8. //定义一个便捷方法,方便子树中的widget获取共享数据
  9. static ShareDataWidget of(BuildContext context) {
  10. return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
  11. }
  12. //该回调决定当data发生变化时,是否通知子树中依赖data的Widget
  13. @override
  14. bool updateShouldNotify(ShareDataWidget old) {
  15. //如果返回true,则子树中依赖(build函数中有调用)本widget
  16. //的子widget的`state.didChangeDependencies`会被调用
  17. return old.data != data;
  18. }
  19. }

效果:

37.改变主题

  1. class ThemeTestRoute extends StatefulWidget {
  2. @override
  3. _ThemeTestRouteState createState() => new _ThemeTestRouteState();
  4. }
  5. class _ThemeTestRouteState extends State<ThemeTestRoute> {
  6. Color _themeColor = Colors.teal; //当前路由主题色
  7. @override
  8. Widget build(BuildContext context) {
  9. ThemeData themeData = Theme.of(context);
  10. return Theme(
  11. data: ThemeData(
  12. primarySwatch: _themeColor, //用于导航栏、FloatingActionButton的背景色等
  13. iconTheme: IconThemeData(color: _themeColor) //用于Icon颜色
  14. ),
  15. child: Scaffold(
  16. appBar: AppBar(title: Text("主题测试")),
  17. body: Column(
  18. mainAxisAlignment: MainAxisAlignment.center,
  19. children: <Widget>[
  20. //第一行Icon使用主题中的iconTheme
  21. Row(
  22. mainAxisAlignment: MainAxisAlignment.center,
  23. children: <Widget>[
  24. Icon(Icons.favorite),
  25. Icon(Icons.airport_shuttle),
  26. Text(" 颜色跟随主题")
  27. ]
  28. ),
  29. //为第二行Icon自定义颜色(固定为黑色)
  30. Theme(
  31. //局部主题覆盖全局主题
  32. data: themeData.copyWith(
  33. iconTheme: themeData.iconTheme.copyWith(
  34. color: Colors.black
  35. ),
  36. ),
  37. child: Row(
  38. mainAxisAlignment: MainAxisAlignment.center,
  39. children: <Widget>[
  40. Icon(Icons.favorite),
  41. Icon(Icons.airport_shuttle),
  42. Text(" 颜色固定黑色")
  43. ]
  44. ),
  45. ),
  46. ],
  47. ),
  48. floatingActionButton: FloatingActionButton(
  49. onPressed: () => //切换主题
  50. setState(() =>
  51. _themeColor =
  52. _themeColor == Colors.teal ? Colors.blue : Colors.teal
  53. ),
  54. child: Icon(Icons.palette)
  55. ),
  56. ),
  57. );
  58. }
  59. }

效果:

      

38.异步UI更新

  1. class MyHomePage extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. return new Scaffold(
  5. appBar: new AppBar(
  6. title: new Text('标题'),
  7. ),
  8. body: StreamBuilder<int>(
  9. stream: counter(), //调用异步耗时任务
  10. builder: (BuildContext context, AsyncSnapshot<int> snapshot) {//snapshot会包含当前异步任务的状态信息及结果信息
  11. //通过snapshot.hasError判断异步任务是否有错误
  12. if (snapshot.hasError)
  13. //打印错误
  14. return Text('Error: ${snapshot.error}');
  15. //onnectionState是一个枚举类,根据当前异步任务状态ConnectionState来返回不同的widget
  16. switch (snapshot.connectionState) {
  17. case ConnectionState.none:
  18. return Text('没有Stream');
  19. case ConnectionState.waiting:
  20. return Text('等待数据...');
  21. case ConnectionState.active:
  22. return Text('active: ${snapshot.data}');
  23. case ConnectionState.done:
  24. return Text('Stream已关闭');
  25. }
  26. return null; // unreachable
  27. },
  28. ),
  29. );
  30. }
  31. }
  32. //使用Stream来实现异步每隔一秒生成一个数字,每次返回一个int类型
  33. Stream<int> counter() {
  34. return Stream.periodic(Duration(seconds: 1), (i) {
  35. return i;
  36. });
  37. }

效果:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/308543
推荐阅读
相关标签
  

闽ICP备14008679号