zoukankan      html  css  js  c++  java
  • 开启Fluter基础之旅<二>-------Future再论、常用组件、Material Design风格组件学习

    Future再论:

    这里在继续往下学习之前,先来看一下Dart语言关于Event-Queue和Microtask Queue需要注意的一个小点,这个在之前https://www.cnblogs.com/webor2006/p/11994645.html已经学习过了,先来回顾一下当时的代码:

    import 'dart:async';
    
    void main() {
      testScheduleMicrotask();
    }
    
    void testScheduleMicrotask() {
      scheduleMicrotask(() => print('s1'));
    
      new Future.delayed(new Duration(seconds: 1), () => print('s2'));
    
      new Future(() => print('s3')).then((_) {
        print('s4');
        scheduleMicrotask(() => print('s5'));
      }).then((_) => print('s6'));
    
      new Future(() => print('s7'));
    
      scheduleMicrotask(() => print('s8'));
    
      print('s9');
    }

    输出结果为:

     

    好,接下来再来改一下:

    那又输出啥呢?这里先看结果:

    其中相比上面的输出,就是这块不同:

    那咱们就针对性的分析加入的这代码的逻辑:

    正常来理解应该是s10、s11、s12、s7嘛,为啥输出的跟预想的不一样的,其实是这样的:

    所以此时就只会输出s10了,而接下来则会执行下面的这个Future了:

    接下来则这块相继会得到执行:

     

    所以结果就是s10、s7、s11、s12了。

    好,继续再来改,彻底要理解透这块的东东:

    其实很好理解,这句会导致之后的then都不会打印,所以是先打印s3,然后再打印下面的s10,最终如下:

    记住一点,then中如果是一个Future则不会立马执行了就成。

    常用组件:

    继续来学Flutter的常用组件,组件太多,挑常用的先学着,这块得要通过项目来实战才行,但是不了解基础用法也不行。

    文本组件:

    Text:

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text("Text示例"),
            ),
            body: Center(
              child: Column(
                children: <Widget>[
                  Text(
                      'tttttttttttttttttttttttttttkkkkkkkkkkkkkkkkssssssssssssstestlkdkdkkd'),
                ],
              ),
            ),
          ),
        );
      }
    }

    咱们可以将它居中显示:

    TextOverflow:单行处理

    如果只想显示单行,则有几种形式显示:

    而还可以省略显示:

    它则是底部有一层阴影效果:

    TextStyle:

    设置删除线:

    其中这个删除线的样式也能改呢?

    RichText:

    其实在Andorid中也有类似的东东,就是在一断文本中可以增加一些点击事件之类的,下面来看一下如何弄:

    接下来处理一下点击事件,这里点击之后打开一个网页,先来添加一个依赖包:

    这里肯定需要用到异步处理了,如下:

    运行看一下效果:

    其中这是啥语法呢?

    图标及按钮组件:

    图标组件Icon展示图标的组件,该组件不可交互,要实现交互图标,可以考虑使用IconButton组件。图标相关组件有以下几个:

    • Icons:框架自带Icon集合
      这个在之前也已经多次用过了:

    • IconButton:可交互的Icon,图标按钮组件IconButton是基于Meterial Design风格的组件,可以响应按下的事件,并且按下时带水波纹效果。如果它的onPressed回调函数为null,那么这个按钮处于禁用状态,并且不可按下。

      其中点击时用了一个三方的toast库,所以需要添加一下依赖:

      效果:
       

    • RaisedButton:是Material Design中的button,一个凸起的材质矩形按钮,它可以响应按下事件,并且按下时会带一个触摸效果。


    列表控件:

    列表是最常见的需求。在Flutter中,用ListView来显示列表项,支持垂直和水平方向展示,通过一个属性我们就可以控制其方向,列表有以下几类。

    基础列表组件:

    基础列表组件为ListView组件。

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: Text("listview示例"),
            ),
            body: ListView(
              children: <Widget>[
                ListTile(
                  leading: Icon(Icons.favorite_border),
                  title: Text('favarite_border'),
                ),
                ListTile(
                  leading: Icon(Icons.favorite_border),
                  title: Text('favarite_border'),
                ),
                ListTile(
                  leading: Icon(Icons.favorite_border),
                  title: Text('favarite_border'),
                ),
                ListTile(
                  leading: Icon(Icons.favorite_border),
                  title: Text('favarite_border'),
                ),
              ],
            ),
          ),
        );
      }
    }

    就不过多解释了,根据效果就能知道上面写的代码的含义,下面再来扩展一下:

    可以还差分隔线,可以修改如下:

    这里介绍一个小技巧,可以通过IDE来抽象出一个Widget来,如下:

    水平列表组件:

    水平列表组件即为水平方向排列的组件,列表内部元素以水平方向排列。把ListView组件的scrollDirection属性设置为Axis.horizontal即可。 

    注意一下这种是一次性加载100条,而非按需加载,为啥要提这个,因为之后还有一种创建方式。这里又把它抽取一下:

    长列表组件【最常用】:

    当列表的数据项非常多时,需要使用长列表,比如淘宝后台订单列表、手机通讯录等,这些列表项数据很多。长列表也是使用ListView作为基础组件,只不过需要添加一个列表项构造器itemBuilder。 

    很明显就是按需来加载的,也就是有别于上面使用的List.generate()生成的列表,这里给列表中增加一个下划线:

     

    网络布局组件:

    网格布局组件GridView可以实现多行多列布局的应用场景。使用GridView创建网格列表有多种方式:

    • GridView.count:通过单行展示个数创建。

      先运行看一下:

      可以看到总共是2行,然后是横向滑动的。其中childAspectRatio它是啥意思呢?在网上找了一下:

      其实就是每个隔子高度与宽度的比例,如目前我们设置的是2/3,则高度占2,宽度占3,所以是一个长方形,这里为了看到效果,设置为3行:

      如果设置成3/3,那很显然就成一个正方形了:



      而如果设置成1/3,很显然是更加长了:


      接着我们还可以设置成垂直滚动的:


      而此时的childAspectRatio设置的则是子元素宽和高的比例,跟那个横向滑动是相反的。

    • GridView.builder():
      跟ListView一样,也可以用Builder来进行构建:

        

    表单组件:

    表单是一个包含表单元素的区域。表单元素允许用户输入内容,比如文本域,下拉列表,单选框,复选框等。常见应用场景有:登录、注册、输入信息等。表单里有两个重要的组件,一个是Form组件,用来左整个表单提交使用的;另一个是TextFormField组件,用来做用户输入的。 

    Form组件常用属性:

    说到表单,当然最典型的就是用户登录了,所以下面来编写一个用户登录的表单界面,这里直接贴出代码:

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
              appBar: AppBar(
                title: Text("gridview示例"),
              ),
    //          body: new GridViewWidget()),
              body: LoginPage()),
        );
      }
    }
    
    class LoginPage extends StatefulWidget {
      @override
      _LoginPageState createState() => _LoginPageState();
    }
    
    class _LoginPageState extends State<LoginPage> {
      String _userName;
      String _password;
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Column(
            children: <Widget>[
              Container(
                padding: const EdgeInsets.all(10.0), //间隙
                child: Form(
                  child: Column(
                    children: <Widget>[
                      TextFormField(
                        decoration: InputDecoration(labelText: '请输入用户名'),
                        onSaved: (value) {
                          print('$value');
                          _userName = value;
                        },
                        onFieldSubmitted: (value) {
                          print('onFieldSubmitted : $value');
                        },
                      ),
                      TextFormField(
                        decoration: InputDecoration(labelText: '请输入密码'),
                        onSaved: (value) {
                          print('$value');
                          _password = value;
                        },
                        validator: (value) {
                          //这里做个校验,如果不足6位给出错误提示
                          return value.length < 6 ? "密码长度不够6位" : null;
                        },
                      ),
                      Container(
                        margin: const EdgeInsets.only(top: 20.0),
                         400.0,
                        height: 40.0,
                        child: RaisedButton(
                          child: Text('登录'),
                          onPressed: () {
                            //TODO 进行登录
                          },
                        ),
                      )
                    ],
                  ),
                ),
              )
            ],
          ),
        );
      }
    }

    运行一下:

    此时则需要来处理点击事件了,这里面有个写法比较陌生,先记住,之后还会再学的:

    运行看一下效果:

    此时日志输出如下:

    另外,密码框现在还是明文的,得搞成密文风格:

    Material Design风格组件:

    Material Design是由谷歌推出的全新设计语言,这种设计语言旨在为手机、平板电脑、台式机和其他平台提供更一致、更广泛的外观和感觉。Material Design风格是一直非常有质感的设计风格,并会提供一些默认的交互动画,对于搞Android开发的来说应该耳熟能详了。

    App结构和导航组件:

    MaterialApp(应用组件):

    MaterialApp代表使用Material Design风格的应用,里面包含了其他所需的基本控件。官方提供的示例demo就是从MaterialApp这个主组件开始的,我们在之前也已经使用多次了,这里再来从头梳理一下它:

    设置主页:

    使用home属性设置应用的主页,即整个应用的主组件。

    路由处理:

    routes对象是一个Map<String, WidgetBuilder>。当使用Navigator.pushNamed来跳转路由的时候,通过routes查找路由名字,然后使用对应的WidgetBuilder来构造一个带有页面切换动画的MaterialPageRoute。如果应用只有一个界面,则不用设置整个属性,使用home即可。

    下面来使用一下:

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          routes: {'/other': (BuildContext context) => OtherPage()},
          home: HomePage(),
        );
      }
    }
    
    class HomePage extends StatefulWidget {
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('MaterialApp示例'),
          ),
          body: Center(),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              Navigator.pushNamed(context, '/other');
            },
            tooltip: '路由跳转',
            foregroundColor: Color(0xffffffff),
            backgroundColor: Color(0xff000000),
            //阴影
            elevation: 0.0,
            child: Icon(Icons.arrow_forward),
          ),
        );
      }
    }
    
    class OtherPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('OtherPage'),
          ),
        );
      }
    }

    此时运行就可以实现页面的跳转了:

    这里使用了FloatingActionButton,顺便再来学一下它的其它用法,还可以控制它的位置:

     还可以将圆形变为方形:

     

    自定义主题:

    应用程序的主题,各种定制的颜色都可以设置,用于程序主题切换。 这个在未来用到时再进一步学习。

    Scaffold(脚手架组件):

    Scaffold实现了基本的Material Design布局。只要是在Material Design中定义过的单个界面显示的布局组件元素,都可以使用Scaffold来绘制。

    AppBar(应用按钮组件):

    应用按钮组件有AppBar和SliverAppBar。它们是Material Design中的AppBar,也就是Android中的ToolBar。
    AppBar和SliverAppBar都继承自StatefulWidget,两者的区别在于AppBar的位置是固定在应用最上面的;而SliverAppBar是可以跟随内容滚动的。

    BottomNavigatorBar(底部导航栏):

    这个就是典型的像微信那种底部的菜单TAB效果,下面来实现一下:

    class HomePage extends StatefulWidget {
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      int _currentIndex = 0;
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('MaterialApp示例'),
          ),
          body: Center(),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              Navigator.pushNamed(context, '/other');
            },
            tooltip: '路由跳转',
            foregroundColor: Color(0xffffffff),
            backgroundColor: Color(0xff000000),
            //阴影
            elevation: 0.0,
            child: Icon(Icons.arrow_forward),
    //        shape: RoundedRectangleBorder(),
          ),
          floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
          bottomNavigationBar: BottomNavigationBar(
            items: [
              BottomNavigationBarItem(
                icon: Icon(Icons.message),
                title: Text('信息'),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.contacts),
                title: Text('通讯录'),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.near_me),
                title: Text('发现'),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.account_circle),
                title: Text('我'),
              ),
            ],
            currentIndex: _currentIndex,
            onTap: (index) {
              setState(() {
                _currentIndex = index;
              });
            },
          ),
        );
      }
    }

    运行看一下:

    再运行:

    哇塞,效果还蛮好的呢?下面点击完之后,咱们在上面切换一下内容,这里简单切换一下文件模拟下:

    再运行一下:

    关于Material Design风格组件还有很多,下次再继续。

  • 相关阅读:
    02 .NET CORE 2.2 使用OCELOT -- 路由
    01 .NET CORE 2.2 使用OCELOT -- 简单使用
    Winows上简单配置使用kafka(.net使用)
    【C#】 获取计算机的硬件信息
    使用NPOI进行Excel操作
    Xamarin 开发Android应用简易教程(1)
    【日常笔记】字符串加密
    【日常笔记】生成验证码图片
    [Winfrom] 使用一个启动快捷方式,打开2个不同的窗体并且共用一个缓存空间
    windows获取物理mac地址
  • 原文地址:https://www.cnblogs.com/webor2006/p/12545701.html
Copyright © 2011-2022 走看看