Flutter基础笔记

简介: 目录List里面常用的属性和方法:SetMapforEach,map, where,any,everyextends抽象类 和 implementsFlutter环境搭建入口文件、入口方法第一个 Demo Center 组件的 使用把内容单独抽离成一个组件给 Text 组件增加一些装饰用MaterialApp 和 Scaffold两个组件装饰 AppText 组件Container 组件图片组件引入本地图片裁剪布局之 ClipRect、ClipRRect、ClipOval、ClipPath、CustomClipper实现圆角以及实现圆形图片圆形头像

目录

List里面常用的属性和方法:

Set

Map

forEach,map, where,any,every

extends抽象类 和 implements

Flutter环境搭建

入口文件、入口方法

第一个 Demo Center 组件的 使用

把内容单独抽离成一个组件

给 Text 组件增加一些装饰

用MaterialApp 和 Scaffold两个组件装饰 App

Text 组件

Container 组件

图片组件

引入本地图片

裁剪布局之 ClipRect、ClipRRect、ClipOval、ClipPath、CustomClipper

实现圆角以及实现圆形图片

圆形头像

ClipOval

② CircleAvatar

③ BoxDecoration BoxShape.circle

圆角头像

① ClipRRect

② BoxDecoration BoxShape.rectangle

列表组件概述

列表参数

基本列表

水平列表

动态列表(动态循环数据)

GridView 组件的常用参数

GridView.count 实现网格布局

GridView.builder 实现网格布局

Paddiing 组件

Row 水平布局组件

Column 垂直布局组件

Expanded 类似 Web 中的 Flex 布局

Stack 组件

Stack Align

Stack Positioned

AspectRatio 组件

Card 组件

Card 组件实现一个图文列表布局

RaisedButton 定义一个按钮

Wrap 组件

自定义有状态组件

BottomNavigationBar 组件

路由

基本路由使用

基本路由跳转传值

命名路由

命名路由跳转传值

命名路由单独抽离到一个文件

返回到上一级页面

替换路由

返回到根路由

AppBar 自定义顶部按钮图标、颜色

AppBar 中自定义 TabBar 实现顶部 Tab 切换

把 TabBar 放在导航最顶部

AppBar 中自定义 TabBar 实现 Tabs 的另一种方法。

Flutter Drawer 侧边栏

DrawerHeader

UserAccountsDrawerHeader

侧边栏路由跳转

按钮组件介绍

按钮组件中的一些属性

FloatingActionButton 介绍

常用表单介绍

TextField 文本框组件

Checkbox、CheckboxListTile 多选框组件

Radio、RadioListTile 单选按钮组件

开关 Switch

日期和时间戳

第三方库 date_format 的使用

调用自带日期组件和时间组件

调用自带日期组件和时间组件改为中文

调用第三方时间组件

轮播图组件

一、AlertDialog

二、SimpleDialog

三、showModalBottomSheet

四、showToast

自定义Dialog

定时器

定时器结合 Dialog

JSON 字符串和 Map 类型的转换(小项目)

使用 http 库进行网络请求

Dio 库

下拉刷新和上拉分页

下拉刷新

上拉分页加载更多

核心代码

完整代码

解决请求重复问题

滚动条回到顶部

参考代码

实现一个简单的新闻 APP

解析 html

WebView 组件 inappbrowser的使用

获取设备信息

使用高德定位准备工作获取 key

实现用高德定位

image_picker 实现相机拍照和相册选择

上传图片到服务器

视频播放

chewie 视频播放完整 demo

检测网络

检测网络完整 demo

本地存储

本地存储里面常用的一些方法

本地存储完整 demo

扫描二维码条形码插件

检测应用版本号、服务器下载文件以及实现 App 自动升级、安装

1、Android App 升级执行流程

2、升级 app 之前的准备工作配置权限

3、Android 升级 app 涉及的 API 库

4、获取版本信息

5、获取文件存储路径

6、下载文件

7、打开文件

8、注意事项

完整代码

调用 url_launcher 模块打开外部浏览器 打开外部应用 拨打电话 发送短信

Android 修改应用名称、应用图标、应用启动画面

**1**、Android 修改应用名称

**2**、Android 修改应用图标

**3**、Android 修改应用启动画面

竖向 ListView 嵌套横向 ListView ,以及ListView 嵌套 GridView

