flutter学习总结(语法,组件,布局,和路由)

一.helloworld应用

按国际惯例,写来一个hello world应用跑一遍.

创建项目

启动 VS Code
调用 View>Command Palette…
输入 ‘flutter’, 然后选择 ‘Flutter: New Project’ action
输入 Project 名称 (如myapp), 然后按回车键
指定放置项目的位置,然后按蓝色的确定按钮
等待项目创建继续,并显示main.dart文件
开始代码,写在根目录\lib\main.dart文件中,这就是Flutter主文件.

基本思路:

引入flutter包

入口函数

声明MyApp类

重写build方法,它返回一个MaterialApp风格的组件

在Material组件的home属性里赋值一个Scaffold组件

在Scaffold组件里创建appBar和body

在body的中间区域添加hello world文本

填充代码:

// flutter相当于一个UI库,所以使用前要引入flutter
import 'package:flutter/material.dart';

// 入口函数
void main() => runApp(MyApp());

// 声明MyApp类
class MyApp extends StatelessWidget {
// 重写build方法,它返回一个Material风格的组件
  @override
  Widget build(BuildContext context) {
// 在MaterialApp组件的home属性里赋值一个Scaffold组件
    return MaterialApp(
      title: "welcome",
      home: Scaffold(
// 在Scaffold组件(相当于脚手架的东西)里创建appBar和body
        appBar: AppBar(title: Text('This is header')),
// 在body的中间区域添加hello world文本
        body: Center(child: Text('hello world')),
      ),
      debugShowCheckedModeBanner: false,//去掉右上方的bug
    );
  }
}

效果:flutter学习总结(语法,组件,布局,和路由)_第1张图片
精简版基本模板:

import 'package:flutter/material.dart';
void main()=>runApp(MyApp());
class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return MaterialApp(
      title:'test',
      home:Scaffold(
        appBar: new AppBar(
          title:new Text("这是头部"),
          
        ),
        body:new Text('内容')
      )
    );
  }
}

也许你对上面的语法还不够了解,但你不必惊慌,我会进行说明,那先来看一下Dart中的函数。

Dart语法Function函数

Dart是面向对象的语言,即使是函数也是对象,并且属于函数类型的对象。
比如我们写的上面第二行代码,就是一个函数

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

上面是简写,普通写法如下:

void main() {
  return runApp(MyApp());
}

总结:发现Dart语言是不能省略结束符“;”的。

二.常用组件

Text()组件介绍

这个是文本组件,是非常常见的.记住在flutter中一切东西都是组件(组件英文名叫widget).

Text()组件的属性介绍:

textAlign文字对齐属性
center: 文本以居中形式对齐,这个也算比较常用的了。
left:左对齐,经常使用,让文本居左进行对齐,效果和start一样。
right :右对齐,使用频率也不算高。
start:以开始位置进行对齐,类似于左对齐。
end: 以为本结尾处进行对齐,不常用。有点类似右对齐.

总结起来,也就算三个对齐方式,left(左对齐)、center(居中对齐)、right(右对齐)。我们来看一下具体代码写法:
在这里插入图片描述
内容写在第一个参数里,属性以对象值的方式写.

maxLines属性最多显示的行数

maxLines属性设置显示的行数,比如我们给1,文字只能显示出1行了,多的自动消失.

overflow超出显示属性

有三个值:
clip:直接切断,
ellipsis:后面显示三个省略号,
fade:直接切断,并带有整行上下渐变的效果.
flutter学习总结(语法,组件,布局,和路由)_第2张图片
注意值的写法是要加上Text,用TextOverflow点出各自的值.

style属性

style属性内容比较多:

