• Flutter开发之Widget布局和页面导航


    摘自:https://www.cnblogs.com/jyd0124/p/Widget2.html

    Flutter开发之Widget布局和页面导航

     

    一、水平布局Row

    Row控件可以分为非灵活排列和灵活排列两种,灵活的可以在外边加入Expanded使用

    两者混用:

    import 'package:flutter/material.dart';
    void main() => runApp(MyApp());
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return MaterialApp(
          title: '',
          home: new Scaffold(
            appBar: new AppBar(title: new Text('hello row')),
            body: new Row(
              children: <Widget>[
                Expanded(                      //灵活使用
                    child: new RaisedButton(
                      onPressed: () {},
                      color: Colors.blue,
                      child: new Text('Blue Button'),
                    )),
                new RaisedButton(
                  onPressed: () {},
                  color: Colors.green,
                  child: new Text('Green Button'),
                ),
              ],
            ),
          ),
        );
      }
    }

    二、垂直布局Column

          对齐方式:

    • main轴: 比如Row组件,那水平就是主轴。比如Column组件,那垂直就是主轴。

    • cross轴:比如Row组件,那垂直就是副轴。比如Columu组件,那水平就是副轴。
    import 'package:flutter/material.dart';
    void main() => runApp(MyApp());
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return MaterialApp(
          title: '',
          home: new Scaffold(
            appBar: new AppBar(title: new Text('hello Column')),
            body: new Center(
              child: new Column(
                crossAxisAlignment: CrossAxisAlignment.center, //副轴对齐方式
                mainAxisAlignment: MainAxisAlignment.center, //主轴对齐方式
                children: <Widget>[
                  new Text('君不见黄河之水天上来,',
                      style: TextStyle(
                        color: Colors.black,
                        fontSize: 30.0,
                      )),
                  new Text('东流到海不复还,',
                      style: TextStyle(
                        color: Colors.redAccent,
                        fontSize: 30.0,
                      )),
                ],
              ),
            ),
          ),
        );
      }
    }

    三、层叠布局Stack

    alignment属性:控制层叠的位置

    alignment: const FractionalOffset(dx,dy) dx、dy 为0~1
    import 'package:flutter/material.dart';
    void main() => runApp(MyApp());
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        var stack = new Stack(
          alignment: const FractionalOffset(0.5, 0.8),
          children: <Widget>[
            new CircleAvatar(
              backgroundImage:
                  new NetworkImage('https://profile.csdnimg.cn/0/5/2/1_jyd0124'),
              radius: 100.0,
            ),
            new Container(
              decoration: BoxDecoration(
                color: Colors.cyan,
              ),
              child: new Text('blog_jyd0124'),
              padding: EdgeInsets.all(5.0),
            ),
          ],
        );
        // TODO: implement build
        return MaterialApp(
          title: '',
          home: new Scaffold(
            appBar: new AppBar(title: new Text('hello Stack')),
            body: new Center(child: stack),
          ),
        );
      }
    }

    说明:CircleAvatar组件经常用来作头像,radius属性可以设置图片的弧度

    Stack布局高级用法:Positioned(层叠定位组件)用于层叠多个组件

    var stack = new Stack(
          //alignment: const FractionalOffset(0.5, 0.8),
          children: <Widget>[
            new CircleAvatar(
              backgroundImage:
                  new NetworkImage('https://profile.csdnimg.cn/0/5/2/1_jyd0124'),
              radius: 100.0,
            ),
            new Positioned(
                bottom: 20.0,
                left: 60.0,
                child: new Container(
                  decoration: BoxDecoration(
                    color: Colors.cyan,
                  ),
                  child: new Text('blog_jyd0124'),
                  padding: EdgeInsets.all(5.0),
                )),
          ],
        );

    四、卡片布局Card

    import 'package:flutter/material.dart';
    void main() => runApp(MyApp());
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        var card = new Card(
          child: new Column(
            children: <Widget>[
              ListTile(
                title: new Text('成都市',style:TextStyle(fontWeight:FontWeight.w100)),
                subtitle: new Text('QQ:150048****'),
                leading: new Icon(Icons.account_balance,color: Colors.blue,),
              ),
              ListTile(
                title: new Text('西安市',style:TextStyle(fontWeight:FontWeight.w100)),
                subtitle: new Text('QQ:150048****'),
                leading: new Icon(Icons.account_balance,color: Colors.blue,),
              ),
              ListTile(
                title: new Text('兰州市',style:TextStyle(fontWeight:FontWeight.w100)),
                subtitle: new Text('QQ:150048****'),
                leading: new Icon(Icons.account_balance,color: Colors.blue,),
              ),
            ],
          )
        );
        // TODO: implement build
        return MaterialApp(
          title: '',
          home: new Scaffold(
            appBar: new AppBar(title: new Text('hello Column')),
            body: new Center(child: card),
          ),
        );
      }
    }

     五、页面的导航和返回

           1.RaisedButton按钮组件

              两个常用属性:

    • child:可以放入容器,图标,文字
    • onPressed:事件的响应,一般调用Navigator组件

           2.Navigator组件

    • Navigator.push()   =====跳转到下一个页面,接受两个参数一个是上下文context,另一个是要跳转的函数。
    • Navigator.pop()     =====返回到上一个页面,接受一个context(上下文)参数
    import 'package:flutter/material.dart';
    
    void main() => runApp(MaterialApp(
          title: '导航演示',
          home: new FirstScreen(),
        ));
    
    class FirstScreen extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return Scaffold(
          appBar: AppBar(
            title: Text(''),
          ),
          body: Center(
            child: RaisedButton(
                child: Text('跳转'),
                onPressed: () {
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) => new SecondScreen(),
                      ));
                }),
          ),
        );
      }
    }
    
    class SecondScreen extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return Scaffold(
          body: new Scaffold(
            appBar: new AppBar(title: new Text('跳转完成')),
            body: new Center(
                child: RaisedButton(
              child: Text('返回'),
              onPressed: () {
                Navigator.pop(context);
              },
            )),
          ),
        );
      }
    }

     六、导航参数的传递和接收

    import 'package:flutter/material.dart';
    
    class Product {
      String title;
      String description;
      Product(this.title, this.description);
    }
    
    void main() {
      runApp(MaterialApp(
        title: '导航的数据传递和接受',
        home: ProductList(
            products:
                List.generate(20, (i) => Product('商品 $i', '这是一个商品详情,编号为 $i'))),
      ));
    }
    
    class ProductList extends StatelessWidget {
      final List<Product> products;
      ProductList({Key key, @required this.products}) : super(key: key);
      @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}'),
          ),
        );
      }
    }
    • 小技巧 :Android Studio 中输入stless可以自动生成StatelessWidget,但在VSCode中,需先安装Awesome Flutter snippets插件,然后输入stlss;

    七、页面跳转并返回数据

      1.异步请求与等待

               使用async...await

      2.SnackBar

               显示提示信息的一个控件,会自动隐藏,SnackBar是以Scaffold的showSnackBar()方法来进行显示的;

      3.返回数据

               Navigator.pop()带第二个参数就可以

    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(
          onPressed: () {
            navigateToNumber(context);
          },
          child: Text('Get'),
        );
      }
    
      navigateToNumber(BuildContext context) async {
        //async是启用异步方法
        final result = await Navigator.push(
            //等待
            context,
            MaterialPageRoute(builder: (context) => Number()));
        Scaffold.of(context).showSnackBar(SnackBar(content: Text('$result')));
      }
    }
    
    class Number 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, '两位数:98');
                  },
                ),
                RaisedButton(
                  child: Text('三位数'),
                  onPressed: () {
                    Navigator.pop(context, '三位数:124');
                  },
                ),
              ],
            ),
          ),
        );
      }
    }

     八、静态资源和项目图片的处理

        在pubspec.yaml文件中声明资源文件

        测试:

    import 'package:flutter/material.dart';
    
    void main()=>runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Image.asset('images/csdn.jpg'),
        );
      }
    }

      九、客户端打包(Android)

     1. 配置APP的图片的目录    /android/app/src/main/res/

     2.配置APP的名称、图标和系统权限的目录    /android/app/src/main/AndroidManifest.xml

      

     3.生成keystore

           <1> flutter doctor -v  命令找到keytool.exe的位置

            <2>cd进入这个目录,然后执行下面命令就会在D盘下面有一个jks的文件

      keytool -genkey -v -keystore D:key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key

              <3>到项目目录下的android文件夹下,创建一个名为key.properties的文件,并打开粘贴下面的代码

    storePassword=<password from previous step>    //输入上一步创建KEY时输入的 密钥库 密码
    keyPassword=<password from previous step>    //输入上一步创建KEY时输入的 密钥 密码
    keyAlias=key
    storeFile=<E:/key.jks>    //key.jks的存放路径

    4.配置key注册

         <1>进入项目目录的/android/app/build.gradle文件,在android{这一行前面,加入如下代码

    def keystorePropertiesFile = rootProject.file("key.properties")
    def keystoreProperties = new Properties()
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))

        <2>把如下代码进行替换

     替换成的代码:

    signingConfigs {
        release {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile file(keystoreProperties['storeFile'])
            storePassword keystoreProperties['storePassword']
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }

     5.生成apk

       在终端输入 flutter build apk,这时候打包成功,可在buildappoutputsapk elease找到

       然后在终端输入flutter install 直接安装到

     
    分类: 编程基础
    标签: AndroidFlutter
  • 相关阅读:
    ASP.NET -- repeater控件的使用
    在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。 (provider: 命名管道提供程序, error: 40
    错误提示:在此上下文中不允许使用名称 "***"。有效表达式包括常量、 常量表达式和变量(在某些上下文中),不允许使用列名。
    mongodb 性能提高之利用索引, 待续
    工程化 经历的 4 个阶段
    把连续的字符 变成 一个
    sort 排序详解
    理解正则 的 ?! ?:
    [ 订单查询 ] 性能 高并发 : 分表 与 用户id%1024 存放表
    搭建LNMP基础框架
  • 原文地址:https://www.cnblogs.com/xichji/p/12332420.html
Copyright © 2020-2023  润新知