Flutter学习之旅

6 篇文章 0 订阅
1 篇文章 0 订阅

安装/配置

请看官网:

遇到问题

1.配置创建第一工程过程中,可能会回到一步在卡在gradle这一步:

Running 'gradle assembleDebug

解决方案
2.Flutter工程找不到手机设备(no devices to select)
解决方案:执行【flutter config --android-sdk 自己的android sdk路径】

语法

入口函数

方式一

main(){

}

方式二

void main(){

}

变量

dart是一门强大的脚步类语言,可以不预先定位变量的类型,会自动推断类型
var s1 = ‘hello’
String s2 = ‘hello’
注:var后不要加类型,写了类型就不要加var
类里的变量加上下划线(_)可以使之变为私有的,如同private关键字

命名规则

  1. 变量命名必须有数字、字母、下划线和美元符号($)组成
  2. 标识符开头不能是数字
  3. 标识符不能是保留字和关键字
  4. 变量名字是区分大小写的

常量

final(运行时变量)

开始可以不赋值,只赋值一次

const(编译是变量)

值不变,一开始就赋值

数据类型(常用)

  1. Number(数值)
    int
    double
  2. String(字符)
    String,单引号,双引号,三个单引号(适用于多行),三个双引号(适用于多行)
    拼接使用 符号、 + 号,如 S t r i n g s 1 = ′ h e l l o ′ ; S t r i n g s 2 = ′ w o r l d ′ ; S t r i n g s 3 = ′ 符号、+号,如 String s1 = 'hello'; String s2 = 'world'; String s3 = ' 符号、+号,如Strings1=hello;Strings2=world;Strings3=s1 $s2’ //hello world
    String s4 = s1 + s2 //hello world
  3. Booleans
    bool
  4. List(数组)
    Dart中,数组是列表对象
  5. Maps(字典)
    map
    初始化方式一
    var map1 = {
    “key1”:“value1”,
    “key2”:“value2”,
    “key3”:“value3”
    }
    初始化方式二
    var map2 = new Map()
    map2[‘key1’] = ‘value1’;
    map2[‘key2’] = ‘value2’;
    map2[‘key3’] = ‘value3’;
    map2.keys;//获取所有的key
    map.values;//获取所有的value

类型判断(is)

var s1 = ‘hello’;
if(s1 is String){
}

运算符(与java基本类似)

赋值运算符 = ??=

String s1;
s1 ??= ‘hello’;//表示如果s1为空的话,把’hello’赋值给s1

for循环

  1. (var i = 0;i < length;i++){}
  2. for(var item in list){}
  3. list.forEach((value){});
  4. map.forEach((key,value){});
  5. newList = list.map((value){//返回原集合中个元素*2的组成新的集合
    return value * 2;
    })
  6. newList = list.where((value){//返回原集合中大于10的元素组成新的集合
    return value > 10;
    })
  7. newList = list.any((value){//判断原集合中的元素是否有大于10的
    return value > 10;
    })
  8. newList = list.every((value){//判断原集合中的元素是否都大于10
    return value > 10;
    })

函数(方法)

  1. 函数内部可以嵌套函数
  2. 可选参数使用中括号,如
void func(int a,[int b=1,int c]){} //其中,b,c为可选参数

3.命名参数使用大括号,如

void func(int a,{int b,int c}){} //其中,b,c为命名参数
调用
func(1,b=2,c=4)

闭包

概念:函数嵌套函数,嵌套的函数会调用外部函数的变量或参数,变量或参数不会被系统回收
写法:函数嵌套函数,并return里面的函数,这样就形成闭包

?条件运算符(同kotlin),如:

Object ob;
ob?.toString()

as 类型转换

is 类型判断

… 级联操作(连缀)

class User{
 int age;
 String name;
}
User user = new User();
user..age=10
     ..name="Tim";

初始化列表(执行构造函数前执行)

class User{
  int age;
  String name;
  User()in age=11,name='Tim'{
  }
}
class SubUser extend User{
	SubUser():supter(){}
}

复写

@override可写可不写

类似多继承(mixins)

class B{}
class C{}
class A with B,C{

}
注:使用mixins时,B、C类不能有构造函数,B、Clei不能继承其他类

网络请求

async: 让方法变成一部

void test() async {}

await 等待异步方法执行完成

只有在使用async时,才能使用await

 getDataFromSever() async {
	var httpClient =new HttpClient();
	var uri = new Uri.http("http:xxxx");
	var request = await httpClient.getUrl(uri);
	var respone = await request.close();
	return respone.transForm(utf8.decoder).join();
}