inherit 是否将null值替换为祖先文本样式中的值(例如,在TextSpan树中)。如果为false,则没有显式值的属性将恢复为默认值:白色,字体大小为10像素,采用无衬线字体。
color 字体的颜色
fontSize 文字大小,单位为像素,如果没有指定大小则默认为14像素,可以乘以textScaleFactor来增加字体大小以便用户更加方便的阅读
fontWeight 字体厚度,可以使文本变粗或变细
fontStyle 字体变形,有两种 FontStyle.normal(字体直立), FontStyle.italic(字体倾斜)
letterSpacing 字母间距,整数拉开字母距离,若是负数则拉近字母距离
wordSpacing,单词间距,同上
textBaseline 用于对齐文本的水平线
height 文本行高,为字体大小的倍数
locale 用于选择区域特定符号的区域设置
background 文本的背景颜色
shadows 文本的阴影可以利用列表叠加处理,例如shadows: [Shadow(color:Colors.black,offset: Offset(6, 3), blurRadius: 10)], color即阴影的颜色, offset即阴影相对文本的偏移坐标,blurRadius即阴影的模糊程度,越小越清晰
decoration 文字的线性装饰,比如 underline 下划线, lineThrough删除线
decorationColor 文本装饰线的颜色
decorationStyle 文本装饰线的样式,比如 dashed 虚线
debugLabel 这种文本样式的可读描述,此属性仅在调试构建中维护。

具体的可以看官网:https://api.flutter.dev/flutter/painting/TextStyle-class.html#painting.TextStyle.1

小技巧快速打开虚拟机的方法:依次点击下面的即可
flutter学习总结(语法,组件,布局,和路由)_第3张图片

Container组件的使用

Container组件相当于我们的div标签,它的作用就是方便我们进行布局的.

alignment属性

alignment属性的作用是针对的是Container内child的对齐方式,也就是容器子内容的对齐方式,并不是容器本身的对齐方式.
flutter学习总结(语法,组件,布局,和路由)_第4张图片
常用属性有:

bottomCenter:下部居中对齐。
botomLeft: 下部左对齐。
bottomRight:下部右对齐。
center:纵横双向居中对齐。
centerLeft:纵向居中横向居左对齐。
centerRight:纵向居中横向居右对齐。
topLeft:顶部左侧对齐。
topCenter:顶部居中对齐。
topRight: 顶部居左对齐。

总结规律:纵向在前,横向在后.

宽width,高height,背景颜色color(注意color不是字体颜色,而是背景颜色)设置

flutter学习总结(语法,组件,布局,和路由)_第5张图片

padding和margin属性

跟我们的css样式一样,但注意点写法:值是要带常量声明

padding:const EdgeInsets.all(20.0)

这句的意思是设置Container的内边距是20,左右上下全部为20,这看起来非常容易。那我们再加大一点难度。如果上边距为30,左边距为10,这时候EdgeInsets.all()就满足不了我们了。
我们用EdgeInsets.fromLTRB(value1,value2,value3,value4) 可以满足我们的需求,LTRB分别代表左、上、右、下。

decoration修饰属性

背景设置:
decoration属性主要是用来设置背景和边框.
比如我们要设置渐变背景,上面的color背景只能设置单一颜色,我们可以用decoration来设置(与color不能同时存在,只能留一个)
设置方法:这时候就要用new BoxDecoration()这个组件.写法如下:
flutter学习总结(语法,组件,布局,和路由)_第6张图片
边框设置:(这个不需要new)

border:Border.all(width:2.0,color:Colors.purple)

效果:
flutter学习总结(语法,组件,布局,和路由)_第7张图片
附完整代码:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return MaterialApp(
      title:"hello widget",
      home:Scaffold(
        body:Center(
          child:Container(
            child:new Text('hahahahahahahahahahahahahhahahahahahahahahahahahahhahahahahahahahahahahahahhahahahahahahahahahahahahhahahahahahahahahahahahah',
            style:TextStyle(
              fontSize:20.0
            )
            ),
            alignment:Alignment.topLeft,
            width:500.0,
            height: 400.0,
            
            padding:const EdgeInsets.all(20.0),
            margin:const EdgeInsets.all(30.0),
            decoration:new BoxDecoration(
                  gradient:const LinearGradient(
                    colors:[Colors.lightBlue,Colors.greenAccent,Colors.purple]
                  ),
                  border:Border.all(width:5.0,color:Colors.purple)
                )
           

          )
        )
      )
    );
  }
}

遇到的坑点:记住color背景属性和decoration属性不能同时存在,存在会报错.

Image图片组件

图片引入的几种方式:
Image.asset:加载资源图片,就是加载项目资源目录中的图片,加入图片后会增大打包的包体体积,用的是相对路径。
Image.network:网络资源图片,意思就是你需要加入一段http://xxxx.xxx的这样的网络路径地址。
Image.file:加载本地图片,就是加载本地文件中的图片,这个是一个绝对路径,跟包体无关。
Image.memory: 加载Uint8List资源图片(相当于内存一样),这个我目前用的不是很多.
图片fit填充属性的设置