不同终端屏幕适配问题

JSON 序列化反序列化(模型类)

JSON字符串和Map类型的转换 dart:convert手动序列化 JSON

在模型类中序列化 JSON

json_to_dart 自动生成模型类

IndexedStack 保持页面状态

AutomaticKeepAliveClientMixin 保持页面状态

通过事件打开侧边栏

修改主题样式

下拉菜单 showMenu

弹出底部菜单

StatefulBuilder更新Flutter showDialog 、showModalBottomSheet 中的状态

状态管理

provider库和flutter provide库

provider 的使用

event_bus 事件广播 事件监听

MediaQuery.removePadding移除元素的pandding

瀑布流布局

Sliver牛逼!!!

适配夜间模式

夜间模式跟随系统

手动开启夜间模式

保存用户配置

状态管理

通用夜间模式Provider Model类

MaterialApp修改

登录注册案例

Flutter SliverAppBar 隐藏/显示导航栏

骨架屏

flutter 全屏背景图(包括appbar和状态栏)

极光推送:

指纹

List里面常用的属性和方法:

/*
List里面常用的属性和方法:
   常用属性:
       length          长度
       reversed        翻转
       isEmpty         是否为空
       isNotEmpty      是否不为空
   常用方法:  
       add         增加
       addAll      拼接数组
       indexOf     查找  传入具体值
       remove      删除  传入具体值
       removeAt    删除  传入索引值
       fillRange   修改   
       insert(index,value);            指定位置插入    
       insertAll(index,list)           指定位置插入List
       toList()    其他类型转换成List  
       join()      List转换成字符串
       split()     字符串转化成List
       forEach   
       map
       where
       any
       every
*/
void main(){
 // List myList=['香蕉','苹果','西瓜'];
 // print(myList[1]);
 // var list=new List();
 // list.add('111');
 // list.add('222');
 // print(list);
//List里面的属性:
   // List myList=['香蕉','苹果','西瓜'];
   // print(myList.length);
   // print(myList.isEmpty);
   // print(myList.isNotEmpty);
   // print(myList.reversed);  //对列表倒序排序
   // var newMyList=myList.reversed.toList();
   // print(newMyList);
//List里面的方法:
   // List myList=['香蕉','苹果','西瓜'];
   //myList.add('桃子');   //增加数据  增加一个
   // myList.addAll(['桃子','葡萄']);  //拼接数组
   // print(myList);
   //print(myList.indexOf('苹x果'));    //indexOf查找数据 查找不到返回-1  查找到返回索引值
   // myList.remove('西瓜');
   // myList.removeAt(1);
   // print(myList);
   // List myList=['香蕉','苹果','西瓜'];
   // myList.fillRange(1, 2,'aaa');  //修改
   //  myList.fillRange(1, 3,'aaa');  
   // myList.insert(1,'aaa');      //插入  一个
   // myList.insertAll(1, ['aaa','bbb']);  //插入 多个
   // print(myList);
   // List myList=['香蕉','苹果','西瓜'];
   // var str=myList.join('-');   //list转换成字符串
   // print(str);
   // print(str is String);  //true
   var str='香蕉-苹果-西瓜';
   var list=str.split('-');
   print(list);
   print(list is List);
}

Set

//Set 
//用它最主要的功能就是去除数组重复内容
//Set是没有顺序且不能重复的集合,所以不能通过索引去获取值
void main(){
  // var s=new Set();
  // s.add('香蕉');
  // s.add('苹果');
  // s.add('苹果');
  // print(s);   //{香蕉, 苹果}
  // print(s.toList()); 
  List myList=['香蕉','苹果','西瓜','香蕉','苹果','香蕉','苹果'];
  var s=new Set();
  s.addAll(myList);
  print(s);
  print(s.toList());
}

Map

