Flutter基础笔记

Posted Lucklyの博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter基础笔记相关的知识,希望对你有一定的参考价值。

目录

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

1MaterialApp

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

常用的属性:

home(主页)

title(标题)

color(颜色)

theme(主题)

routes(路由)

2Scaffold

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 组件

名称功能
textAlign文本对齐方式(center 居中,left 左 对齐,right 右对齐,justfy 两端对齐)
textDirection文本方向(ltr 从左至右,rtl 从右至 左)
overflow文字超出屏幕之后的处理方式(clip 裁剪,fade 渐隐,ellipsis 省略号)
textScaleFactor字体显示倍率
maxLines文字显示最大行数
style字体的样式设置

下面是 TextStyle 的参数 :

名称功能
decoration文字装饰线(none 没有线,lineThrough 删 除线,overline 上划线,underline 下划线)
decorationColor文字装饰线颜色
decorationStyle文字装饰线风格([dashed,dotted]虚线, double 两根线,solid 一根实线,wavy 波浪 线)
wordSpacing单词间隙(如果是负值,会让单词变得更紧 凑
letterSpacing字母间隙(如果是负值,会让字母变得更紧 凑)
fontStyle文字样式(italic 斜体,normal 正常体)
fontSize文字大小
color文字颜色
fontWeight字体粗细(bold 粗体,normal 正常体)

更多参数:https://docs.flutter.io/flutter/painting/TextStyle-class.html

Container 组件

名称功能
alignmenttopCenter:顶部居中对齐
topLeft:顶部左对齐
topRight:顶部右对齐
center:水平垂直居中对齐
centerLeft:垂直居中水平居左对齐
centerRight:垂直居中水平居右对齐
bottomCenter 底部居中对齐
bottomLeft:底部居左对齐
bottomRight:底部居右对齐
decorationdecoration: BoxDecoration(
color: Colors.blue,
border: Border.all(
color: Colors.red,
width: 2.0,
),
borderRadius:
BorderRadius.all(
Radius.circular(8.0)
)
)
marginmargin 属性是表示 Container 与外部其他 组件的距离。
EdgeInsets.all(20.0),
paddingpadding 就是 Container 的内边距,指 Container 边缘与 Child 之间的距离
padding: EdgeInsets.all(10.0)
transform让 Container 容易进行一些旋转之类的
transform: Matrix4.rotationZ(0.2)
height容器高度
width容器宽度
child容器子元素

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

图片组件

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

Image.asset 本地图片

Image.network 远程图片

Image 组件的常用属性:

名称类型说明
alignmentalignment图片的对齐方式
color 和 colorBlendMode设置图片的背景颜色,通常和 colorBlendMode 配合一起使用,这样可以是图片颜色和背景色混合。上面的图片就是进行了颜色的混合,绿色背景和图片红色的混合
fitBoxFitfit 属性用来控制图片的拉伸和挤压,这都是根据父容器来的。
BoxFit.fill:全图显示,图片会被拉伸,并充满父容器。
BoxFit.contain:全图显示,显示原比例,可能会有空隙。
BoxFit.cover:显示可能拉伸,可能裁切,充满(图片要充满整个容器,还不变形)。
BoxFit.fitWidth:宽度充满(横向充满),显示可能拉伸,可能裁切。
BoxFit.fitHeight :高度充满(竖向充满),显示可能拉伸,可能裁切。
BoxFit.scaleDown:效果和 contain 差不多,但是此属性不允许显示超过源图片大小,可小不可大。
repeat平铺ImageRepeat.repeat : 横向和纵向都进行重复,直到铺满整个画布。
ImageRepeat.repeatX: 横向重复,纵向不重复。
ImageRepeat.repeatY:纵向重复,横向不重复。
width宽度 一般结合 ClipOval 才能看到效果
height高度 一般结合 ClipOval 才能看到效果

更多属性参考: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、矩阵式列表(网格布局)

列表参数

名称类型说明
scrollDirectionAxisAxis.horizontal 水平列表
Axis.vertical 垂直列表
paddingEdgeInsetsGeometry内边距
resolvebool组件反向排序
childrenList列表元素

基本列表

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 实现网格布局

常用属性:

名称类型说明
scrollDirectionAxis滚动方法
paddingEdgeInsetsGeometry内边距
resolvebool组件反向排序
crossAxisSpacingdouble水平子 Widget 之间间距
mainAxisSpacingdouble垂直子 Widget 之间间距
crossAxisCountint一行的 Widget 数量
childAspectRatiodouble子 Widget 宽高比例
children[ ]
gridDelegateSliverGridDelegateWithFix
edCrossAxisCount(常用)
SliverGridDelegateWithMax
CrossAxisExtent
控制布局主要用在GridView.builder 里面

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 组件处理容器与子元素直接的间距。

属性说明
paddingpadding 值, EdgeInsetss 设置填充的值
child子组件
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 水平布局组件

属性说明
mainAxisAlignment主轴的排序方式
crossAxisAlignment次轴的排序方式
children组件子元素
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 垂直布局组件

属性说明
mainAxisAlignment主轴的排序方式
crossAxisAlignment次轴的排序方式
children组件子元素
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 布局中

属性说明
flex元素站整个父 Row /Column 的比例
child子元素
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)),
    );
  }
}