填充属性值有以下几种:

BoxFit.fill:全图显示,图片会被拉伸,并充满父容器。

BoxFit.contain:全图显示,显示原比例,可能会有空隙。

BoxFit.cover:显示可能拉伸,可能裁切,充满(图片要充满整个容器,还不变形)。

BoxFit.fitWidth:宽度充满(横向充满),显示可能拉伸,可能裁切。

BoxFit.fitHeight :高度充满(竖向充满),显示可能拉伸,可能裁切。

BoxFit.scaleDown:效果和contain差不多,但是此属性不允许显示超过源图片大小,可小不可大。
图片的背景颜色混合模式设置

color:是要混合的颜色,如果你只设置color是没有意义的。
colorBlendMode:是混合模式,相当于我们如何混合

图片混合模式(colorBlendMode)和color属性配合使用,能让图片改变颜色,里边的模式非常的多,产生的效果也是非常丰富的。
效果:
flutter学习总结(语法,组件,布局,和路由)_第8张图片

repeat图片重复属性

ImageRepeat.repeat : 横向和纵向都进行重复,直到铺满整个画布。

ImageRepeat.repeatX: 横向重复,纵向不重复。

ImageRepeat.repeatY:纵向重复,横向不重复。
flutter学习总结(语法,组件,布局,和路由)_第9张图片

ListView列表循环组件

下面我们使用了ListView,然后在他的内部children中,使用了widget数组,因为是一个列表,所以它接受一个数组,然后有使用了listTite组件(列表瓦片),在组件中放置了图标和文字。
flutter学习总结(语法,组件,布局,和路由)_第10张图片
上面默认就是纵向列表,怎样变为横向列表你,在ListView组件里,设置scorllDirectin属性值为Axis.horizontal即可.
flutter学习总结(语法,组件,布局,和路由)_第11张图片
上面内容不能写死,怎样使用动态列表呢?
用dart语言准备数组,数组的声明方式有以下几种方式:

var myList = List(): 非固定长度的声明。
var myList = List(2): 固定长度的声明。
var myList= List():固定类型的声明方式。
var myList = [1,2,3]: 对List直接赋值。

我声明和接收如下
flutter学习总结(语法,组件,布局,和路由)_第12张图片
使用后显示如下:
flutter学习总结(语法,组件,布局,和路由)_第13张图片

GridView网格列表组件

// 网格布局的基本使用

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'GridView',
        home: Scaffold(
            body: GridView.count(
          padding: const EdgeInsets.all(20.0),
          crossAxisSpacing: 10.0,
          crossAxisCount: 3, //每行显示的列数
          children: <Widget>[
            Icon(Icons.ac_unit),
            Icon(Icons.airport_shuttle),
            Icon(Icons.all_inclusive),
            Icon(Icons.beach_access),
            Icon(Icons.cake),
            Icon(Icons.free_breakfast)
          ],
        )));
  }
}

常用属性:

padding:表示内边距,这个应该很熟悉。
crossAxisSpacing:网格间的空当,相当于每个网格之间的间距。
crossAxisCount:网格的列数,相当于一行放置的网格数量。

GridView用来图片布局:
注意第一个gridDelegate属性,它有两个参数,如下所示,第一个表示以数量布局,第二个表示以内容布局.
在这里插入图片描述
具体使用如下:

//图片布局
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'GridView',
        home: Scaffold(
            body: GridView(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 3,
              mainAxisSpacing: 2.0,
              crossAxisSpacing: 2.0,
              childAspectRatio: 0.7),
          children: <Widget>[
            new Image.network(
                'https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2571762536.webp'),
            new Image.network(
                'https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2571762536.webp'),
            new Image.network(
                'https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2571762536.webp'),
            new Image.network(
                'https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2571762536.webp'),
            new Image.network(
                'https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2571762536.webp'),
            new Image.network(
                'https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2571762536.webp'),
            new Image.network(
                'https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2571762536.webp'),
            new Image.network(
                'https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2571762536.webp'),
            new Image.network(
                'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2567998580.webp'),
            new Image.network(
                'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2567998580.webp'),
            new Image.network(
                'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2567998580.webp'),
          ],
        )));
  }
}

