Flutter学习总结之四 常见Widget及页面跳转

一.常见布局方式

  • Row,是水平方向的线性布局(linearlayout)

  • Column,是垂直方向的线性布局(linearlayout)

  • Stack,可以理解成为相对布局。

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Welcome to Flutter',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Welcome to Flutter'),
        ),
        body: new Center(
          child: new Column(
            children: <Widget>[
              new Text('Text 1'),
              new Text('Text 2'),
              new Text('Text 3')
            ],),),),);}
}

二.事件

在 Flutter 中,有两种方法来添加点击监听者:
1、如果 widget 本身支持事件监测,直接传递给它一个函数,并在这个函数里实现响应方法。例如,RaisedButton、IconButton、OutlineButton、Checkbox、SnackBar、Switch等。

body:Center(
  child: OutlineButton(
    child: Text('点击我'),
     onPressed: (){
          Fluttertoast.showToast(
                    msg: '你点击了FlatButton',
            toastLength: Toast.LENGTH_SHORT,
                gravity: ToastGravity.CENTER,
        timeInSecForIos: 1,
     );
  }),
),

2、如果 widget 本身不支持事件监测,则在外面包裹一个 GestureDetector,并给它的 onTap 属性传递一个函数:

class SampleApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: GestureDetector(
          child: FlutterLogo(
            size: 200.0,
          ),
          onTap: () {
            print("tap");
          },
        ),
      ),
    );
  }
}

3、widget 上的其他手势

属性 取值意义
onTapDwon 当按下屏幕时触发
onTap 当与屏幕短暂地触碰时触发,最常用
onTapUp 当用户停止触碰屏幕时触发
onTapCancel 当用户触摸屏幕,但没有完成Tap事件时触发
onDoubleTap 快速双击屏幕时触发
onLongPress 当长按屏幕时触发(与屏幕接触事件必须超过500ms)
onPanUpdate 当在屏幕上移动时触发
onVerticalDragDown 当手指触碰屏幕且准备往屏幕垂直方向移动时触发
onVerticalDragStart 当手指触碰屏幕且开始往屏幕垂直方向移动时触发
onVerticalDragUpdate 当手指触碰屏幕且开始往屏幕垂直方向移动并发生位移时触发
onVerticalDragEnd 当用户完成垂直方向触摸屏幕时触发
onVerticalDragCancel 当用户中断了onVerticalDragDown时触发
onHorizontalDragDown 当手指触摸屏幕且准备往屏幕水平方向移动时触发
onHorizontalDragStart 当手指触摸屏幕且开始往屏幕水平方向移动时触发
onHorizontalDragUpdate 当手指触摸屏幕且开始往屏幕水平方向移动并发生位移时触发
onHorizontalDragEnd 当用户完成水平方向触摸屏幕时触发
onHorizontalDragCancel 当用户中断了onHorizontalDragDown时触发
onPanDown 当用户触摸屏幕时触发
onPanStart 当用户触摸屏幕并开始移动时触发
onPanUpdate 当用户触摸屏幕并产生移动时触发
onPanEnd 当用户完成触摸屏幕时触发
onScaleStart 当用户触摸屏幕并开始缩放时触发
onScaleUpdate 当用户触摸屏幕并产生缩放时触发
onScaleEnd 当用户完成缩放时触发

三.跳转页面(路由和导航)

Flutter 中万物皆 Widget,页面自然也是一个 Widget。只不过是一个全屏的 Widget。在flutter中三种页面跳转方式:无名路由跳转(一种动态构建路由的方式)、命名路由跳转(一种提前命名路由的方式)

1.无名路由跳转

直接使用使用 Navigator 跳转页面,在 Flutter 中,使用 Navigator 来进行页面跳转。一个简单的跳转页面的例子:

          Navigator.push(
            context,
            MaterialPageRoute(
            // 目标页面,即一个 Widget
              builder: (context) => PageA(),
            ),
          );