/*
  映射(Maps)是无序的键值对:
    常用属性:
        keys            获取所有的key值
        values          获取所有的value值
        isEmpty         是否为空
        isNotEmpty      是否不为空
    常用方法:
        remove(key)     删除指定key的数据
        addAll({...})   合并映射  给映射内增加属性
        containsValue   查看映射内的值  返回true/false
        forEach   
        map
        where
        any
        every
*/
void main(){
  // Map person={
  //   "name":"张三",
  //   "age":20
  // };
  // var m=new Map();
  // m["name"]="李四";
  // print(person);
  // print(m);
//常用属性:
    // Map person={
    //   "name":"张三",
    //   "age":20,
    //   "sex":"男"
    // };
    // print(person.keys.toList());
    // print(person.values.toList());
    // print(person.isEmpty);
    // print(person.isNotEmpty);
//常用方法:
    Map person={
      "name":"张三",
      "age":20,
      "sex":"男"
    };
    // person.addAll({
    //   "work":['敲代码','送外卖'],
    //   "height":160
    // });
    // print(person);
    // person.remove("sex");
    // print(person);
    print(person.containsValue('张三'));
}

forEach,map, where,any,every

/*
        forEach     
        map         
        where       
        any
        every
*/
void main(){
      //  List myList=['香蕉','苹果','西瓜'];
      // for(var i=0;i<myList.length;i++){
      //   print(myList[i]);
      // }
      // for(var item in myList){
      //   print(item);
      // }
      // myList.forEach((value){
      //     print("$value");
      // });
      // List myList=[1,3,4];
      // List newList=new List();
      // for(var i=0;i<myList.length;i++){
      //   newList.add(myList[i]*2);
      // }
      // print(newList);
      // List myList=[1,3,4];      
      // var newList=myList.map((value){
      //     return value*2;
      // });
      //  print(newList.toList());
      // List myList=[1,3,4,5,7,8,9];
      // var newList=myList.where((value){
      //     return value>5;
      // });
      // print(newList.toList());
      // List myList=[1,3,4,5,7,8,9];
      // var f=myList.any((value){   //只要集合里面有满足条件的就返回true
      //     return value>5;
      // });
      // print(f);
      // List myList=[1,3,4,5,7,8,9];
      // var f=myList.every((value){   //每一个都满足条件返回true  否则返回false
      //     return value>5;
      // });
      // print(f);
      // set
      // var s=new Set();
      // s.addAll([1,222,333]);
      // s.forEach((value)=>print(value));
      //map
       Map person={
          "name":"张三",
          "age":20
        };
        person.forEach((key,value){            
            print("$key---$value");
        });
}

extends抽象类 和 implements

/*
Dart中抽象类: Dart抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类接口。
  1、抽象类通过abstract 关键字来定义
  2、Dart中的抽象方法不能用abstract声明,Dart中没有方法体的方法我们称为抽象方法。
  3、如果子类继承抽象类必须得实现里面的抽象方法
  4、如果把抽象类当做接口实现的话必须得实现抽象类里面定义的所有属性和方法。
  5、抽象类不能被实例化,只有继承它的子类可以
extends抽象类 和 implements的区别:
  1、如果要复用抽象类里面的方法,并且要用抽象方法约束自类的话我们就用extends继承抽象类
  2、如果只是把抽象类当做标准的话我们就用implements实现抽象类
*/

Flutter环境搭建

安装最新的 Xcode


下载androidstudio


https://developer.android.google.cn/studio


下载 Flutter SDK


https://flutter.dev/docs/development/tools/sdk/releases?tab=macos


把下载好的 Flutter SDK 随便减压到你想安装 Sdk 的目录如

/Users/cc/flutter

Flutter 安装目录的 bin 目录配置到环境变量,然后把 Flutter 国内镜像也配置到环境 变量里面

vim ~/.zshrc


export PATH=/Users/cc/flutter/bin:$PATH
export ANDROID_HOME="/Users/cc/Library/Android/sdk"
export PATH=${PATH}:${ANDROID_HOME}/tools
export PATH=${PATH}:${ANDROID_HOME}/platform-tools
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
source ~/.zshrc

flutter -h 如果能出来一些命令说明 flutter sdk 配置成功。


注意如果配置完成后输入 flutter -h 告诉你 flutter 不是内置命令之类的错误的话,可能 sdk 没有配置成功,也可能 sdk 下载的时候没有下载全


运行 flutter doctor 命令检测环境


入口文件、入口方法

每一个 flutter 项目的 lib 目录里面都有一个 main.dart 这个文件就是 flutter 的入口文件


main.dart 里面的

void main() {
  runApp(MyApp());
}
//也可以简写
void main() => runApp(MyApp());

其中的 main 方法是 dart 的入口方法。runApp 方法是 flutter 的入口方法。 MyApp 是自定义的一个组件