第三方模块

托管:统一托管在pub上,如

dev/packages
fluter-io
dartlang

flutter工程

目录

在这里插入图片描述

程序入口

main(){
	runApp(myApp())
}
或
main() => runApp(myApp())

组件

Widget

对应Android中的View

MaterialApp

作为Widget的顶层组件

home(主页)
title(标题)
color(颜色)
theme(主题)
routes(路由,相当Activity)
Scaffold 是Meterial Design的布局的基本实现

有以下几个属性

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(
      home: Scaffold(
        appBar: AppBar(
          title: Text(
            '我是标题栏'
          ),
        ),
        body: MyCenter(),
      ),
      theme: ThemeData(
        primarySwatch:Colors.red //主题颜色
      ),
    );
  }

}

class MyCenter extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Center(
        child: Text(
          'hello',
          textDirection: TextDirection.ltr,
          style: TextStyle(
              color: Colors.red,
              fontSize: 32
          ),
        )
    );
  }
}

//class MyApp extends StatelessWidget {
//
//  @override
//  Widget build(BuildContext context) {
//    return new MaterialApp(
//      title: 'my First flutter',
//      home: new Scaffold(
//        appBar: new AppBar(
//          title: new Text('I am appBar 哈哈233'),
//        ),
//        body: new Center(
//          child: new Text('Hello World!!!2'),
//        ),
//      ),
//    );
//  }
//}

//void main() {
//  runApp(
//    new Center(
//      child: new Text(
//        'Hello, world!',
//        textDirection: TextDirection.ltr,
//      ),
//    ),
//  );
//}

Container(容器)

也是集成与StateLessWidget

Image

本地图片 Image.asset
  1. 先在工程目录下创建存放图片的目录,如:
    在这里插入图片描述
    images根目录为标准图片
    images/2.0x为2.0倍
    images/3.0x为3.0倍
    以上三个目录比配放置图片
  2. 在pubspec.yaml配置该图片路径
assets:
    - images/bg.png
    - images/2.0x/bg.png
    - images/3.0x/bg.png
  1. 最后引用
Image.asset('images/bg.png');
网络图片 Image.network(picUrl)
圆角及圆形图片
圆形
  1. 利用Container的borderRadius
Container(
      width: 400,
      height: 400,
      decoration: BoxDecoration(
          color: Colors.yellow,
//          borderRadius: BorderRadius.all(Radius.circular(60))
      borderRadius: BorderRadius.circular(60),
      image: DecorationImage(
        image: NetworkImage('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581422031471&di=df2254ecbc97fc0cae3396a670511021&imgtype=0&src=http%3A%2F%2Fimg2018.cnblogs.com%2Fblog%2F1762823%2F201911%2F1762823-20191104112732371-1699453123.jpg'),
          fit: BoxFit.cover
      ))
  1. 利用Container的ClipOval属性
child: ClipOval(
      child: Image.network(
        'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581422031471&di=df2254ecbc97fc0cae3396a670511021&imgtype=0&src=http%3A%2F%2Fimg2018.cnblogs.com%2Fblog%2F1762823%2F201911%2F1762823-20191104112732371-1699453123.jpg',
        fit: BoxFit.cover,
      width: 300,
      height: 300,),
    ),

ListView

ListView内部不能嵌套ListView

ListView(
      padding: EdgeInsets.all(15.0),
      scrollDirection: Axis.vertical,
      children: <Widget>[
        ListTile(
          leading: Icon(Icons.ac_unit,color: Colors.red,size: 44,),
            trailing: Icon(Icons.ac_unit,color: Colors.red,size: 44,),
            title: Text('要安装并运行Flutter,您的开发环境必须满足以下最低要求:'),
            subtitle: Text('要安装并运行Flutter,您的开发环境必须满足以下最低要求:')
        ),
       //或者其他Widget
      ],
    );

ListView.builder

import 'package:flutter/material.dart';


class MyListView extends StatelessWidget {

  var list = new List();

  MyListView(){
    for(var i = 0;i < 20;i++){
      list.add('第$i条数据');
    }
  }

  @override
  Widget build(BuildContext context) {
//    return ListView(
//      padding: EdgeInsets.all(15.0),
//      scrollDirection: Axis.vertical,
//      children: _getStaticData(),
//    );
  return ListView.builder(
    itemCount: this.list.length,
    itemBuilder: (context,index){
      return ListTile(
        title: Text(this.list[index]),
      );
    }
  );
  }
}

List<Widget> _getStaticData(){
  return <Widget>[
    ListTile(
        leading: Icon(Icons.ac_unit,color: Colors.red,size: 44,),
        trailing: Icon(Icons.ac_unit,color: Colors.red,size: 44,),
        title: Text('要安装并运行Flutter,您的开发环境必须满足以下最低要求:'),
        subtitle: Text('要安装并运行Flutter,您的开发环境必须满足以下最低要求:')
    ),
    ListTile(
        leading: Icon(Icons.accessibility),
        title: Text('要安装并运行Flutter,您的开发环境必须满足以下最低要求:'),
        subtitle: Text('要安装并运行Flutter,您的开发环境必须满足以下最低要求:')
    ),
    ListTile(
        leading: Image.asset('images/bg.png',width: 44,height: 44,),
        title: Text('要安装并运行Flutter,您的开发环境必须满足以下最低要求:'),
        subtitle: Text('要安装并运行Flutter,您的开发环境必须满足以下最低要求:')
    )
  ];
}



GridView

实现方式

GridView.count
GridView.count(
      scrollDirection: Axis.vertical,//方向
      crossAxisCount: 3, //一行几列
      crossAxisSpacing: 8,//水平间隔
      mainAxisSpacing: 8,//垂直间隔
      children: _getStaticData(),
    )
GridView.builder
GridView.builder(
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 3,
          crossAxisSpacing: 5,
          mainAxisSpacing: 5

    ),
    itemCount: this.list.length,
    itemBuilder: (context,index){
      return Container(
//        height: 120,
        child: Image.network(
            "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581422031471&di=df2254ecbc97fc0cae3396a670511021&imgtype=0&src=http%3A%2F%2Fimg2018.cnblogs.com%2Fblog%2F1762823%2F201911%2F1762823-20191104112732371-1699453123.jpg",
          fit: BoxFit.cover),
      );
    }
  )