Stack 组件

Stack 表示堆的意思,我们可以用 Stack 或者 Stack 结合 Align 或者 Stack 结合 Positiond 来实现页面的定位布局

属性说明
alignment配置所有子元素的显示位置
children子组件
class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Center(
      child: Stack(
        alignment: Alignment.topLeft,
        children: <Widget>[              
          Container(
            height: 400,
            width: 300,
            color: Colors.red,
          ),
          Text('我是一个文本',style: TextStyle(
            fontSize: 40,
            color: Colors.white
          ))           
        ],
      ),
    );
  }
}
class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Center(
      child: Stack(
        alignment: Alignment(1,0.3),
        children: <Widget>[              
          Container(
            height: 400,
            width: 300,
            color: Colors.red,
          ),
          Text('我是一个文本',style: TextStyle(
            fontSize: 20,
            color: Colors.white
          ))           
        ],
      ),
    );
  }
}

Stack Align

Stack 组件中结合 Align 组件可以控制每个子元素的显示位置

属性说明
alignment配置所有子元素的显示位置
child子组件
class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Center(
      child:  Container(
            height: 400,
            width: 300,
            color: Colors.red,
            child: Stack(
              // alignment: Alignment.center,
              children: <Widget>[
                Align(
                  alignment: Alignment(1,-0.2),
                  child: Icon(Icons.home,size: 40,color: Colors.white),
                ),
                Align(
                  alignment: Alignment.center,
                  child: Icon(Icons.search,size: 30,color: Colors.white),
                ),
                Align(
                  alignment: Alignment.bottomRight,
                  child: Icon(Icons.settings_applications,size: 30,color: Colors.white),
                )
              ],
            ),
      ),
    );
  }
}

Stack Positioned

Stack 组件中结合 Positioned 组件也可以控制每个子元素的显示位置

属性说明
top子元素距离顶部的距离
bottom子元素距离底部的距离
left子元素距离左侧距离
right子元素距离右侧距离
child子组件
class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Center(
      child:  Container(
            height: 400,
            width: 300,
            color: Colors.red,
            child: Stack(
              // alignment: Alignment.center,
              children: <Widget>[
                Positioned(
                //  left: 10,
                  child: Icon(Icons.home,size: 40,color: Colors.white),
                ),
                Positioned(
                 bottom: 0,
                 left: 100,
                  child: Icon(Icons.search,size: 30,color: Colors.white),
                ),
                Positioned(
                  right: 0,
                  child: Icon(Icons.settings_applications,size: 30,color: Colors.white),
                )
              ],
            ),
      ),
    );
  }
}

AspectRatio 组件

AspectRatio 的作用是根据设置调整子元素 child 的宽高比。

AspectRatio 首先会在布局限制条件允许的范围内尽可能的扩展,widget 的高度是由宽度和比率决定的,类似于 BoxFit 中的 contain,按照固定比率去尽量占满区域。

如果在满足所有限制条件过后无法找到一个可行的尺寸,AspectRatio 最终将会去优先适应布局限制条件,而忽略所设置的比率。

属性说明
aspectRatio宽高比,最终可能不会根据这个值去布局,具体则要看综合因素,外层是否允许按照这种比率进行布局,这只是一个参考值
child子组件
return Center(
      child: Container(
        width: 200,
        child: AspectRatio(
          aspectRatio: 2.0 / 1.0,
          child: Container(
            color: Colors.red,
          ),
        ),
      ),
    );