第一个 Demo Center 组件的 使用

import 'package:flutter/material.dart';
void main() {
  runApp(Center(
    child: Text(
      "我是一个文本内容",
      textDirection: TextDirection.ltr,
    ),
  ));
}

把内容单独抽离成一个组件

在 Flutter 中自定义组件其实就是一个类,这个类需要继承 StatelessWidget/StatefulWidget


前期我们都继承 StatelessWidget。后期给大家讲 StatefulWidget 的使用。


StatelessWidget 是无状态组件,状态不可变的 widget

StatefulWidget 是有状态组件,持有的状态可能在 widget 生命周期改变

import 'package:flutter/material.dart';
void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        "我是一个文本内容",
        textDirection: TextDirection.ltr,
      ),
    );
  }
}

给 Text 组件增加一些装饰

import 'package:flutter/material.dart';
void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        "我是一个文本内容",
        textDirection: TextDirection.ltr,
        style: TextStyle(
            fontSize: 40.0,
            fontWeight: FontWeight.bold,
            // color: Colors.yellow
          color: Color.fromRGBO(255, 222, 222, 0.5)
        ),
      ),
    );
  }
}

用MaterialApp 和 Scaffold两个组件装饰 App

1、MaterialApp


MaterialApp 是一个方便的 Widget,它封装了应用程序实现 Material Design 所需要的 一些 Widget。一般作为顶层 widget 使用。


常用的属性:


home(主页)


title(标题)


color(颜色)


theme(主题)


routes(路由)



2、Scaffold


Scaffold 是 Material Design 布局结构的基本实现。此类提供了用于显示 drawer、snackbar 和底部 sheet 的 API。


Scaffold 有下面几个主要属性:


appBar - 显示在界面顶部的一个 AppBar。


body - 当前界面所显示的主要内容 Widget。


drawer - 抽屉菜单控件。

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("Hello Flutter"),
          elevation: 30.0, 设置标题阴影  不需要的话值设置成 0.0
        ),
        body: HomeContent(),
      ),
      theme: ThemeData(
          //设置主题颜色
          primarySwatch: Colors.yellow),
    );
  }
}
class HomeContent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        "我是一个文本内容",
        textDirection: TextDirection.ltr,
        style: TextStyle(
            fontSize: 40.0,
            fontWeight: FontWeight.bold,
            // color: Colors.yellow
            color: Color.fromRGBO(255, 222, 222, 0.5)
        ),
      ),
    );
  }
}

Text 组件image.png下面是 TextStyle 的参数 :image.png更多函数:https://docs.flutter.io/flutter/painting/TextStyle-class.html

Container 组件image.png更多参数:https://api.flutter.dev/flutter/widgets/Container-class.html


图片组件

图片组件是显示图像的组件,Image 组件有很多构造函数,这里我们只给大家讲两个


Image.asset 本地图片


Image.network 远程图片


Image 组件的常用属性:

image.png

更多属性参考:https://api.flutter.dev/flutter/widgets/Image-class.html

return Center(
      child: Container(
        child: Image.network(
          "http://pic.baike.soso.com/p/20130828/20130828161137-1346445960.jpg",
          alignment: Alignment.topLeft,
          color: Colors.red,
          colorBlendMode: BlendMode.colorDodge,
          // repeat: ImageRepeat.repeatX,
          fit: BoxFit.cover,
        ),
        width: 300.0,
        height: 400.0,
        decoration: BoxDecoration(
            color: Colors.yellow
        ),
      ),
    );

引入本地图片

emmm…不记了


裁剪布局之 ClipRect、ClipRRect、ClipOval、ClipPath、CustomClipper

widget 作用

ClipRect 将 child 剪裁为给定的矩形大小

ClipRRect 将 child 剪裁为圆角矩形

ClipOval 如果 child 为正方形时剪裁之后是圆形,如果 child 为矩形时,剪裁之后为椭圆形

ClipPath 将 child 按照给定的路径进行裁剪

CustomClipper 并不是一个widget,但是使用CustomClipper可以绘制出任何我们想要的形状


实现圆角以及实现圆形图片

实现圆角图片