Padding、 Row Column、Expanded

Padding–间距组件

Row–水平组件

Row(
        mainAxisAlignment: MainAxisAlignment.end,//主轴(水平)排列方式
        children: <Widget>[
          Image.network(
            'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581422031471&di=df2254ecbc97fc0cae3396a670511021&imgtype=0&src=http%3A%2F%2Fimg2018.cnblogs.com%2Fblog%2F1762823%2F201911%2F1762823-20191104112732371-1699453123.jpg',
            fit: BoxFit.cover,
            width: 50,
            height: 50,),
          Image.network(
            'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581422031471&di=df2254ecbc97fc0cae3396a670511021&imgtype=0&src=http%3A%2F%2Fimg2018.cnblogs.com%2Fblog%2F1762823%2F201911%2F1762823-20191104112732371-1699453123.jpg',
            fit: BoxFit.cover,
            width: 50,
            height: 50,),
          Image.network(
            'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581422031471&di=df2254ecbc97fc0cae3396a670511021&imgtype=0&src=http%3A%2F%2Fimg2018.cnblogs.com%2Fblog%2F1762823%2F201911%2F1762823-20191104112732371-1699453123.jpg',
            fit: BoxFit.cover,
            width: 50,
            height: 50,),
          Image.network(
            'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581422031471&di=df2254ecbc97fc0cae3396a670511021&imgtype=0&src=http%3A%2F%2Fimg2018.cnblogs.com%2Fblog%2F1762823%2F201911%2F1762823-20191104112732371-1699453123.jpg',
            fit: BoxFit.cover,
            width: 50,
            height: 50,)
        ],
      )

Column–垂直组件

Column(
        mainAxisAlignment: MainAxisAlignment.end,//主轴(垂直)排列方式
        children: <Widget>[
          Image.network(
            'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581422031471&di=df2254ecbc97fc0cae3396a670511021&imgtype=0&src=http%3A%2F%2Fimg2018.cnblogs.com%2Fblog%2F1762823%2F201911%2F1762823-20191104112732371-1699453123.jpg',
            fit: BoxFit.cover,
            width: 50,
            height: 50,),
          Image.network(
            'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581422031471&di=df2254ecbc97fc0cae3396a670511021&imgtype=0&src=http%3A%2F%2Fimg2018.cnblogs.com%2Fblog%2F1762823%2F201911%2F1762823-20191104112732371-1699453123.jpg',
            fit: BoxFit.cover,
            width: 50,
            height: 50,),
          Image.network(
            'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581422031471&di=df2254ecbc97fc0cae3396a670511021&imgtype=0&src=http%3A%2F%2Fimg2018.cnblogs.com%2Fblog%2F1762823%2F201911%2F1762823-20191104112732371-1699453123.jpg',
            fit: BoxFit.cover,
            width: 50,
            height: 50,),
          Image.network(
            'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581422031471&di=df2254ecbc97fc0cae3396a670511021&imgtype=0&src=http%3A%2F%2Fimg2018.cnblogs.com%2Fblog%2F1762823%2F201911%2F1762823-20191104112732371-1699453123.jpg',
            fit: BoxFit.cover,
            width: 50,
            height: 50,)
        ],
      )