效果:
flutter学习总结(语法,组件,布局,和路由)_第14张图片

说明:
childAspectRatio:是宽高比,这个值的意思是宽是高的多少倍,如果宽是高的2倍,那我们就写2.0,如果高是宽的2倍,我们就写0.5。

三.布局

水平布局Row的使用

Row控件就是水平控件,它可以让Row里边的子元素进行水平排列,Row控件可以分为不灵活排列和灵活排列两种.

不灵活排列(默认)

从字面上就可以理解到,不灵活就是根据Row子元素内容的大小,进行布局。如果子元素内容不足,它会留有空隙,如果子元素内容超出,它会警告.

import 'package:flutter/material.dart';
void main(){
  runApp(MyApp());
}

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return MaterialApp(
      title:"Row布局",
      home:Scaffold(
        appBar: AppBar(title:Text('头部')),
        body:Row(
          children:<Widget>[
            RaisedButton(
              child:Text('蓝色按钮'),
              color:Colors.lightBlue,
              onPressed:(){}
            ),
            RaisedButton(
              child:Text('红色按钮'),
              color:Colors.redAccent,
              onPressed:(){}
            ),
            RaisedButton(
              child:Text('黄色按钮黄色按钮黄色按钮黄色按钮黄色按钮黄色按钮'),//文字超出会警告
              color:Colors.orangeAccent,
              onPressed: (){},
            )
          ]
        )
      )
    );
  }
}

小坑:如果按钮不写onPressed属性,背景颜色不会出来.
效果:
flutter学习总结(语法,组件,布局,和路由)_第15张图片
假设上面"黄色按钮""只留四个字,那会出现下面没有充满的情况,
flutter学习总结(语法,组件,布局,和路由)_第16张图片
怎么让它刚好充满呢,这就用到我们的灵活布局了.

灵活布局

灵活布局只要在按钮的外边加入Expanded就可以,它会自动填充一屏.

import 'package:flutter/material.dart';
void main(){
  runApp(MyApp());
}

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return MaterialApp(
      title:'切换文字',
      home:Scaffold(
        appBar:AppBar(title:Text("灵活水平布局")),
        body:Row(
          children: <Widget>[
            RaisedButton(
              child: Text("蓝色按钮"),
              color:Colors.lightBlue,
              onPressed: (){},
            ),
            Expanded(
              child:RaisedButton(
                child:Text('红色按钮'),
                color:Colors.redAccent,
                onPressed: (){},
              )
            ),
            Expanded(
              child:RaisedButton(
                child:Text('黄色按钮'),
                onPressed:(){},
                color:Colors.orangeAccent
              )
            )
          ],
        )

      )
    );
  }
}

flutter学习总结(语法,组件,布局,和路由)_第17张图片
灵活水平布局和不灵活水平布局可以互相结合使用.

Column垂直布局的使用

// 垂直布局

import 'package:flutter/material.dart';
void main (){
  runApp(MyApp());
}

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return MaterialApp(
      title:'',
      home:Scaffold(
        appBar:AppBar(title:Text('垂直布局')),
        body:Column(
          mainAxisAlignment:MainAxisAlignment.center,//主轴
          crossAxisAlignment: CrossAxisAlignment.start,//副轴
          children: <Widget>[
            Text('第一行第一行第一行'),
           Expanded(
             child: Text('第二行'),//这里自适应
           ) ,
            Text('第三行第三行第三行第三行第三行第三行第三行')
          ],
        )
      )
    );
  }
}

flutter学习总结(语法,组件,布局,和路由)_第18张图片

Stack,Positioned层叠布局的使用

水平布局和垂直布局确实很好用,但是有一种情况是无法完成的,比如放入一个图片,图片上再写一些字或者放入容器,这时候Row和Column就力不从心了。Flutter为这种情况准备了Stack层叠布局.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: '',
        home: Scaffold(
            appBar: AppBar(
              title: Text("Stack层叠布局"),
            ),
            body: Center(
                child: new Stack(
              alignment: const FractionalOffset(0.5, 0.8),
              children: <Widget>[
                new CircleAvatar(
                  backgroundImage: new NetworkImage(
                      'https://avatars1.githubusercontent.com/u/45531884?s=460&v=4'),
                  radius: 100.0,
                ),
                new Container(
                    decoration: new BoxDecoration(color: Colors.lightBlue),
                    padding: EdgeInsets.all(5.0),
                    child: new Text('我是层叠文本'))
              ],
            ))));
  }
}