return Center(
      child: Container(
        width: 300.0,
        height: 300.0,
        decoration: BoxDecoration(
            color: Colors.yellow,
            borderRadius: BorderRadius.circular(150),
            image: DecorationImage(
                image: NetworkImage(
                  "http://pic.baike.soso.com/p/20130828/20130828161137-1346445960.jpg",
                ),
                fit: BoxFit.cover
            )
        ),
      ),
    );

实现圆形图片

return Center(
      child: Container(
        child: ClipOval(
          child: Image.network(
            "https://www.itying.com/images/201905/thumb_img/1101_thumb_G_1557845381862.jpg",
            width: 150.0,
            height: 150.0,
          ),
        ),
      ),
    );

圆形头像

ClipOval

new ClipOval(
    child: new Image.asset(Utils.getImgPath('ali_connors')),
  )

② CircleAvatar

new CircleAvatar(
    radius: 36.0,
    backgroundImage: AssetImage(
      Utils.getImgPath('ali_connors'),
    ),
  )

③ BoxDecoration BoxShape.circle

new Container(
    width: 72.0,
    height: 72.0,
    decoration: BoxDecoration(
      shape: BoxShape.circle,
      image: DecorationImage(
        image: AssetImage(
          Utils.getImgPath('ali_connors'),
        ),
      ),
    ),
  )

圆角头像

① ClipRRect

new ClipRRect(
    borderRadius: BorderRadius.circular(6.0),
    child: new Image.asset(Utils.getImgPath('ali_connors')),
  )

② BoxDecoration BoxShape.rectangle

new Container(
    width: 88.0,
    height: 88.0,
    decoration: BoxDecoration(
      shape: BoxShape.rectangle,
      borderRadius: BorderRadius.circular(6.0),
      image: DecorationImage(
        image: AssetImage(
          Utils.getImgPath('ali_connors'),
        ),
      ),
    ),

列表组件概述

列表布局是我们项目开发中最常用的一种布局方式。Flutter 中我们可以通过 ListView 来定义 列表项,支持垂直和水平方向展示。通过一个属性就可以控制列表的显示方向。列表有一下 分类:


**1、垂直列表(宽度自动扩展,设置宽度无效)**可以在外层包Container控制


2、垂直图文列表


**3、水平列表(高度自动扩展,设置高度无效)**可以在外层包Container控制


4、动态列表


5、矩阵式列表(网格布局)


列表参数

image.png

基本列表

class HomeContent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: ListView(
        children: <Widget>[
          ListTile(
            leading: Icon(Icons.phone),
            title: Text("this is list", style: TextStyle(fontSize: 28.0)),
            subtitle: Text('this is list this is list'),
          ),
          ListTile(
            title: Text("this is list"),
            subtitle: Text('this is list this is list'),
            trailing: Icon(Icons.phone),
          ),
          ListTile(
            title: Text("this is list"),
            subtitle: Text('this is list this is list'),
          ),
          ListTile(
            title: Text("this is list"),
            subtitle: Text('this is list this is list'),
          ),
          ListTile(
            title: Text("this is list"),
            subtitle: Text('this is list this is list'),
          )
        ],
      ),
    );
  }
}

水平列表

class HomeContent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 200.0,
      margin: EdgeInsets.all(5),
      child: ListView(
        scrollDirection: Axis.horizontal,
        children: <Widget>[
          Container(
            width: 180.0,
            color: Colors.lightBlue,
          ),
          Container(
            width: 180,
            color: Colors.amber,
            child: ListView(
              children: <Widget>[
                Image.network(
                    "https://resources.ninghao.org/images/childhood-in-a-picture.jpg"),
                SizedBox(height: 16.0),
                Text("这是一个文本信息",
                    textAlign: TextAlign.center,
                    style: TextStyle(fontSize: 16.0)),
              ],
            ),
          )
        ],
      ),
    );
  }
}

动态列表(动态循环数据)

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("Hello Flutter")),
        body: HomeContent(),
      ),
    );
  }
}
class HomeContent extends StatelessWidget {
  List list = List();
  HomeContent() {
    for (int i = 0; i < 20; i++) {
      list.add("这是第$i条数据");
    }
    print(list);
  }
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
        itemCount: this.list.length,
        itemBuilder: (context, index) {
          // print(context);
          return ListTile(
            leading: Icon(Icons.phone),
            title: Text("${list[index]}"),
          );
        });
  }
}