Expanded

类似web中的flex布局

Row(
      children: <Widget>[
        Expanded(
          flex: 2,
          child: Image.network(
            'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581422031471&di=df2254ecbc97fc0cae3396a670511021&imgtype=0&src=http%3A%2F%2Fimg2018.cnblogs.com%2Fblog%2F1762823%2F201911%2F1762823-20191104112732371-1699453123.jpg',
            fit: BoxFit.cover,
            height: 100,),
        ),
        Expanded(
            flex: 1,
            child: Image.network(
          'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581422031471&di=df2254ecbc97fc0cae3396a670511021&imgtype=0&src=http%3A%2F%2Fimg2018.cnblogs.com%2Fblog%2F1762823%2F201911%2F1762823-20191104112732371-1699453123.jpg',
          fit: BoxFit.cover,
          height: 100,)
        )],
    )

Stack

页面层叠组件,类似于RelativeLayout布局
属性

alignment 配置所有子元素显示的位置

 Stack(
        children: <Widget>[
          Align( //相对位置
            alignment: Alignment(0,0.5),//(0.0)为中心
            child: Icon(Icons.home,size:60,color: Colors.red),
          ),
          Align(
            alignment: Alignment.bottomLeft,
            child: Icon(Icons.save,size:60,color: Colors.yellow),
          ),
          Positioned(//绝对位置)
            left: 0,//左上角
//            top: 0,
//            right: 0,
            bottom: 100,
            child: Icon(Icons.settings,size:60,color: Colors.yellow),
          )
        ],
      )

注意:(0.0)为中心

position

children 子组件

Positioned(//绝对位置)
            left: 0,//左上角
//            top: 0,
//            right: 0,
            bottom: 100,
            child: Icon(Icons.settings,size:60,color: Colors.yellow),
          )
Container(
      height: 400,
      width: 400,
      color: Colors.blue,
      alignment: Alignment(0,1),
      child: new Stack(
        children: <Widget>[
          Align( //相对位置
            alignment: Alignment(0,0.5),//(0.0)为中心
            child: Icon(Icons.home,size:60,color: Colors.red),
          ),
          Align(
            alignment: Alignment.bottomLeft,
            child: Icon(Icons.save,size:60,color: Colors.yellow),
          ),
          Positioned(//绝对位置)
            left: 0,//左上角
//            top: 0,
//            right: 0,
            bottom: 100,
            child: Icon(Icons.settings,size:60,color: Colors.yellow),
          )
        ],
      ),
    )

AspectRadio、Card

AspectRadio

作用:可以设置调整child子元素的宽高比

AspectRatio(
        aspectRatio: 2/1,//宽/高
        child: Container(
          color: Colors.blue
        ),
    )

Card

属性
  1. margin 外边距
  2. child 子组件
  3. shape 卡片的阴影效果,默认是圆角的长方形
Card(
          margin: EdgeInsets.all(10),
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(20))),
          child: Column(
            children: <Widget>[
              AspectRatio(
                aspectRatio: 16/9,
                child: Image.network(
                    'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581422031471&di=df2254ecbc97fc0cae3396a670511021&imgtype=0&src=http%3A%2F%2Fimg2018.cnblogs.com%2Fblog%2F1762823%2F201911%2F1762823-20191104112732371-1699453123.jpg',
                    fit: BoxFit.cover),
              ),
              ListTile(
                leading: CircleAvatar(
                  backgroundImage: NetworkImage("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1581422031471&di=df2254ecbc97fc0cae3396a670511021&imgtype=0&src=http%3A%2F%2Fimg2018.cnblogs.com%2Fblog%2F1762823%2F201911%2F1762823-20191104112732371-1699453123.jpg"),
                ),
                title: Text('name'),
                subtitle: Text('subContent'),
              )
            ],
          )
        )

RaisedButton

child

onPressed

Wrap

实现流布局,相对于FloxBoxLayout

import 'package:first_flutter_app/MyRaisedButton.dart';
import 'package:flutter/material.dart';

class MyWrap extends StatelessWidget {

  var list = new List();