flutter学习总结(语法,组件,布局,和路由)_第19张图片
alignment属性:是控制层叠的位置的,建议在两个内容进行层叠时使用。它有两个值X轴距离和Y轴距离,值是从0到1的,都是从上层容器的左上角开始算起的。

CircleAvatar头像组件:这个经常用来做头像,组件里边有个radius的值可以设置图片的弧度。

Stack层叠的Position属性

当背景上层叠的组件超过两个时,我们可以考虑用Position定位属性,层叠定位无需alignment属性,直接给定位设置对应定位的坐标即可,操作如下:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: '',
        home: Scaffold(
            appBar: AppBar(
              title: Text("Stack层叠布局"),
            ),
            body: Center(
                child: new Stack(children: <Widget>[
              new CircleAvatar(
                  backgroundImage: new NetworkImage(
                      'https://avatars1.githubusercontent.com/u/45531884?s=460&v=4'),
                      radius: 100.0,
                      ),
              new Positioned(
                top:10.0,
                left:40.0,
                child:Text('定位内容1')
              ),
              new Positioned(
                right: 50.0,
                bottom: 20.0,
                child:Text('定位内容2')
              )
            ]))));
  }
}

flutter学习总结(语法,组件,布局,和路由)_第20张图片
Positioned组件的位置属性

bottom: 距离层叠组件下边的距离
left:距离层叠组件左边的距离
top:距离层叠组件上边的距离
right:距离层叠组件右边的距离
width: 层叠定位组件的宽度
height: 层叠定位组件的高度

Card卡片组件布局

这个布局可以做出很炫的东西,比如我们现在要开发一个类似收获地址的列表,并且列表外部使用一个卡片式布局,代码如下:

// 卡片布局
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: '',
        home: Scaffold(
            appBar: AppBar(title: Text('card布局')),
            body: Center(
                child: new Card(
              child: Column(
                //定义垂直布局
                children: <Widget>[
                  ListTile(//每个瓦片
                      title: Text("广东省深圳市龙华区",
                          style: TextStyle(fontWeight: FontWeight.w600)), //标题
                      subtitle: Text('电话:13800138000'), //第二行标题
                      leading: Icon(Icons.account_box, color: Colors.red) //左边内容
                      ) ,
                      new Divider(),//增加边框
                    ListTile(
                      title:Text("广东省深圳市龙华区广东省深圳市龙华区",style:TextStyle(fontWeight:FontWeight.w600)),
                      subtitle: Text('电话:13800138000'),
                      leading:Icon(Icons.add_location,color:Colors.lightBlue)
                    ),
                    new Divider(color:Colors.red),
                    ListTile(
                      title:Text("广东省深圳市龙华区广东省深圳市龙华区",style:TextStyle(fontWeight:FontWeight.w600)),
                      subtitle: Text('电话:13800138000'),
                      leading:Icon(Icons.add_location,color:Colors.lightBlue)
                    ),
                    new Divider(color:Colors.blue)
                ],
              ),
            ))));
  }
}

flutter学习总结(语法,组件,布局,和路由)_第21张图片

四.路由导航

1.页面跳转的应用:

导航的使用在任何程序里都至关重要,这也是一个程序的灵魂.下面先来一个一般页面的导航和返回,代码如下:

import 'package:flutter/material.dart';

void main(){
 runApp(
   MaterialApp(
     title:'路由导航',
     home:new FirstScreen()
   )
 );
}

class FirstScreen extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return Scaffold(
      appBar:AppBar(title:Text('点击下面跳转查看详情页面')),
      body:Center(
        child: new RaisedButton(
          child:Text("去详情页面"),
          onPressed:(){
            Navigator.push(context,
            MaterialPageRoute(builder:(context){
              return SecondScreen();
            })
            );
          }
        ),
      )

    );
  }
}