GridView 组件的常用参数

当数据量很大的时候用矩阵方式排列比较清晰。此时我们可以用网格列表组件 GridView 实现布局。


GridView 创建网格列表有多种方式,下面我们主要介绍两种。


1、可以通过 GridView.count 实现网格布局


2、通过 GridView.builder 实现网格布局


常用属性:


image.png

image.png

GridView.count 实现网格布局

import 'package:cc/res/listData.dart';
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("Hello Flutter")),
        body: LayoutContent(),
      ),
    );
  }
}
class LayoutContent extends StatelessWidget {
  List<Widget> _getListData() {
    var tempList = listData.map((value) {
      return Container(
        child: Column(
          children: <Widget>[
            Image.network(value["imageUrl"]),
            SizedBox(height: 12),
            Text(value["title"],
                textAlign: TextAlign.center, style: TextStyle(fontSize: 20))
          ],
        ),
        decoration: BoxDecoration(
            border: Border.all(
                color: Color.fromRGBO(230, 230, 230, 0.9), width: 1.0)),
      );
    });
    // ('124124','124214')
    return tempList.toList();
  }
  @override
  Widget build(BuildContext context) {
    return GridView.count(
      crossAxisCount: 2,
      crossAxisSpacing: 20,
      mainAxisSpacing: 20,
//       childAspectRatio:0.7,
      children: this._getListData(),
    );
  }
}

GridView.builder 实现网格布局

import 'package:cc/res/listData.dart';
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("Hello Flutter")),
        body: LayoutContent(),
      ),
    );
  }
}
class LayoutContent extends StatelessWidget {
  Widget _getListData(context, index) {
    return Container(
      child: Column(
        children: <Widget>[
          Image.network(listData[index]["imageUrl"]),
          SizedBox(height: 12),
          Text(listData[index]["title"],
              textAlign: TextAlign.center, style: TextStyle(fontSize: 20))
        ],
      ),
      decoration: BoxDecoration(
          border: Border.all(
              color: Color.fromRGBO(230, 230, 230, 0.9), width: 1.0)),
    );
  }
  @override
  Widget build(BuildContext context) {
    return GridView.builder(
      itemCount: listData.length,
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          //横轴元素个数
          crossAxisCount: 2,
          //纵轴间距
          mainAxisSpacing: 20.0,
          //横轴间距
          crossAxisSpacing: 10.0,
          //子组件宽高长度比例
          childAspectRatio: 1.0),
      itemBuilder: this._getListData,
    );
  }
}

Paddiing 组件

在 html 中常见的布局标签都有 padding 属性,但是 Flutter 中很多 Widget 是没有 padding 属性。这个时候我们可以用 Padding 组件处理容器与子元素直接的间距。

image.png

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.fromLTRB(0, 0, 10, 0),
      child: GridView.count(
        crossAxisCount: 2,
        childAspectRatio: 1.5,
        children: <Widget>[
          Padding(
            padding: EdgeInsets.fromLTRB(10, 10, 0, 0),
            child: Image.network("https://www.itying.com/images/flutter/1.png",
                fit: BoxFit.cover),
          ),
          Padding(
            padding: EdgeInsets.fromLTRB(10, 10, 0, 0),
            child: Image.network("https://www.itying.com/images/flutter/2.png",
                fit: BoxFit.cover),
          ),
          Padding(
            padding: EdgeInsets.fromLTRB(10, 10, 0, 0),
            child: Image.network("https://www.itying.com/images/flutter/3.png",
                fit: BoxFit.cover),
          ),
          Padding(
            padding: EdgeInsets.fromLTRB(10, 10, 0, 0),
            child: Image.network("https://www.itying.com/images/flutter/4.png",
                fit: BoxFit.cover),
          ),
          Padding(
            padding: EdgeInsets.fromLTRB(10, 10, 0, 0),
            child: Image.network("https://www.itying.com/images/flutter/5.png",
                fit: BoxFit.cover),
          ),
          Padding(
            padding: EdgeInsets.fromLTRB(10, 10, 0, 0),
            child: Image.network("https://www.itying.com/images/flutter/6.png",
                fit: BoxFit.cover),
          ),
        ],
      ),
    );
  }
}