  MyWrap(){
    for(var i = 0;i < 20;i++){
      list.add('第$i条数据');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Wrap(
      direction: Axis.horizontal,//方向
        spacing: 5,//主轴间距
        runSpacing: 5,//副轴间距
        alignment: WrapAlignment.center,//主轴方向对其方式
      children: _getWidgets()
    );
  }

  List<Widget> _getWidgets(){
    return list.map((value) {
      return MyRaisedButton(value);
    }).toList();
  }
}

StatefulWidget

有状态组件

关键点

  1. MyWidget 继承 StatefulWidget
  2. 并继承State
  3. 改变状态是,在state类里调用setState函数
import 'package:flutter/material.dart';

class MySatefulWidget extends StatefulWidget {

  @override
  _MySatefulWidgetState createState() {
    return _MySatefulWidgetState();
  }

}

class _MySatefulWidgetState extends State<MySatefulWidget>{

  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        SizedBox(
          height: 10,
        ),
        Text('Hi ${this.count}'),
        SizedBox(
          height: 10,
        ),
        RaisedButton(
          child: Text('click'),
          onPressed: (){
            setState(() {
              this.count++;
            });
          },
        )
      ],
    );
  }

}

BottomNavigationBar

自定义底部导航条
属于Scaffold
常见属性

  1. items 底部导航条按钮组合(List)
  2. iconSize
  3. currentIndex
  4. onTap 选中变化回调的函数
  5. fixedColor 选中的颜色,如果不设置,默认跟主题颜色一样
  6. type
    1).BottomNavigationBar.fixed
    2).BottomNavigationBar.shifting
Scaffold(
        appBar: AppBar(
          title: Text('我是标题栏'),
        ),
        body: this._pages[this._currentIndex],
        bottomNavigationBar:BottomNavigationBar(
          currentIndex: this._currentIndex,
          iconSize: 22.0,//icon大小
          fixedColor:Colors.blue, //选中的颜色,如果不设置,默认跟主题颜色一样
          type: BottomNavigationBarType.fixed, //解决多个tabItem时,不显示的配置
          onTap: (int index) {
            setState(() {
              this._currentIndex = index;
            });
          },
          items: [
        BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Text('首页')
        ),
        BottomNavigationBarItem(
            icon: Icon(Icons.message),
            title: Text('消息')
        ),
        BottomNavigationBarItem(
            icon: Icon(Icons.departure_board),
            title: Text('发现')
        ),
        BottomNavigationBarItem(
            icon: Icon(Icons.people),
            title: Text('我的')
        ),
//        BottomNavigationBarItem(
//            icon: Image.asset('/images/bg.png'),
//            title: Text('发现')
//        )
      ],
    ))

路由

也就是页面跳转,通过navigator来管理路由导航,并提供了堆栈的管理方法,如,Navigator.push()–跳转下一级,Navigator.pop(),返回上一级

配置方式

基本路由

跳转
RaisedButton(
          child: Text("去搜索"),
          onPressed: (){
            Navigator.of(context).push(
              MaterialPageRoute(
                builder: (context) => SearchPage()//目标页
              )
            );
          },
        )
返回
Navigator.of(context).pop()

命名路由

定义在MaterialApp里,相当于Android的manifest文件里配置的Activity

调用步骤
  1. 先在MaterialApp注册页面信息
MaterialApp(
     //注册里一个搜索,一个设置页面
      routes: {
        '/search':(context) => SearchPage(),
        '/setting':(context) => SettingPage(),
      },
    )
  1. 在点击跳转的时候执行
Navigator.pushNamed(context, "/search");
或
Navigator.pushNamed(context, "/setting");
传值
//配置页面,类似Androd里Manifest.xml配置的Activity
final _routes = {
  '/search':(context,{arguments}) => SearchPage(arguments: arguments,),
  '/setting':(context,{arguments}) => SettingPage(arguments: arguments)
};

//传值固定配置函数
Route onGenerateRoute(RouteSettings settings) {
  final String name = settings.name;//点击跳转是输入的name//Navigator.pushNamed(context, "/search");name为"/search"
  final Function pageBuilder = _routes[name];//跳转的函数//(context,{arguments}) => SearchPage(arguments: arguments,)
  if (pageBuilder != null) {
    if (settings.arguments != null) {
      // 如果透传了参数
      return MaterialPageRoute(
          builder: (context) =>
              pageBuilder(context, arguments: settings.arguments));
    } else {
      // 没有透传参数
      return MaterialPageRoute(builder: (context) => pageBuilder(context));
    }
  }
  return null;
}

路由替换

