Flutter学习(4)——自定义Widget控件及相关知识

Stars-one 2020年10月05日 623次浏览 本篇字数为0字

本文为作者原创,转载请注明出处,谢谢配合
作者:Stars-one
链接:https://stars-one.site/2020/10/05/flutter-study-4


StatelessWidget与StatefulWidget简介

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

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

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

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

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

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

StatelessWidget

创建Widget

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

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类对象即可

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

StatefulWidget

简单说明

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

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

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

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

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这个类中的代码即可

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类中提供一个方法,用来修改数据

State中定义方法

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

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

Widget中调用State对象方法

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

Widget中直接定义方法

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

相关标签