Card 组件

Card 是卡片组件块,内容可以由大多数类型的 Widget 构成,Card 具有圆角和阴影,这让它看起来有立体感。

属性说明
margin外边距
child子组件
ShapeCard 的阴影效果,默认的阴影效果为圆角的长方形边。
class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: <Widget>[
        Card(
          margin: EdgeInsets.all(10),
          child: Column(
            children: <Widget>[
              ListTile(
                title: Text(
                  "张三",
                  style: TextStyle(fontSize: 28),
                ),
                subtitle: Text("高级软件工程师"),
              ),
              Divider(),
              ListTile(
                title: Text("电话:123123123"),
              ),
              ListTile(
                title: Text("地址:北京市海淀区"),
              )
            ],
          ),
        ),
        Card(
          margin: EdgeInsets.all(10),
          child: Column(
            children: <Widget>[
              ListTile(
                title: Text(
                  "李四",
                  style: TextStyle(fontSize: 28),
                ),
                subtitle: Text("高级软件工程师"),
              ),
              Divider(),
              ListTile(
                title: Text("电话:123123123"),
              ),
              ListTile(
                title: Text("地址:北京市海淀区"),
              )
            ],
          ),
        ),
      ],
    );
  }
}

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

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
        children: listData.map((value) {
      return Card(
        margin: EdgeInsets.all(10),
        child: Column(
          children: <Widget>[
            AspectRatio(
              aspectRatio: 16 / 9,
              child: Image.network(value["imageUrl"], fit: BoxFit.cover),
            ),
            ListTile(
              leading: CircleAvatar(
                backgroundImage: NetworkImage(value["imageUrl"]),
              ),
              title: Text(value["description"]),
              subtitle: Text(
                value["description"],
                overflow: TextOverflow.ellipsis,
              ),
            )
          ],
        ),
      );
    }).toList());
  }
}
class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: listData.length,
      itemBuilder: (context,index){
        return Card(
          margin: EdgeInsets.all(10),
          child: Column(
            children: <Widget>[
              AspectRatio(
                aspectRatio: 16 / 9,
                child: Image.network(listData[index]["imageUrl"], fit: BoxFit.cover),
              ),
              ListTile(
                leading: CircleAvatar(
                  backgroundImage: NetworkImage(listData[index]["imageUrl"]),
                ),
                title: Text(listData[index]["description"]),
                subtitle: Text(
                  listData[index]["description"],
                  overflow: TextOverflow.ellipsis,
                ),
              )
            ],
          ),
        );
      },
    );
  }
}

RaisedButton 定义一个按钮

Flutter 中通过 RaisedButton 定义一个按钮。RaisedButton 里面有很多的参数,这一讲我们只是简单的进行使用。

return RaisedButton(
        child: Text("Flutter"),
        textColor: Theme.of(context).accentColor,
    onPressed: (){
          
    });

Wrap 组件

Wrap 可以实现流布局,单行的 Wrap 跟 Row 表现几乎一致,单列的 Wrap 则跟 Row 表 现几乎一致。但 Row 与 Column 都是单行单列的,Wrap 则突破了这个限制,mainAxis 上空 间不足时,则向 crossAxis 上去扩展显示。

属性说明
direction主轴的方向,默认水平
alignment主轴的对其方式
spacing主轴方向上的间距
textDirection文本方向
verticalDirection定义了 children 摆放顺序,默认是 down,见Flex 相关属性介绍。
runAlignmentrun 的对齐方式。run 可以理解为新的行或者列,如果是水平方向布局的话,run 可以理解为新的一行
runSpacingrun 的间距
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
  Widge

以上是关于Flutter基础笔记的主要内容,如果未能解决你的问题,请参考以下文章

Flutter笔记_基础篇

Flutter基础笔记

在 webview_flutter 中启用捏合和缩放,在哪里添加代码片段 [this.webView.getSettings().setBuiltInZoomControls(true);]

DOM探索之基础详解——学习笔记

Flutter学习笔记·认识Flutter

Flutterflutter doctor 报错Android license status unknown. Run `flutter doctor --android-licenses‘(代码片段