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,这时候打包成功,可在build\app\outputs\apk\release\找到

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

原文地址:https://www.cnblogs.com/jyd0124/p/Widget2.html

时间: 2024-10-26 04:36:17

Flutter开发之Widget布局和页面导航的相关文章

Flutter开发之Widget学习

一.Text 组件 属性 textAlign: TextAlign.left,                           -----文本对齐方式 maxLines: 1,                                            -----显示最大行 overflow: TextOverflow.clip,                 -----文本溢出的处理方式 clip:直接切断溢出的文字. ellipsis:在后边显示省略号(...)  常用 fa

iOS 开发之Widget的开发及使用(下)

在iOS 开发之Widget的开发及使用(上)中都交代清楚了关于widget扩展的添加,以及布局部分的内容,下面说下关键部分:关于数据共享的操作. 在Apple发布iOS8.0以后,对App有提供一个新的扩展选择项,叫做App groups,选择宿主Target之后,在capabilities选项卡下面会找到这个选项: 那么这个选项主要是做何使用呢? iOS系统,每个开发应该都清楚,其内部程序都是遵循沙盒机制,App与App之间,是不能进行数据共享的,A 不能访问 B 的数据,同样 B 也不能访

Google glass Mirror app开发之HTML布局之标签篇

$_[.=.]  原谅我不太会写标题.. 谷歌眼镜开发 之 Mirror api开发之 HTML布局之 css样式 之xxx... 好了,进入正题,在https://developers.google.com/glass/tools-downloads/playground中可以实时地预览效果 CSS样式文件:https://mirror-api-playground.appspot.com/assets/css/base_style.css Mirror API - Timeline:http

iOS 开发之Widget的开发及使用(上)

在iOS8发布以后,Apple官方发布了,有关第三方开发软件可以集成进手机的通知中心,对于我们这帮开发来说,无疑是一个很新鲜的玩意儿,都巴不得赶紧将自己的App加入Widget的功能扩展. 那么关于widget的功能扩展需要做的步骤,我简单的分享一下我个人的简单过程.不对望斧正.我将会分为两次分别概述widget的基本添加以及布局和数据共享部分. 首先,在自己的在xcode的菜单项,为当前项目添加一个新的target.然后选择Application Extension 类型选Today. 接下来

iOS开发之widget实现

前言 ????iOS extension的出现,方便了用户查看应用的服务,比如用户可以在Today的widgets中查看应用的简略信息,然后点击进入相关的应用界面.暂且不表网络上现有的widget文章,本篇文章主要说明本人具体实现widget的步骤,希望能够帮助到需要实现widget的同行朋友. 图1 Today的widget展示----以支付宝为例说明 文章将依次从以下几个问题着手,进行详细说明:1.如何为现有的工程添加widget:2.如何绘制UI:3.如何调起app:4.如何与host a

HTML5移动开发之Flexbox布局讲解与使用技巧

现在来详细介绍一下Flexbox布局语法跟使用.大家可能非常关心以下几个问题: 1 .什么是Flexbox布局? 2. Flexbox布局主要用于什么场景? 3. Flexbox布局它的语法是什么? 4. 如何实际使用Flexbox布局? 5. Flexbox布局它的缺陷是什么? 下面就这五个问题给大家分析分析.希望给那些想尝试用Flexbox的行内人有所帮助. 在恰当的地方能够使用恰当的布局方法,如果有说的不到位,希望大家指正,一起进步. 1 .什么是Flexbox布局? 1.1 W3C解释

IOS开发之UI布局

前言:本篇随笔会经常更新,随着本人对布局的深入学习,会不断补充新的知识.新的使用技巧.新的认识等等. 1.Autoresizing(在代码中使用) 先简单的看看下面的代码,以及左边运行出来的效果,然后后面就会对iPhone模拟器进行旋转,再看看效果,然后结合代码中的autoresizingMask属性来体会一下: 横屏之后,说明竖屏默认的frame(0,0,100,500)换到横屏之后会默认在中间一些的位置,但是因为上面设置autoresizingMask属性是左边和上边自动伸缩: 以上就是基本

浅谈android4.0开发之GridLayout布局

作者:李响 本文重点讲述了自android4.0版本号后新增的GridLayout网格布局的一些基本内容,并在此基础上实现了一个简单的计算器布局框架.通过本文,您可以了解到一些android UI开发的新特性,并可以实现相关应用. 在android4.0版本号之前,假设想要达到网格布局的效果,首先能够考虑使用最常见的LinearLayout布局,可是这种排布会产生例如以下几点问题: 1.不能同一时候在X,Y轴方向上进行控件的对齐. 2.当多层布局嵌套时会有性能问题. 3.不能稳定地支持一些支持自

Android入门开发之Linearlayout布局(七)

前言 上一节我们主要讲解了linux下的权限说明,今天我们来了解一下Android中的UI设计,聊聊android中常用的布局. android中的布局主要有六种,分别是线性布局(LinearLayout),相对布局(Relativelayout),帧布局(FrameLayout),网格布局(GridLayout)以及绝对布局(AbsoluteLayout)和表格布局(TableLayout),在这六种布局中,我们比较常用的就是线性布局和相对布局以及帧布局,所以在布局方面,我打算主要围绕这三个布