页面1→页面2→页面3 点击返回到→页面1,
在页面2点击跳转的时候,执行以下跳转方法

Navigator.pushReplacementNamed(conext,name)

返回根路由

//相当于跳转到根页面,然后把之前的栈清空
            Navigator.pushAndRemoveUntil(
                context,
                MaterialPageRoute(builder: (context) => RootPage()),
                (route) => route = null);

跳转方式

  1. 路由直接跳转到下一个页面Navigator.pushNamed(context,"/nextPage");
    2. 跳转的下一个页面,替换当前的页面Navigator.of(context).pushReplacementNamed('/nextPage')
    3. 返回上一个页面 Navigator.of(context).pop()
    4. 返回到指定的页面(指定的页面必须已经在栈里)
    Navigator.of(context).popUntil(ModalRoute.withName(MyRoute.TABS))
    5. 跳转新页面并清空堆栈路由或者返回指定的路由Navigator.of(context).pushAndRemoveUntil( new MaterialPageRoute(builder: (context) => new MyTextFiled()), (route) => route == null //rootRoute()指定返回的路由 );

AppBar

顶部导航

属性

属性描述
leading标题前的一个控件,通常首页显示应用的logo,其他页面显示返回键
title标题
actions通常使用IconButton表示,可以放置按钮组
buttom通常放tabBar,标题下面显示一个Tab 导航栏
comTheme图标样式
titleTheme文字样式
centerTitle标题是否居中显示
backgroundColor背景栏颜色
Scaffold(
      appBar: AppBar(
        title: Text('myAppbar'),
        centerTitle: true,//标题是否居中
        backgroundColor: Colors.black,
//        leading: Icon(Icons.accessibility),//标题左边,没有点击事件的
        leading: IconButton(
          icon: Icon(Icons.beach_access),
          onPressed: () {
            Navigator.pop(context);
          },
        ), //标题左边,有点击事件的
        actions: <Widget>[ //导航右侧图标
          Icon(Icons.settings),
          Icon(Icons.departure_board)
        ],
      ),
      body: Center(
        child: Text('内容'),
      ),
    )

AppBar里的TabBar

常见属性
属性描述
tabs显示的标签内容,一般用Tab对象,也可以用其他Widget
controllerTabController对象
isScrollable是否可以滚动
indicatorColor指示器(下划线)颜色
indicatorSize指示器长度
label选择文字的颜色

在这里插入图片描述

DefaultTabController(
        length: 2,
        child: Scaffold(
          appBar: AppBar(
            bottom: TabBar(
              tabs: <Widget>[
                Tab(text: '热门',),
                Tab(text: '推荐',),
              ],
            ),
            title: Text('myAppbar'),
            centerTitle: true,//标题是否居中
            backgroundColor: Colors.black,
//        leading: Icon(Icons.accessibility),//标题左边,没有点击事件的
            leading: IconButton(
              icon: Icon(Icons.beach_access),
              onPressed: () {
                Navigator.pop(context);
              },
            ), //标题左边,有点击事件的
            actions: <Widget>[ //导航右侧图标
              Icon(Icons.settings),
              Icon(Icons.departure_board)
            ],
          ),
          body: TabBarView(
            children: <Widget>[
              Text('热门内容'),
              Text('推荐内容')
            ],
          ),
        ),
      )
切换
  1. 代码配置
body: TabBarView(
            children: <Widget>[
              Text('热门内容'),
              Text('推荐内容')
            ],
          ),

2.TabContoller

import 'package:flutter/material.dart';

class MyTabBarCtrlPage extends StatefulWidget {

  @override
  State<StatefulWidget> createState() {
    return _MyTabBarCtrlPageState();
  }
}

class _MyTabBarCtrlPageState extends State<MyTabBarCtrlPage> with SingleTickerProviderStateMixin{

  TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(
        vsync:this,
        length:3
    );
    _tabController.addListener(() {
      print('index= ${_tabController.index}');
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('MyTabBarCtrlPage'),
        bottom: TabBar(
          controller: this._tabController,//注意,必须要加
          tabs: <Widget>[
            Tab(text: '热门'),
            Tab(text: '推荐'),
            Tab(text: '更多')
          ],
        ),
      ),
      body: TabBarView(
        controller: this._tabController,//注意,必须要加
        children: <Widget>[
          Center(
            child: Text('热门内容'),
          ),
          Center(
            child: Text('推荐内容'),
          ),
          Center(
            child: Text('更多内容'),
          )
        ],
      ),
    );
  }
}

Drawer

抽屉组价、侧边栏

左侧栏

