Flutter系列教程之(4)——自定义Widget控件及相关知识

目录

StatelessWidget与StatefulWidget简介

StatelessWidget

创建Widget

使用

StatefulWidget

简单说明

改变页面数据

使用补充

1.传递参数

2.外层Widget改变当前Widget


StatelessWidget与StatefulWidget简介

我们需要创建我们自定义的 Widget 控件,只需要创建一个类去继承 StatelessWidget 和 StatefulWidget 这两个类即可,这两个类都是 Flutter 提供的基本 Widget 类,不过在使用上有所区别

StatelessWidget 是静态 Widget ,而 StatefulWidget 则是动态 Widget

StatefulWidget 与 StatelessWidget 唯一不同的特点,就是其提供了一个 setState() 的方法,我们可以调用此方法,更新数据,从而会让该 Widget 的内容发生改变(本质上与 MVVM 模式类似)

那什么是静态 Widget 和动态 Widget 分别是什么意思呢?静态 Widget 则是说明其中的内容不会发生改变,如 Button 按钮、文字 Text 等,动态 Widget 则是内容是可变的,如一个列表显示的数据,其数据是通过网络请求来获得的,网络请求返回的数据每次可能有所不一样,之后我们需要增加一个下拉刷新的效果,我们就可以调用 setState 的方法,去更改数据,从而进一步改变列表中显示的数据

综上所述:我们需要创建自定义Widget,需要根据需求来判断是应该使用StatefulWidget还是StatelessWidget,不过实际的需求一般都是动态的多些,比如说两个下拉框需要数据联动,或者是复选框的勾选等...

下面就是分别介绍StatefulWidget和StatelessWidget这两种Widget的用法

StatelessWidget

创建Widget

这种Widget实现比较简单,我们只需要定义一个类,继承StatelessWidget,之后实现StatelessWidget的build接口方法即可

Dart 复制代码
class DemoWidget extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      theme: new ThemeData(
        primaryColor: Colors.blue,
        accentColor: Colors.blueAccent,
      ),
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Flutter Bar'),
        ),
        body: new Center(
          child: new Text('Hello World'),
        ),
        floatingActionButton:
        FloatingActionButton(onPressed: () {
          Fluttertoast.showToast(
            msg: "点击添加",
            toastLength: Toast.LENGTH_SHORT,
            gravity: ToastGravity.BOTTOM,
            backgroundColor: Colors.black,
          );
        },
            child: Icon(Icons.add)
        ),
      ),
    );
    
  }

我这里是直接把之前的那个例子拿过来用了,把它封装成了DemoWidget

使用

使用的话就很简单了,我们直接new一个DemoWidget类对象即可

Dart 复制代码
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
	  //new关键字可以省略
    return DemoWidget();
  }
}

StatefulWidget

简单说明

StatefulWidget实现过程稍微复杂一些,需要两个类,一个是Widget,另外一个则是State状态类,如下图所示

还记得之前说到的setState方法吗,其实它是State状态类里的方法

StatefulWidget与StatelessWidget不一样,StatefulWidget需要实现createState()方法,其方法需要返回一个State对象,而State类与之前的StatelessWidget一样,需要实现build()方法

之后,每当调用setState()方法时候,DemoWidget就会得到一个新的状态,并重新渲染页面(也就是改变了页面显示的内容)

Dart 复制代码
class DemoWidget extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    return DemoWidgetState();
  }

}

class DemoWidgetState extends State<DemoWidget>{
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      theme: new ThemeData(
        primaryColor: Colors.blue,
        accentColor: Colors.blueAccent,
      ),
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Flutter Bar'),
        ),
        body: new Center(
          child: new Text('Hello World'),
        ),
        floatingActionButton:
        FloatingActionButton(onPressed: () {
          Fluttertoast.showToast(
            msg: "点击添加",
            toastLength: Toast.LENGTH_SHORT,
            gravity: ToastGravity.BOTTOM,
            backgroundColor: Colors.black,
          );
        },
            child: Icon(Icons.add)
        ),
      ),
    );
  }
}

PS:用法和之前一样,直接创建个实例对象即可显示页面

改变页面数据

上面的代码其实与之前的StatelessWidget中的代码效果一致,点击按钮会弹出Toast提示,接下来我们对上面的代码进行部分的改造,实现点击按钮,让页面中间显示的数据发生改变,我们只需要改DemoWidgetState这个类中的代码即可

Dart 复制代码
class DemoWidgetState extends State<DemoWidget> {
  var i = 0;
  var str = "hello";

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      theme: new ThemeData(
        primaryColor: Colors.blue,
        accentColor: Colors.blueAccent,
      ),
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Flutter Bar'),
        ),
        body: new Center(
          child: new Text(str),
        ),
        floatingActionButton: FloatingActionButton(
            onPressed: () {
              setState(() {
                str = "hello$i";
                i++;
              });
            },
            child: Icon(Icons.add)),
      ),
    );
  }
}

可以看到我们需要的效果,点击添加按钮,中间的文字就会变为hello0,之后第二次就变为hello1

使用补充
1.传递参数

上面为StatefulWidget的基本用法,接下来补充一下如何传递参数以及获取布局里的数据

传递参数稍微有些繁琐,需要在Widget中写一个变量,同时,也需要在State状态类中写个变量,比如之前的那个布局,我们中间默认显示hello,之后点击按钮会变为hello0

我们想要实现创建的时候直接给定默认显示的数据,可以是hello,或者是其他的数据,就可以写个构造函数,用来传递默认显示的数据即可,代码如下图所示:

可以看到,代码其实没有较大的改动,只是在Widget和State这两个类中添加了对应的成员变量和构造方法

2.外层Widget改变当前Widget

这里可能起的名字不是很好,我们举个例子来说明一下

比如我们有个页面,有个按钮Button的Widget和我们创建的自定义Widget,我们想要实现点击按钮就要获得我们自定义Widget里的数据,这个时候我们有什么办法呢?

我不确定我这是不是正确的解决方法,我的做法是,在Widget类中声明了一个State的变量引用,之后由State类中提供一个方法,用来修改数据

之后使用的时候,我们可以直接调用DemoWidget对象实例的state变量,从而在调用setData()

当然,你也可以在DemoWidget中创建一个方法,之后在里面调用state的方法,如:

又或者state不写那个setData方法,直接在Widget中写也可以,如:

PS:至于获取Widget的数据,与上面也是类似,直接在Widget或者是State中定义个方法,用来返回数据即可

相关推荐
豪冷啊12 小时前
Flutter Invalid constant value.
flutter
顾林海16 小时前
Flutter容器组件深度解析
android·前端·flutter
xq952716 小时前
mac os flutter 配置环境变量
flutter
sg_knight19 小时前
Flutter性能优化终极指南:从JIT到AOT的深度调优
前端·flutter·性能优化·web·dart
zonda的地盘21 小时前
[Get 源码] GetPageRoute 与 GetxController 的自动回收机制
flutter
明似水1 天前
Flutter iOS 项目中 VolumeControllerPlugin 报错解决方案
flutter·ios
折翅鵬1 天前
Flutter报错:Warning: CocoaPods is installed but broken
flutter·cocoapods
pengyu1 天前
【Flutter 状态管理 - 壹】 | 提升对声明式编程的认知
android·flutter·dart
zonda的地盘2 天前
Flutter PlatformViewLink vs Texture
flutter
zonda的地盘2 天前
‌AndroidView 配置 TLHC(Texture Layer Hybrid Composition)模式指南
flutter