用Flutter实现小Q聊天机器人(二)

版权声明:转载请注明出处:白玉梁的专栏 https://blog.csdn.net/baiyuliang2013/article/details/88719555

用Flutter实现小Q聊天机器人(一)
用Flutter实现小Q聊天机器人(二)
用Flutter实现小Q聊天机器人(三)
用Flutter实现小Q聊天机器人(四)
用Flutter实现小Q聊天机器人(五)

GitHub:https://github.com/baiyuliang/Qrobot_Flutter

接上篇,我们新建一个Flutter Project:
在这里插入图片描述
flutter项目中有android、ios、lib等目录,可能刚开始有不少同学建完项目,就直奔android目录准备开发了,但其实,flutter的编程目录是在lib下的,所有编程文件后缀都为.dart,我们也可以把其看做安卓开发时.java以及java目录,可以更好的理解!

其中的pubspec.yaml这个文件很重要,类似于安卓开发时app目录下的build.gradle,我们在引用一些第三方的工具或插件时都要在该文件中声明,如下图:
在这里插入图片描述
引入后点击右上角的Pakage get,就可以获取该包,然后再项目中引入该包路径,就可以使用里面提供的方法了。

在新建的flutter项目的lib目录下,都会有一个mian.dart,这个就是程序的入口,里面提供的有示例,在我们着手开始写代码之前,还是 有必要去了解一下Flutter UI方面的一些知识。

  • dart导入包跟java一样,用import关键字,当你输入import时,AS会自动提示很方便;
  • 如java一样,dart同样用class声明类,extends继承类;
  • java的精髓是万物皆对象,flutter的精髓是万物皆组件,所以你在开发flutter时会经常用到Widget;
  • Widget可以理解为安卓中的View;
  • 更多内容可以去官网学习

我们在布局一个界面的UI时经常要用到两个类:StatelessWidget和StatefulWidget:

StatelessWidget表示静态页面,就像我们常说的写死的,不会有改变的;而StatefulWidget是动态的,也就是UI会根据数据的改变做出动态响应的;我们看到主程序里面第一个组类就是StatelessWidget:

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

build方法中返回的Widget 就像是该界面整个UI的一个最顶级的ViewGroup,像一个底板,然后里面的接下来的所有组件都会在这个group中一层套一层的布局;另外,这个结构看起来似曾相识啊:

public class MainActivity extends FlutterActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
  }
}

区别就是,安卓中我们用xml布局,而Flutter中我们要用代码布局,UI中的所有组件我们都要用代码一个一个实现,是不是有种想放弃的感觉,哈哈!
MaterialApp就是Material风格的app了,做安卓开发的再熟悉不过了,里面的属性大家可以自行查看官网说明,重点说home这个属性:字面意思,家,就是这个界面的家,在home中也就需要我们根据UI设计去一点一点布局了;

 home: MyHomePage(title: 'Flutter Demo Home Page'),

MyHomePage继承了StatefulWidget,说明这个界面是一个动态的;我们需要知道,安卓开发中,我们可以直接去操控view,改变view的属性,但Flutter中却不能,我们需要通过数据的改变去重绘UI,也就是我们只能改变数据,而不能直接操控组件,跟微信小程序开发是一样的道理;
而实现要实现动态界面,StatefulWidget和State两个类是紧紧相连的:

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
      ),
      body: Center(

      ));
  }
}

MyHomePage 重写createState方法,返回State(_MyHomePageState ),接下来该界面所使用的变量,方法等都可以在_MyHomePageState 类中声明,改变UI则可以通过方法 setState:

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

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

而真正布局的开始,则是在_MyHomePageState 的Widget build(BuildContext context)方法中:

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
      ),
      body: Center(

      ));
  }

Scaffold 实现了Material风格的布局及组件,仅从布局意义上讲,我们仍然可以把其理解为一个ViewGroup,主要属性说明:

  • appBar:Material 的标题栏;
  • body:UI主要内容(标题栏以下)
  • floatingActionButton: 在 Material 中定义的一个功能按钮;
  • persistentFooterButtons:固定在下方显示的按钮;
  • drawer:侧边栏;
  • bottomNavigationBar:底部导航栏;
  • backgroundColor:背景颜色;
  • resizeToAvoidBottomPadding: 控制界面内容 body是否重新布局来避免底部被覆盖了,比如当键盘显示的时候,重新布局避免被键盘盖住内容;

对于组件的声明我们可以前面加上new如: new Text(‘标题’),也可以不加如:Text(‘标题’),所以大家在看到不同项目中有的有new,有的没有时不要疑惑,没有任何区别;接下来,我们来了解一下常用的一些组件:

  • 文本:Text;
  • 输入框:TextField;
  • 列表:ListView;
  • divider:Divider;
  • 边框:BoxDecoration;
  • 包裹容器:Container;
  • 水平布局容器:Row;
  • 垂直布局容器:Column;
  • 可伸缩布局容器:Flexible;
  • 图片:Image;

等等…不在过多罗列,各种组件都有其对应的各种属性如:margin,padding,width,heigth等等;

下面我们来实现一个上面是内容,底部是输入框的这么一个界面:

class _MyHomePageState extends State<MyHomePage> {
  TextEditingController _textController = new TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: new Column(children: <Widget>[
          new Text("Hello World"),
          new Divider(height: 1.0), //分界线
          new TextField(
            controller: _textController,
            decoration: new InputDecoration.collapsed(hintText: '请输入消息'),
          )
        ]));
  }
}

先用最简单的实现,首先思考布局,上面是内容,下面是输入框,这类似于LinlearLayout的垂直布局,那么在flutter中我们可以用Column来实现,需要注意的是:Column和Row容器中可以有多个子Widget,也就相当于可以有多个子View,类似于LinearLayout,RelayLayout等,对应的属性是children,字面意思:孩子们,而像Container,Flexible等容器中只能有一个组件,类似于ScrollView,对应的属性是child,对比children意思一目了然,而Text,Image等组件跟安卓中想同,为最小View,他们中不能再有组件;

另外注意组件的书写方式:

child:组件(
   属性:xx,
   属性:xx,
),
 children: <Widget>[
	组件(
	   属性:xx,
	   child:组件(
	              属性:xx,
	              child:xx,
	            ),
	),
	组件(
	   属性:xx,
	   属性:xx,
	),
]

所有属性以及组件间用逗号“,”隔开,并注意属性及组件的层次递进;

输入框TextField实现时需要一个控制器TextEditingController,再类中声明一下即可,过后我们就可以用这个对象实现获取输入框中的内容,清空输入框的内容等一系列操作了;

运行程序,效果如下:
在这里插入图片描述
本篇讲述了flutrer项目结构,布局规则,及不同组件的作用及使用方法,大家对Flutter项目的开发有一个最基本的了解之后,下一篇将继续讲解如何实现一个Flutter版的聊天机器人。

展开阅读全文

没有更多推荐了,返回首页