Drawer()

右侧栏

endDrawer()

侧栏普通头部

DrawerHeader

侧栏用户头部

UserAccountsDrawerHeader()

caffold(
      appBar: AppBar(
        title: Text('MyDrawer'),
      ),
      body: Center(
        child: Text('内容'),
      ),
      drawer: Drawer(
          child: Column(
            children: <Widget>[
              DrawerHeader(
                child: Text('左侧标题'),
              ),
              Divider(),
              Text('左侧边栏内容'),
            ],
          )
      ),
      endDrawer: Drawer(
        child: Center(
          child: Text('右侧边栏内容'),
        ),
      ),
    )

按钮组件

名称描述
RaisedButton凸起按钮
FlatButton扁平化按钮
OutlineButton线框按钮
IconButton图标按钮
ButtonBar按钮组
FlatingActionButton浮动按钮

在这里插入图片描述

表单

TextFiled

文本框组件(Editext)

TextField(
          obscureText: true,//密码框
          maxLines: 1,
          decoration: InputDecoration(
            icon: Icon(Icons.people),
            hintText: '请输入内容',
            labelText: '用户名',//显示在输入框左上角
            border: OutlineInputBorder(),//变边框的
          ),
        )
获取TextFiled里的值

监听onChanged()方法

TextField(
//              obscureText: true,//密码框
              maxLines: 1,
              decoration: InputDecoration(
                icon: Icon(Icons.people),
                hintText: '请输入内容',
                labelText: '用户名',//显示在输入框左上角
                border: OutlineInputBorder(),//变边框的
              ),
              onChanged: (value){
                 
              },
            )

CheckBox

Checkbox(
              value: this._checkFlag,
              onChanged: (value) {
                setState(() {
                  this._checkFlag = value;
                });
              },
              activeColor: Colors.yellow,//选择的颜色
            )

CheckBoxListTile

在这里插入图片描述

CheckboxListTile(
              value: this._checkFlag,
              title: Text('标题'),
              subtitle: Text('内容'),
              secondary: Icon(Icons.settings),//左侧加图片
              onChanged: (value) {
                setState(() {
                  this._checkFlag = value;
                });
              },
            )

Radio

Radio(
              value: 1,
              onChanged: (v){
                setState(() {
                  this._radioValue = v;
                });
              },
              groupValue: this._radioValue,//radio组选择的值
            )

RadioListTile

类似RadioListTile的用法

本地化语言设置

  1. 引入依赖
    在pubspec.yaml文件中配置
dependencies:
  flutter_localizations:
    sdk: flutter
  1. 在入口处
MaterialApp(
      //配置本地化
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate
      ],
      supportedLocales: [
        const Locale('zh', 'CH'),
        const Locale('en', 'US')
      ],
      )

日期组件

官方控件

日期

showDatePicker(
        context: context,
        initialDate: _nowDate,
        firstDate: DateTime(1970),
        lastDate: DateTime(2021)
    ).then((result){

    })

时间

showTimePicker(
        context: context,
        initialTime: TimeOfDay.now()
    ).then((result){

    });

Swiper(第三方轮播图组件)

轮播图组件

new Swiper(
          itemCount: 3,
        itemBuilder: (BuildContext context,int index){
            return Image.network(
              'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2628977794,1833531909&fm=26&gp=0.jpg',
              fit: BoxFit.cover,);
        },
        pagination: SwiperPagination(),//指示器(点下。。。)
        control: SwiperControl(),//配置左右箭头
      ),
    )

AlertDialog

在这里插入图片描述