class SecondScreen extends StatelessWidget{
  @override
  Widget build(BuildContext context){
    return MaterialApp(
      home:Scaffold(
        appBar: AppBar(title:Text("这是详情页")),
        body:Center(
          child:
          RaisedButton(
            child:Text('返回上一页'),
            onPressed:(){
              Navigator.pop(context);//返回上一页,直接调用pop方法,把上下文传过去即可
            }
          )
        )
      )
    );
  }
}

路由的Navigator.push()和Navigator.pop()方法说明:
Navigator.push():是跳转到下一个页面,它接收两个参数,参数1是上下文,参数2是MaterialPageRoute()组件,里面有一个builder属性,值是一个函数,参数是上下文,内容是要跳转的页面组件即可.
实现效果:
flutter学习总结(语法,组件,布局,和路由)_第22张图片

2.页面跳转的参数传递

import "package:flutter/material.dart";

// 准备一个商品信息的抽象类

class Product{
  final String title;//商品标题
  final String description;//商品描述
  Product(this.title,this.description);
}

void main(){
  runApp(MaterialApp(
    title:"参数传递案例",
    home:ProductList(
      // 下面是相当于声明了一个数组
      products:List.generate(50,(index)=>
        Product('商品$index','这是商品详情,编号为$index')
      ),
    )
  ));
}


class ProductList extends StatelessWidget{
  
  final List<Product> products;// 引入上面的数组
  ProductList({Key key,@required this.products}):super(key:key);//挂载在当前组件上,除了this.products,其它是固定写法
  @override
  Widget build(BuildContext context){
    return Scaffold(
      appBar: AppBar(title:Text('商品列表页')),
      body:ListView.builder(//动态列表
        itemCount:products.length,
        itemBuilder: (context,index){
          return ListTile(//每个瓦片
              title:Text(products[index].title),//瓦片内容
              onTap: (){
                Navigator.push(context, MaterialPageRoute(
                  builder: (context)=>ProductDetail(product:products[index])//括号里的是传递值
                ));
              },
          );
        },
      )
    );
  }
}

class ProductDetail extends StatelessWidget{
  //接收上面传递的值
  final Product product; //二三是抽象类和上面传递的属性
  ProductDetail({Key key,@required this.product}):super(key:key);
  @override 
  Widget build(BuildContext context){
    return Scaffold(
      appBar: AppBar(title:Text(product.title)),
      body:Center(child: Text(product.description),)
    );
  }
}

说明:在点击商品列表的时候,我们用product属性将里面的products(商品信息,里面有标题和描述)传递了出去,在ProductDetail页面组件中进行了接收和使用.

实现效果:
flutter学习总结(语法,组件,布局,和路由)_第23张图片

3.返回页面携带参数
import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(title: '返回页面参数传递', home: FirstPage()));
}

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text("找小姐姐的电话")),
        body: Center(
            child: RouteButton()));
  }

}

class RouteButton extends StatelessWidget{
  @override 
  Widget build(BuildContext context){
    return RaisedButton(
          child: Text('去找小姐姐'),
          onPressed: () {
            //下面这里调用异步请求,把上下文传递过去
            _navigateToXiaoJieJie(context);
          },
        );
  }
   //在组件里准备异步请求函数,里面也是两个上下文方法,大括号前记得写async
  _navigateToXiaoJieJie(BuildContext context) async {
    final result = await Navigator.push(
        context, MaterialPageRoute(builder: (context) => XiaoJieJie()));
    //返回后的数据显示
    Scaffold.of(context).showSnackBar(SnackBar(
      content: Text('$result'),
    ));
  }
}

 

class XiaoJieJie extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text("请选择你要的小姐姐")),
        body: Center(
            child: Column(
          children: <Widget>[
            RaisedButton(
              child: Text("大长腿小姐姐"),
              onPressed: () {
                Navigator.pop(context, "大长腿电话:1511008888");
              },
            ),
            RaisedButton(
              child: Text("小长腿小姐姐"),
              onPressed: () {
                Navigator.pop(context, "小长腿电话:1511009999");
              },
            ),
          ],
        )));
  }
}

效果:
flutter学习总结(语法,组件,布局,和路由)_第24张图片
最后,附上源码链接地址:[email protected]:huanggengzhong/flutter.git

你可能感兴趣的:(十八.Flutter)