• Flutter:statelessWidget案例、StatefulWidget案例


    前言

    在线教程:statelessWidget

    参考:Widget 简介

    statelessWidget

    StatelessWidget用于不需要维护状态的场景,它通常在build方法中通过嵌套其他 widget 来构建UI,在构建过程中会递归的构建其嵌套的 widget 。

    基本demo

    import 'package:flutter/material.dart';
    
    //使用箭头函数简写
    main() => runApp(const MyApp());
    
    // app需要返回一个material类型的app -> MaterialApp需要一个首页,然后创建一个首页的widget(YcHomePage)
    // 主页面需要有导航条和内容,借助Scaffold快速创建,然后创建导航条appBar和 body
    // body是一个widget,再创建YcHomeBody
    
    class MyApp extends StatelessWidget {
      //创建widget的唯一标识
      const MyApp({Key? key}) : super(key: key);
    
      //重写build方法
      @override
      Widget build(BuildContext context) {
        //返回一个material类型的app
        return const MaterialApp(
          //指定显示哪一个页面
          home: YcHomePage(),
        );
      }
    }
    
    //app的主页面
    class YcHomePage extends StatelessWidget {
      const YcHomePage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        //首页需要有导航和内容,这里借助Scaffold来快速创建
        return Scaffold(
          //导航条
          appBar: AppBar(
            title: const Text("商品列表", style: TextStyle(color: Colors.white)),
          ),
          //页面主题内容
          body: const YcHomeBody(),
        );
      }
    }
    
    //主页面的body
    class YcHomeBody extends StatelessWidget {
      const YcHomeBody({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        //Column可以在垂直方向排列其子组件
        return Column(
          children: const [
            YcHomeProductItem("vue", "渐进式,JavaScript 框架易学易用,性能出色,适用场景丰富的 Web 前端框架。",
                'https://pic3.zhimg.com/v2-d73df22d306f557a0d3d313d78f50f84_1440w.jpg'),
            YcHomeProductItem(
                "Flutter",
                "Flutter 是 Google 推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。",
                'https://pic2.zhimg.com/v2-d4475f94d92ae6012a4f2f727a51700d_1440w.jpg'),
            YcHomeProductItem(
                "Flutter",
                "Flutter 是 Google 推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。",
                'https://pic2.zhimg.com/v2-d4475f94d92ae6012a4f2f727a51700d_1440w.jpg')
          ],
        );
      }
    }
    
    //商品
    class YcHomeProductItem extends StatelessWidget {
      //定义需要的参数,widget里面定义的变量必须是final的
    
      final String title; //标题
      final String desc; //描述
      final String imgUrl; //图片地址
    
      //构造函数
      const YcHomeProductItem(this.title, this.desc, this.imgUrl, {Key? key})
          : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [Text(title), Text(desc), Image.network(imgUrl)],
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    效果图
    在这里插入图片描述
    这里存在一个问题,当内容超出屏幕的显示范围时会出现下面的这块区域,解决方法就是设置成滚动的区域

    优化

    Column 换成 ListView

    //主页面的body
    class YcHomeBody extends StatelessWidget {
      const YcHomeBody({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        //Column可以在垂直方向排列其子组件
        return ListView(
          children: const [
            YcHomeProductItem("vue", "渐进式,JavaScript 框架易学易用,性能出色,适用场景丰富的 Web 前端框架。",
                'https://pic3.zhimg.com/v2-d73df22d306f557a0d3d313d78f50f84_1440w.jpg'),
            YcHomeProductItem(
                "Flutter",
                "Flutter 是 Google 推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。",
                'https://pic2.zhimg.com/v2-d4475f94d92ae6012a4f2f727a51700d_1440w.jpg'),
            YcHomeProductItem(
                "Flutter",
                "Flutter 是 Google 推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。",
                'https://pic2.zhimg.com/v2-d4475f94d92ae6012a4f2f727a51700d_1440w.jpg')
          ],
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    最终代码

    import 'package:flutter/material.dart';
    
    //使用箭头函数简写
    main() => runApp(const MyApp());
    
    // app需要返回一个material类型的app -> MaterialApp需要一个首页,然后创建一个首页的widget(YcHomePage)
    // 主页面需要有导航条和内容,借助Scaffold快速创建,然后创建导航条appBar和 body
    // body是一个widget,再创建YcHomeBody
    
    class MyApp extends StatelessWidget {
      //创建widget的唯一标识
      const MyApp({Key? key}) : super(key: key);
    
      //重写build方法
      @override
      Widget build(BuildContext context) {
        //返回一个material类型的app
        return const MaterialApp(
          //指定显示哪一个页面
          home: YcHomePage(),
        );
      }
    }
    
    //app的主页面
    class YcHomePage extends StatelessWidget {
      const YcHomePage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        //首页需要有导航和内容,这里借助Scaffold来快速创建
        return Scaffold(
          //导航条
          appBar: AppBar(
            title: const Text("商品列表", style: TextStyle(color: Colors.white)),
          ),
          //页面主题内容
          body: const YcHomeBody(),
        );
      }
    }
    
    //主页面的body
    class YcHomeBody extends StatelessWidget {
      const YcHomeBody({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        //Column可以在垂直方向排列其子组件
        return ListView(
          children: const [
            YcHomeProductItem("vue", "渐进式,JavaScript 框架易学易用,性能出色,适用场景丰富的 Web 前端框架。",
                'https://pic3.zhimg.com/v2-d73df22d306f557a0d3d313d78f50f84_1440w.jpg'),
            YcHomeProductItem(
                "Flutter",
                "Flutter 是 Google 推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。",
                'https://pic2.zhimg.com/v2-d4475f94d92ae6012a4f2f727a51700d_1440w.jpg'),
            YcHomeProductItem(
                "Dart",
                "Dart是谷歌开发的计算机编程语言,后来被Ecma (ECMA-408)认定为标准。它被用于web、服务器、移动应用和物联网等领域的开发。",
                'https://static001.infoq.cn/resource/image/a7/d4/a7db324acf088378d8be46fc42eeaed4.png')
          ],
        );
      }
    }
    
    //商品
    class YcHomeProductItem extends StatelessWidget {
      //定义需要的参数,widget里面定义的变量必须是final的
    
      final String title; //标题
      final String desc; //描述
      final String imgUrl; //图片地址
    
      //构造函数
      const YcHomeProductItem(this.title, this.desc, this.imgUrl, {Key? key})
          : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        const titleStyle = TextStyle(fontSize: 24, color: Colors.orange);
        const descStyle = TextStyle(fontSize: 16, color: Colors.blue);
    
        return Container(
          //内边距
          padding: const EdgeInsets.all(8),
          //外边距
          margin: const EdgeInsets.all(8),
          // decoration 装饰,decoration是抽象类,这里使用其子类
          decoration: BoxDecoration(
              //边框
              border: Border.all(
                  width: 2, //边框的宽度
                  color: Colors.blueGrey //边框颜色
                  )),
          child: Column(
            children: [
              Text(title, style: titleStyle),
              //使用SizedBox来实现间距,flutter中没有margin
              const SizedBox(
                height: 8,
              ),
              Text(
                desc,
                style: descStyle,
              ),
              const SizedBox(
                height: 8,
              ),
              Image.network(imgUrl),
              const SizedBox(
                height: 8,
              ),
            ],
          ),
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118

    其他

    • Android studio 可以通过stless 来快速的创建一个statelessWidget
    • Android studio 将鼠标放在widget,来给widget套一层widget
      在这里插入图片描述
    • widget里面定义的变量必须是final的
    • 使用SizedBox来实现间距,flutter中没有margin
    • 使用Container来实现边框

    StatefulWidget

    StatefulWidget 类会对应一个 State 类,State表示与其对应的 StatefulWidget 要维护的状态,State 中的保存的状态信息可以:

    • 在 widget 构建时可以被同步读取。
    • 在 widget 生命周期中可以被改变,当State被改变时,可以手动调用其setState()方法通知Flutter 框架状态发生改变,Flutter 框架在收到消息后,会重新调用其build方法重新构建 widget 树,从而达到更新UI的目的。

    State 中有两个常用属性:

    • widget,它表示与该 State 实例关联的 widget 实例,由Flutter 框架动态设置。注意,这种关联并非永久的,因为在应用生命周期中,UI树上的某一个节点的 widget 实例在重新构建时可能会变化,但State实例只会在第一次插入到树中时被创建,当在重新构建时,如果 widget 被修改了,Flutter 框架会动态设置State. widget 为新的 widget 实例。

    • context。StatefulWidget对应的 BuildContext,作用同StatelessWidget 的BuildContext。

    demo

    import 'package:flutter/material.dart';
    
    //使用箭头函数简写
    main() => runApp(const MyApp());
    
    // app需要返回一个material类型的app -> MaterialApp需要一个首页,然后创建一个首页的widget(YcHomePage)
    // 主页面需要有导航条和内容,借助Scaffold快速创建,然后创建导航条appBar和 body
    // body是一个widget,再创建YcHomeBody
    
    class MyApp extends StatelessWidget {
      //创建widget的唯一标识
      const MyApp({Key? key}) : super(key: key);
    
      //重写build方法
      @override
      Widget build(BuildContext context) {
        //返回一个material类型的app
        return const MaterialApp(
          //指定显示哪一个页面
          home: YcHomePage(),
        );
      }
    }
    
    //app的主页面
    class YcHomePage extends StatelessWidget {
      const YcHomePage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        //首页需要有导航和内容,这里借助Scaffold来快速创建
        return Scaffold(
          //导航条
          appBar: AppBar(
            title: const Text("商品列表", style: TextStyle(color: Colors.white)),
          ),
          //页面主题内容
          body: const YcHomeBody("哈哈哈"),
        );
      }
    }
    
    //主页面的body
    class YcHomeBody extends StatefulWidget {
      // widget是不可变的,必须用final
      final String message;
      const YcHomeBody(this.message, {Key? key}) : super(key: key);
    
      @override
      State<StatefulWidget> createState() {
        //返回对应的状态类
        return _YcHomeBodyState();
      }
    }
    
    //管理主页body的状态类,状态类前面一般加下划线进行标识
    class _YcHomeBodyState extends State<YcHomeBody> {
      int _counter = 0;
      //可以通过this.widget来获取实例
      @override
      Widget build(BuildContext context) {
        return Center(
            child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            _getButton(),
            Text("当前计数为:$_counter"),
            Text("当前传递的信息是:${widget.message}")
          ],
        ));
      }
    
      //获取按钮
      Widget _getButton() {
        return Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
                onPressed: () {
                  setState(() => _counter++);
                },
                child: const Icon(Icons.add)),
            ElevatedButton(
              onPressed: () {
                setState(() => _counter--);
              },
              child: const Icon(Icons.remove),
            ),
          ],
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92

    在这里插入图片描述

    其他

    状态类,前面一般加上_ 来进行标识,标识该类是私有的

    为什么StatefulWidget的build方法放在State中?

    • build出来的widget是需要依赖State中的变量(状态)

    widget可以传参,因此参数哈哈哈,只能放在YcHomeBody 里

    state源码中有一个变量,我们可以通过该变量拿到widget的实例
    在这里插入图片描述

  • 相关阅读:
    Python数据分析 — 数据分析概念、重要性、流程和常用工具
    题目 1058: 二级C语言-求偶数和(python详解)——练气四层中期
    C++十种排序算法实现
    54_Pandas将DataFrame、Series转换为字典 (to_dict)
    从 Hadoop 到云原生, 大数据平台如何做存算分离
    【Deep Dive:AI Webinar】我们是否能将开源许可用于机器学习和人工智能模型?
    软件测试基础篇(2)
    flutter课程(The Complete 2021 Flutter Development Bootcamp with Dart)学习总结
    劲松中西医医院谭巍主任在线分析:HPV复阳的三大祸首
    油管125万粉顶级交易员_教你使用macd
  • 原文地址:https://blog.csdn.net/weixin_41897680/article/details/126452912