Row 水平布局组件image.png

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("Hello Flutter")),
        body: LayoutDemo(),
      ),
    );
  }
}
class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 700,
      width: 500,
      color: Colors.black26,
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
//        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          IconContainer(Icons.home, color: Colors.red),
          IconContainer(Icons.home, color: Colors.blue),
          IconContainer(Icons.home, color: Colors.orange),
        ],
      ),
    );
  }
}
class IconContainer extends StatelessWidget {
  double size;
  IconData icon;
  Color color;
  IconContainer(this.icon, {this.size, this.color = Colors.blue}) {
    this.size = 32.0;
  }
  @override
  Widget build(BuildContext context) {
    return Container(
      width: this.size + 60,
      height: this.size + 60,
      color: this.color,
      child: Center(
          child: Icon(
        this.icon,
        color: Colors.white,
        size: this.size,
      )),
    );
  }
}

Column 垂直布局组件

image.png

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("Hello Flutter")),
        body: LayoutDemo(),
      ),
    );
  }
}
class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 700,
      width: 500,
      color: Colors.black26,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
//        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          IconContainer(Icons.home, color: Colors.red),
          IconContainer(Icons.home, color: Colors.blue),
          IconContainer(Icons.home, color: Colors.orange),
        ],
      ),
    );
  }
}
class IconContainer extends StatelessWidget {
  double size;
  IconData icon;
  Color color;
  IconContainer(this.icon, {this.size, this.color = Colors.blue}) {
    this.size = 32.0;
  }
  @override
  Widget build(BuildContext context) {
    return Container(
      width: this.size + 60,
      height: this.size + 60,
      color: this.color,
      child: Center(
          child: Icon(
        this.icon,
        color: Colors.white,
        size: this.size,
      )),
    );
  }
}

Expanded 类似 Web 中的 Flex 布局

Expanded 可以用在 Row 和 Column 布局中

image.png

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("Hello Flutter")),
        body: LayoutDemo(),
      ),
    );
  }
}
class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.all(10),
      child: Row(
        // crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment: MainAxisAlignment.center,
        // crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Expanded(flex: 2, child: IconContainer(Icons.home)),
          SizedBox(width: 10),
          Expanded(flex: 3, child: IconContainer(Icons.search)),
          // SizedBox(width: 10),
          // Expanded(child: IconContainer(Icons.send))
        ],
      ),
    );
  }
}
class IconContainer extends StatelessWidget {
  double size;
  IconData icon;
  IconContainer(this.icon, {this.size}) {
    this.size = 32.0;
  }
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 100.0,
      height: 100.0,
      color: Colors.blue,
      child:
          Center(child: Icon(this.icon, color: Colors.white, size: this.size)),
    );
  }
}
相关文章
|
3月前
|
存储 设计模式 Dart
Flutter笔记:getX库中的GetView中间件
Flutter笔记:getX库中的GetView中间件
80 0
|
3月前
|
存储 Dart 数据库
Flutter笔记:状态提升、控制器模式、GetX控制器和服务
Flutter笔记:状态提升、控制器模式、GetX控制器和服务
93 0
|
3月前
|
Web App开发 Ubuntu 应用服务中间件
Flutter笔记:Web支持原理与实践
Flutter笔记:Web支持原理与实践
101 0
|
3月前
|
Linux Android开发 iOS开发
Flutter笔记:滑块及其实现分析1
Flutter笔记:滑块及其实现分析1
98 0
|
3月前
|
Web App开发 JSON Android开发
Flutter笔记:获取设备信息
Flutter笔记:获取设备信息
120 0
|
3月前
|
容器
Flutter笔记:Box协议的布局约束原理与应用
Flutter笔记:Box协议的布局约束原理与应用
47 0
|
3月前
|
BI
Flutter笔记:路由观察者
Flutter笔记:路由观察者
74 0
|
3月前
|
存储 编解码 Android开发
Flutter笔记:使用相机
Flutter笔记:使用相机
178 0
|
3月前
|
存储 缓存 Dart
Flutter笔记:目录与文件存储以及在Flutter中的使用(下)
Flutter笔记:目录与文件存储以及在Flutter中的使用(下)
164 0
|
3月前
|
存储 Dart 数据管理
Flutter笔记:目录与文件存储以及在Flutter中的使用(上)
Flutter笔记:目录与文件存储以及在Flutter中的使用(上)
84 0