showDialog(
              context: context,
              builder: (context) {
                return AlertDialog(
                  title: Text('标题'),
                  content: Text('内容'),
                  actions: <Widget>[
                    FlatButton(
                      child: Text('取消'),
                      onPressed: (){
                        Navigator.pop(context);
                      },
                    ),
                    FlatButton(
                      child: Text('确定'),
                      onPressed: (){
                        Navigator.pop(context);
                      },
                    ),
                  ],
                )

SimpleDialog

在这里插入图片描述

showDialog(
              context: context,
              builder: (context) {
                return SimpleDialog(
                  title: Text('标题'),
                  children: <Widget>[
                    SimpleDialogOption(
                      child: Text('option 1'),
                      onPressed: (){},
                    ),
                    SimpleDialogOption(
                      child: Text('option 2'),
                      onPressed: (){},
                    ),
                    SimpleDialogOption(
                      child: Text('option 3'),
                      onPressed: (){
                        Navigator.pop(context,'3');//其中参数'3'可以当结果返回
                      },
                    ),
                  ],
                );

ShowBottomSheet

在这里插入图片描述

showModalBottomSheet(
            context: context,
            builder: (context){
              return Container(
                height: 160,
                child: Column(
                  children: <Widget>[
                    Text('选项一'),
                    Divider(),
                    Text('选项二'),
                    Divider(),
                    Text('选项三'),
                    Divider(),
                    Text('选项四'),
                  ],
                ),
              );
            },
          );

Toast(FlutterToast)

第三方库

 Fluttertoast.showToast(
              msg: 'hello toast',
            toastLength: Toast.LENGTH_SHORT,
            gravity: ToastGravity.CENTER,
            backgroundColor: Colors.black,
            timeInSecForIos: 1,// only iOS
            textColor: Colors.white,
            fontSize: 15,
          );

自定义Dialog

步骤

  1. 写一个组件extend Dialog
import 'package:flutter/material.dart';

class MyCustomDialog extends Dialog{

  @override
  Widget build(BuildContext context) {
    return Material(//注意点
      type: MaterialType.transparency,//设置透明
      child: Center(
        child: Container(
          height: 180,
          width: 320,
          color: Colors.white,
            child: Text('自定义dialog'),
        )
      )
    );
  }
}
  1. 调用的地方
showDialog(
	 context: context,
     builder: (context){
     	return MyCustomDialog(); //此处
 	}
);

网络请求

Json数据与Map类型的转换

需要引入 import ‘dart:convert’

Map转Json字符串

Map map = {
      '年龄':'21',
      '性别':'男',
      '地址':'xxxx',
    };
String jsonStr = json.encode(map);
print('jsonStr= $jsonStr');

Json.encode(Map)

Json字符串转Map

Json.decode(jsonStr)

String jsonStr2 = '{"年龄":"21","性别":"男","地址":"xxxx"}';
Map map2= json.decode(jsonStr2);
print('map2[年龄]= ${map2["年龄"]}');

get请求

String url = 'https://suggest.taobao.com/sug?code=utf-8&q=%E5%8D%AB%E8%A1%A3';
    http.Response respone = await http.get(url);//异步请求
    print('http_code= ${respone.statusCode}');
    if (respone.statusCode == 200) {
      print('http_body= ${respone.body}');
      setState(() {
        this._result = respone.body;
      });
      Map map = convert.jsonDecode(respone.body);//转换为map
    }

post请求

print('http_getData');
    String url = 'https://suggest.taobao.com/sug?code=utf-8&q=%E5%8D%AB%E8%A1%A3';
    http.Response respone = await http.post(url,body:this._map);//异步请求
    print('http_code= ${respone.statusCode}');
    if (respone.statusCode == 200) {
      print('http_body= ${respone.body}');
      setState(() {
        this._result = respone.body;
      });
      Map map = convert.jsonDecode(respone.body);//转换为map
    }

Flutter与原生的混合集成

主要有以下两种

源码集成AAR(andriod),framework(iOS)集成
优点1. 简单快捷 2. 和原生交互较多或需要依赖原生的数据环境时,使用该方式调试方便1. 不影响原生项目 2. 不参与Flutter开发的人员处于无感状态 3. 无需对先原生环境做修改
缺点1. 团队所有人需要安装Flutter环境 2. 需要对现在编译发布体现做修改1. 复杂度较高 2. 与原生调试不是很方便

源码集成

  1. 在原APP Native工程项目里,添加flutter_module
  2. 安装flutter相关开发插件

AAR集成

  1. 创建单独的flutter工程并创建flutter_module
  2. 开发完成,打包成aar
    执行flutter builde aar完成后,控制台会提示配置以下信息
1. Open <host>/app/build.gradle
  2. Ensure you have the repositories configured, otherwise add them:

      repositories {
        maven {
            url '/Users/wangpingtao/yuxun/exitApp/flutter_module/build/host/outputs/repo' //new
        }
        maven {
            url 'http://download.flutter.io' //new
        }
      }

  3. Make the host app depend on the Flutter module:

    dependencies {
      debugImplementation 'exit.wpt.com.flutter_module:flutter_debug:1.0 //new
      profileImplementation 'exit.wpt.com.flutter_module:flutter_profile:1.0 //new
      releaseImplementation 'exit.wpt.com.flutter_module:flutter_release:1.0 //new
    }


  4. Add the `profile` build type:

    android {
      buildTypes {
        profile { //new
          initWith debug //new
        } //new
      }
    }
  1. 在app/build.gralde文件配置aar相关信息:配置aar相关信息
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值