或者

          Navigator.of(context).push(
            MaterialPageRoute(
              builder: (context) => PageA(),
            ),
          );

关闭A页面返回到上一个页面

Navigator.pop(context);

或者

 Navigator.of(context).pop();

2.命名路由跳转

命名路由路由存在的意义在于可以让我们更方便的导航到想要到达的页面,便于管理和维护。

void main() => runApp(MyApp());//单行函数调用写法
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "My App Title",
      theme: ThemeData(primaryColor: Colors.green),
      //home: RandomWord(),//初始路由页面一
      initialRoute: "one_route",//初始路由页面二
      routes: {
        //路由注册表
        "second_page": (BuildContext context) {
          return NextPage(ModalRoute.of(context).settings.arguments);
        },
        "one_route": (BuildContext context) => RandomWord(),
      },
    );
  }
}

可以通过刚刚注册的页面名称来跳转一个页面:

Navigator.pushNamed(context, 'one_route');// one_route表示页面别名

3.接收参数

传递的方式有两种:

  • 在构造方法中传递数据
  • 在Route中传递数据给下一个页面

(1)构造方法中传递数据
需要在接收数据的页面事先定义好构造方法,构造方法中是要接收的参数。例如:我们在PageB中定义一个构造方法,构造方法中可以定义我们要接收的数据:

import 'package:flutter/material.dart';

class PageB extends StatelessWidget {
  String data;

  PageB({this.data});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("B页面"),
        leading: InkWell(
          onTap: () {
            Navigator.pop(pageContext);
          },
          child: Icon(
            Icons.arrow_back,
          ),
        ),
      ),
      body: Center(
        child: Text(data),
      ),
    );
  }
}

跳转页面时给PageB传递数据:

    Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => PageB(
                    data: "要传递的数据",
                  ),
            ),
          );

(2)将参数传递给指定路由
方式一不是太灵活。Flutter也提供了类似于Android那种通过Intent传值的方式,在Flutter中我们可以把要传递的参数放到Navigator中,然后传递给指定的路由,在接收的页面提取出需要的参数即可,这种方式相比方式一更加灵活一些。通过路由进行导航时用到了Navigator.pushNamed(context, pageA);这个方法,实际上这个方法还有第三个参数,
1.首先我们要先定义好要传递的数据
例如:
我们先定义一个实体类:

class People {
  String name;
  int age;
  People(this.name, this.age);
}

2.传递参数
将参数数据传递给PageB,可以有如下四种传参方式,效果都一样

          Navigator.pushNamed(
            context,
            pageB,
            arguments: People("yzq", 25),//要传递的数据
          );

或者

Navigator.of(context).pushNamed(pageB, arguments: People("yzq", 25));

或者·

Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => PageB(),
              settings: RouteSettings(
                arguments: People("yuzhiqiang", 26),
              ),
            ),
          );

或者

          Navigator.of(context).push(
            MaterialPageRoute(
                builder: (context) => PageB(),
                settings: RouteSettings(
                    arguments: People("yuzhiqiang", 26),
                )
            ),
          );

3.接收参数

在PageB接收数据,接收数据要通过 ModalRoute.of 方法。此方法返回带有参数的当前路由。

import 'package:flutter/material.dart';
import 'package:flutter_router/people.dart';

class PageB extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    /*获取传递过来的参数*/
    People _people = ModalRoute.of(context).settings.arguments;

    return Scaffold(
      appBar: AppBar(
        title: Text("B页面"),
        leading: InkWell(
          onTap: () {
            Navigator.pop(context);
          },
          child: Icon(
            Icons.arrow_back,
          ),
        ),
      ),
      body: Center(
        child: Text("姓名:${_people.name},年龄:${_people.age}"),
      ),
    );
  }
}

更多信息参考 Navigator API

Flutter布局方式总
Flutter 初尝试:入门教程
GSY Flutter 系列专栏
flutter中文网
Flutter入门进阶之旅

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351