• 初级基础系列

Flutter开发实战初级(1)ListView详解

Flutter开发实战初级(2)布局详解

  • 项目实战系列

Flutter开发实战 高仿微信(1)主页

Flutter开发实战 高仿微信(2)发现页

Flutter开发实战 高仿微信(2)发现页

1.项目代码

1.1 微, f 6 ~ $ 9信发现页面简述

  1. 在上一篇《flutter开发微信之一》中解说了项目结构的简略树立,整个APP分为四个tabbar:微信,通讯录,发现,我。其间发现是最简略一个页面,先从最简单的页面下手,完结发现页面主页树立。

1.2 APP结构优化

1.2.1 装备APP Logo和启动图片

  1. IOS 启动图片装备
    Flutter开发实战  高仿微信(2)发现页
  2. Android启U z 1 v R / L动图片装备
    Flutter开发实战  高仿微信(2)发现页

1.2.2 装备资源图片

  1. flutter 项目资源在pubspecI @ 3 t.yaml中装备

    Flutter开发实战  高仿微信(2)发现页
  2. 在代码中运用图片资源的办法:

  3. 不同分辨率的图片运用
    跟Android的多图片适配相同,将不同分辨率下的图片放到对应的目录即可,如下:

    Flutter开发实战  高仿微信(2)发现页

    运用代码:

new Image.asset("assets] R V { F b } I/images/a.png");
  1. flutter 在项目中加载资源的两种办法:
  • 经过rootBz B Xundle3 y T W l目标来加载(每个Flutter运用都有一个rootBundle目标,能够拜访主asset bundle) . 假如你地点的业务场景下,拿不到context(不在widget中),那就运用这个吧,不然运} # Q ) l 7 v r用下面的办法。
import 'package:flutter/services.dartA ) ; G n';
Widge* e @ u / ` T - t _createBody() {
return new Fut[ i R uureBuilder(
future: rootBundle.loadString('assm E eets/a.js L F 9 on4 h 2'),
build8 : A Q C ` wer: (context,snapshot){
if(snapshot.hasData) {
return new Text(snapsh_ v K q q d n T hot.data.toString()X * U 0 B k z ( =);
}
},
);
  • 经过DefaultAssetBundle 来获取当时BuildContext 的 AssetBundle,引荐运用。比办法一要灵敏。能够自己拟G j $定。
import 'packageg ? @ $ d e l :flutter/servi o Vices.dart';
Widget _createBody() O f % P Q ` * {
return new FutureBuilder(
futuA u N j 3 { jre: DefaultAssetBundle.of(context).loadString('assets/a.json'),
builder: (context,snapshot){
if(snapshot.hasData) {
return new Text(snapshot.data.toString());
}
},
);

1.2.3 装备其他资源

1.2.3.1 String 资源装备

新建一个.dart文件,比方uidata.dart:

import 'package:flutter/material.dart';
class UIData {
//routes  页面途径
static const String homeRoute = "/home";
static const String profileOneRoute = "/View Profile";
static const String profileTwoRoute = "/ProfiV ? $ R / G Ile 2";
//stringQ g Es
static const String appName = "| 5 Q T L A WFlutter UIKit";
//fonts  字体相关
static const String quickFont = "Quicksand";
static const String ralewayFont = "Rale{ K w + m & d h pway";
static const_ f k X ] String quickBoldFont = "Quicksand_Bold.otf";
static const String quickNormalFont = "Quie p $ F *cksand_Book.otf";
static con^ O } z Mst StriS . b / K H m .ng quickLightFont = "@ b f +Quicksand_Light.otf";
//images
statD X - fic const String imageDir = "assetG H ) P Bs/ # $ 9 I %images";
static const String pkImagG a n 9e = "$imageDir/pk.jpgH : ^ ( # / * h"d . Y i ! ?;
//login  比方登录页面用到的文本
static const String entL i e i W Der_code_label = "Phone Number";
static const String enter_code_hiD u ` E : ~nt = "10 Digit Phone Number";
//gneric 通用的文本
staticM d X ; U E e s [ cons# _ Y { kt String error = "Error";
static const String success = "SS & = v , 7 Uuccess";
static const MaterialColor ui_kit_color = Colors.grey;
//colors
static List<Color> kitGradients = [
// new Color.fromRGBO(103, 218, 255, 1.0),
/( } B V [ Q/ new Color.fromRGBO(3, 169, 244, 1.0)G g a w X I X,
// new Color.fromRGBO(0, 122_ 8 , 193, 14 5 ) +.0),
Colors.blueGrey.shade800,
Colors.black87,
];
static List<Color> kitGradients2 = [
Colors.cyan.shade600,
Colors.blue.shZ l ( 7 e tade900
];
//randomcolor
static final Random _random =B r u _ )  new Random();
/// Returns a random color.
static Color ne? x 9xt() {
return new Color(0xFF000000 + _random.nextInt(0x00FFFFFF));
}
}

1.2., O X } u Z h3.2 国际I , G K I R . 7 P

详情参考:国际化官方教程

Flutter开发实战  高仿微信(2)发现页

1.2.n V O 8 u * p [ =4 增加依靠

在pubspec.yaml 中增加依靠
注意,只有在增加渠道所需相关依靠时,才需求去AndI W Iroid 工程中的gradle中增加+ A 7 ? J依靠。

1.2.5 新建四I L L ] 1个主页对应四个tabbar

1.3 发现页面布1 M ) ; p d

2.知识点

2.1 flutter布局

2.1.1 Row 水平布局

  1. 简介

flex水平布局控件,能够将子控件水平摆放,是依据Web的flexbox的布局模式规划的。
Row子控件有灵敏与不灵敏的两种,Row: J n Y i i 1 D p首要列出不灵敏的子控件,减去它们的总宽度,计H q H N $ e f P o算还有多少可用的空间。然后Row按照Flexible.flex特点确认的份额在可用空间中列出灵敏的子控件。要操控灵敏子V i m S l 控件,需求运用Expanded控件。
注意该控件不支持滑动,假如子控件超越剩下空间,会报错,假如想支持水平滑动,考虑运用ListView。
假如只有一个子控件,能够运用 Align or Center控件界说该子控件方位。

  1. 实例
 1 new Row(
2   children: <Widget>[
3     new Expanded(
4       child: new Text('Deliver features faster', textAlign: TexV v / -tAlign.center),
5     ),
6     new Et X y  9 - oxpan` E f / [ 8 o S Zded(
7       chi~ Y _ * g K E i ^ld: new Text($  h % x 8 ^ - :'Craft beautiful UIs', textAlign:+ = ) n ` & f , TextAlign.center),
8     ),
9     new Expanded(
10       child: new FittedBox(
11         fit: BoxFit.R x a ) W & m Jcontain, // otherwise the logo will be tiny
12         child: const FlutterLogo(),
13       ),
14     ),
15   ],
16 )
  1. 用法

2.1.2 Column 笔S * [ h直布局

  1. 简介
    flex笔直布局控件,能够将子控件笔直摆放。
    用法与Row控件相同。
  2. 实例
new Column(
2   crossAxisAlignment: CrossAxisAlignment.start,
3   mainAxisSize: MainAxisSize.min,
4   children: <Widget>[
5     new Text('We move under cover and we move as one'),
6     new Text('ThS C ~rough the night, we have one shot to live another day` g / K | ` 3'),
7     new Text('c = ^ _ { V q 7We cannot let a stray gunshot give us away'),
8a  h 3 & H M / &     new Text('We will fight up close, seize the moment and stay in it')@ % : i ` = Q,
9     new Text('It’s either that or meet the business end of a bayonet'),
10     new Text('The code word isRochambeau,’ dig me?'),
11     new Text('Rochambeau!', style: DefaultTextStyle.of(context).style.apply(fontSizeFactor: 2.0)6 b I),
12   ],
13 )
  1. 用法

2.1.3 Stack 层布局

  1. 简介p N X b 8 H V v %

  2. 实例

  3. 用法

2.1.4 主轴

  1. 简介

  2. 实例

  3. 用法

2.1.5

  1. 简介

  2. 实例p j x 2 * + c p

  3. 用法M , Y s X S

2.2 flutter根本组件

FQ l z S @lutter控9 2 r G件本身一般由许多小型、单用途的控件组成,结合起来发生强壮的作用,例如,Container是一种常用的控件,由担任– u % e 1 J j布局、绘画、定位和巨细调整的几个控件组K ? J w成,具体来说,Container是由LimitedBox、Cl t ! !onstrainedBox、 Align、Padding( s m |、Dc { e A ? g ~ – wecoratedBox和Transform控件组成,而不是将Container子类化来发生自界说作用e M K J C # I A,您能够用这种新颖的@ W 0 i f 6办法组合这些以及其他简略的控= ( f @ W件。

类的层次结构是扁平的,以最大化可能的组合数量。

Flutter开发实战  高仿微信(2)发现页

在写运用程序时,常常会运用StatelessWidget和StatefulWidget编写新控件,两者的差别在于你是否要管理控件的状况。一个控件的首要任务是完结build函数,界说控件中其他较低层次的控件。: s P 5 9 sbuild函数将依次构建这些控件,直到底层渲染目标。

  • Flu 0 ( E 4utter控件和Android,IOS原生控件比较
Flutter控件 Android控件 IOS控件
App` x } z A u [ H GBar ActionBar/ToolBar UINavgationBar
ListView ListView/Recycle^ d 8 i : xr% d ^ i 7 u bView UITableView
ListView ListView/RecyclerView UITableView
Text TextView UILabel
Center ViewGroup
Container RelativeLayout
FloatingAc@ f K , ; 5 } ^tionButton FloatingActionButton(design库里边的)
BottomNavigationBar BottomNavigation(design库里边的)
RaisedButton/Button Button
Column Lineao c 0 F ZrLayout的android:orientd R t 8 Eation=”Q % ~ ,vertic= 5 { ) h ; Wal”
Row android:orientation=”horizontal”
DecorationImage ImageView
Im! V . | H i g @ #age ImageView UIImageView
Stack Fr: B p vameLayout/RelativeLayout
Algin alginPareK m 0 z 5 # rntXXX特点
resizeToAvoidBottomPadding android:windowSoft, V E aInputMode=x ] v 3 3 F C adjustResize特点
SingleChildScrollView ScrollView UIScrollView
CustomScrollerView Recyclerview j ! e m

2.2.1 Container

  1. 简介

容器,一个常用的控件,由根本的制作、方位和巨细控件组成。担任创建矩形的可视元素,能够用BoxDecoration来规划款式,比方布景、边框和阴影,Container也有边距、填充和巨细} } y S限制,另外& = c $ / s s 5,还能够在三维空间利用矩阵进行变换。
没有子控件的容器尽可能大,除非传入的巨细} n h = : 3束缚是无限的,在这种情况下,它们尽可能小。有子控y 5 { ` c x p H件的容器将自己的尺度给他们的孩子。咱们能够经过width、height和 constraints特点操控size。

  1. 实例
new Container(
constraints: new BoxConstraints.y  j | 5 Fexpand(
height: Theme.of(context).textTheme.display1.fontSize * 1.1 + 200.0,
),
padding: const EdgeInsets.all(8.0),
c% y 8 5 n U [ )olor: Colors.teaP w ol.shade7R = (  @ o ; T00,
alin q / ! 5 k +gnment: Alignment.center,
child: new Text(* K } l f'Hello World', style: Theme.of(_ 8 t 5 Jcontext).textTheme.display1.copyWith(color: Colors.whitX p ] z ~ s 9e)),
foregroundDecoration: new BoxDecoration(
image: new DecoratioL Z v @ ) ? dnImage(
image: ne 2 m = 2 ^ew NetworkImage('httz 7 . n q 3 ;ps://www.example.com/images/frame.png'),
centerSlice: new Rect.fromLTRB(270.0, 180.0, 1360.0, 730.0),
),
),
transform: new Matrix4.rZ J + r Y v t kotationZ(0.1),
)
  1. 用法

2.2.2 Image

  1. 简介

显现图画的控件,Image控件有多C M O种构造函数:
new Image,用v g h 9 8 ~于从ImageProvider获取图画。
new Image.asset,用于运用key从AssetBundle获取t N 1 A P A图画。
new Image.network,用于从URL地址获取; E Q } W s n 5图画。
new Image.file,用于从File获取图画。

为了主动履行像素密度感知资源分辨率,运用AssetImage指定图画,需求确保在控件树中的图片控件上方存在Materia* ! V 3 SlApp、WidgetsApp和MediaQuery控件。

不同p F u的手机有不同的j 4 ! d C k 2像素比率,这时就需求依据手机的像素比率来加载不同图片,做法很简略,只需求在图片同级目录下创建2.0x/…和3.0x/…的目录就能够了。

咱们在pubspec.yaml这个文件里指定本地图片途径

# To add assets to your applica} I H Ktion, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_do] T 8 # v _ j Tt_ham.jpeg
  1. 实例2 N O y | r M p

  2. 用法

2F ; m ? K T / ].2.3 Texa # c @ l T s & +ti [ T S a % L

  1. 简介

  2. 实例
    下面的实例= } U ( X i , –有7个不同款式的文本控件:

1 import 'package:flutter/material.dart';
2 class TextDemo extends StatelessWidget {
3   @override
4   Widget build(Build3 ~ C [ : u k lCo# U , x D ~ D ^ntext context) {
5     return new Scaffold(
6       appBar: new AppBar(
7         title: new Text('文本控件'),
8       ),
9       body: new Column(
10         children: <Widget>[
11           new Text(
12             '红色+黑色删去线+25号',
1g u q j3             style: new TextStyle(
14               color: const Color(0xffff0000),
15               decoration: TextDecoraW $ V 5 x i 9 _ ,tionz s c 1 w * [ _.lineThrough,
16               decorationColor: const Color(0xff000000),
17               fontSize: 25.0,
18             ),
19           ),
20           new Text(
21             '橙色+下划线+24号',
22h . M 7             style: new TextStyle(
23               color: const Color(0xffff9900),
24               decor: y +  Kation: TextDecoration.underline,
25               fontSize: 24.0,
26             ),
27           ),
28           new~ ) 3 H TeB W U v K G 0 oxt(
29             '虚线上划线+23号+歪斜',
30             style: new TextStyle(
31               decoration: TextDecoratioY ^ A 0 w W F 1n.overline,
3G X K P2               decorationStyle: TextDecorationStyle.dasy h ` B s q s I vhed,
33               fontSize: 23.0,
34               fontStyle: FontStyle.italic,
35             ),
36           ),
37           new Text(
38             'serif字体+24号',
3Y E Q ] ` ; h9Q } V Z t 2 I             style: nJ & bew TextStyle(
40               fontFamily: 'serif',
41               fontSize: 26.0,
42             ),
43I S / ( I           ),
4@ Y y4           new Text(
45             'monospac% ] 2 % R Se字体+24号+加粗E 0 b - l d Z } 6',
46             style# ! e v: new TextStyle(
47               fontFamily: 'monospacep 2 b c',
48j e ` b - : 9               fi 4 b 5 } f U r =ontSize: 24.0,
49               fontWeight: FontWeight.bop ; 4 yld,
50             ),
51           ),
52           new Text(
53             '天蓝色+25号+2行跨度',
54             style: new TextStyle(
55               color: const Colo| : $ ^ A T : } Xr(0xff4a86e8),
56               fontSize: 25.0,
57               height: 2.0,
58             ),E ` s
59           ),
60           new Text(
61             '24号+2个字母距离',
6z ) q2             style: new TextStyle(
63               fontSize: 24y ; / G 7 1 ( B.0,
64               letterSpacing: 2.0,
65             ),
66           ),
67         ]8 i L q
68       ),
69     );
70   }w ? t Y z !
71 }
72 void main()t 1 : D 6 e a {
73   runApp(
74     new MaterialApp(
75       title: 'Flutter教程',
76       home: new TextDemo(),
77     )# 1 Y Z m - P G,
78   );
79 }= 5 + c `

运转作用:

Flutter开发实战  高仿微信(2)发现页

3. 用法

2.2.4 IY 2 2 n 5con

  1. 简介

图标控件,按照IconData中所描绘的规则制作,如Materi9 / b { I :al中预界说的IZ F 4 nconDatas。
该控件不可交互,要完结可交互的图标,能够考虑运用Material中的 IconButton。
该控件有必要在 Directionality控件里运用,一般这是由WidgetsApp或 MaterialApp主动引进的。详见Q 4 7 U C:docs.flutter.io/flutter/wid…

  1. 实例

  2. * s K + * ! N j

2.2.5 RaisedButton

  1. 简介

Material Design 风格的浮动按钮,以方形纸片款式悬停在界面上,点击后会发生墨水分散作用。
防止在dialog和card控件里运6 @ 9 n 3用,一般弹出式的控件主张运用扁平化按钮,减少布局层次叠加。详见:docs.flutter.io/flutter/mat…

  1. 实例

  2. 用法
    运用时,要完结onPressed回调办法,不然按钮处于禁用状况,默许显现disabledColf O l / Gor款式的扁平化按钮,而且此时更改按钮的色彩不会收效。
    注意该控件的父控件有必要是{ O Z X sMaterial控件。
    假如你只需求点击后发生墨水分散作用,但不想运用按钮,( [ ` 4 j d请考虑直接运用InkWell控件。
    如有必要,该按钮将拉伸以适应子控件巨细。

2.^ v d 4 4 / x ? @2.6 Scaffold

  1. 简介

Scaffol7 x R :d 完结了根本的Material Design布局结构。也便是说M 1 x ^, MaterialApp 的 child 是 Scaffold Widget。
在Material规划中界说的单个界面上v 5 _ { : 6 I &的各种布局元素,在 Scaffold 中都有支持,比方 左边栏(Drawers)、snack bars、以及 bottom sheets。

Scaffold 有下面几个首要特点:

  • appBar:显现在界面顶部的一个 ApE w M V ( k p .pBar,也便是 Android 中的 ActionBar 、Toolbar

  • body:当时界面所显现的首要内容 Widget

  • floV n YatingActionButton:Material规划中所界说的 FAB,) & Y , w界面的首要功能按钮

  • persistentFooterButtons:固定在下方显现的按钮,比方对话框下方的确认、撤销按钮

  • drawer:侧边栏控件

  • backgroundColor: 内容的布景色彩,默许运用的是 ThemeData.sca ) vffoldBackgroundColor 的值

  • bottomNavigationBar: 显现在页面底# g _ B :部的导航栏

  • resizeToAvoidBottomPaddiB X sng:类似于 Android 中的 android:windowSoftInputU 9 { N p ]Mode=”adjustResize”,操控界面内容 body 是否从头布局来防X Y B R N +止底部被覆盖了,比方当键盘显现的时分,从头布局防止被键盘盖住内容。默许值为 true。

显现 snackbar 或许 bottom sheet 的时分,需求运用当时的 BuildContext 参数调用 Scaffold.of 函数来获取 ScaffoldState 目标,然后运用 ScaffoldState.showSnackBar 和 ScaffoldState.showBottomSheet 函数来显现。

要特别注意 Scaffold.of 的参数 BuildContext, 假如包含该 BuildContexC z { N 8 _t 的 Widget 是 Scaffold 的父 Widget,则 Scaffold.of 是无法查找到对应J / i的 ScaffoldStaT b h c ) ) ( & .te 目标的,Scaffold.of 回来的是父目标中最近的 Sc C b 5 Yaffo* ` o | P sle , _ 3 e y U qd 中的 ScaffoldStaz k Z ute 目标。 比方a ! } U E ~ { e,假如在 Scaffold 的 build 函数中,运用 build 的 BuildContext 参数是能够的:

 1 @ove) L p yrride
2 Widget bd x - p j +uild(l 5 $ #BuildContext context) {
3   return new RaisedButtox X e V I Pn(
4     child: ne n q V w Text('SHOW A SNA1 d gCKBAR'),
5= o I u X { D     onPressed: () {
6       Scaffold.of(context).showSnackBar(new SnackBar(
7         content: new Text('Hello!'),
8       ));
9     },
10   );
11 }
  1. 实例
    假如 build 函数回来一个{ * 8 q Q o @ Scaffold 目标,则由于~ 5 3 z w 2 X s i Scaffold 目标是这个 Widget 的子目标,所以运用这个 build 的 BuildContext 参数是不能查找到 ScaffoldState 目标的,这个时分,经过在 Scaffold 中运用一个 Builder 来提供V ` s一个新的 Build. r =Conext :
@override
2S % V +  C | 0 T Widget build(BuildContext context) {
3   retz | 9 gurn new Scaffold(
4     appBar: new AppBar(
5       title: ne% 9 - ( R & T d Kw Text('Demo')
6     ),
7     body: new Builder(
8       // Create an inner BuildConteV X U Oxt so that theW N 6 D O { h | o onPressed methods
9       // can refer to the Scaffold with Scaffold.of().
10       builder: (BuildContexv D 5t context) {
11         return new Center(
12           chil@ D A [ & #d: new RaisedButton(
13             child:D q [ H news | y Text('SHOW A SNACKBAR'y 5 y @ c b N 2 q),
14             onPressed: ()B X y _  a R x { {
15               Scaffold.of(context).showSnackBar(new SnackBar(
16                 content: new Text('HT r e  cello!'),
17               ));
18             },
19           ),
20         );
21       },v } L
22     ),
23   );
24 }

另外还能够把 build 函数中的 Widget 别离创建,别离引进新的 BuildContext 来获取 Scaffold。

  1. 用法

2.2.7 Appbar

  1. 简介

AppBar 和 SliverT – : ] , ; CAppBar 是Material Design中的 App Bar,也便是 An# m | Odroid 中的 Toolbar,关于 To/ q ! p . z 7olbar 的规划指南请参考Material Design中 Toolbar 的内容。
AppBar 和 SliverAppBar 都是继承StatefulWidget 类,都代表 Toobar,二者的差异在于 AppBar 方位的固定的运用最上面的;而 SliverAppBar 是能够跟随内容翻滚的。

他们的首要特点如下:T = k

  • leadingP 3 6 a ]:在标题前面显现的一个控件,在主页一般显现运用的 logo;在其他界面一般显现为回来按钮

  • title: Toolbar 中1 W [首要内容,一[ , [ .般显现为当时界面的标题文字

  • actions:一个 Widget 列表,代表 Toolbar 中所显现的菜单,关于常用的菜单,一般T F [ q运用 IconBy # ^ d X @ N Outton 来表明;关于不常用的菜单一般运用 PopupMenuButton 来显现为三个点,点击后弹出二级菜单

  • bottom:一个 AppBarBottomWidget 目标,一般是 TabBar。用来在 Toolbar 标题下面显现一个 Tab 导航栏

  • elevation:纸墨规划中控件的 z 坐标顺序,默许值为 4,关于可翻滚的 SliverAppBar,当 SliverAp$ R VpBar 和内容同级的时分,该值为 0, 当内容翻滚 S& b j L 0liverAppBar 变为 T– _ x f 9 , i Moolbar 的时分,修正 elevation 的值

  • flexibleSpace:一个显现在 AppBar 下方的控件,高度和 A ! l 2 _ppBar 高度相同,能够完结一些特殊的作用,该特点一般在 SliverAppBar 中运! V f

  • backgroundColor:APP bar 的色彩,默许值为 ThemeData.primaryColor。改值一般和下面的三个特点一同运用

  • brightness:9 m j App bar 的亮度,有白色和黑色两种主题,默T n / j U 7 Y许值为 ThemeData.primaryColorBrightness

  • iconTheme:App bar 上图标的色彩、透明4 b n l 9 c q & c度、和2 a ) M F 尺度信息。默许值为 ThemeData.primaryIconTheme

  • textTheme: App bar 上的文字款式。默许值为 ThemeData.primaryTextTheme

  • centerTitle: 标题是否居中显现,默许值依据不同的操作系统,显现办法不相同

  1. 实例
import 'pu N n : | Uackage:flutter/material.dart';
2
3 class AppBarBottomSamL o O A _ple extends StatefulWidget {
4   @override
5   _AppBarBottomSampleState createState() => new _AppBarBottomSampleStateh a ^ g ~ U();
6 }
7
8 class _AppBarBoh $ _ b y ]ttomSampleStateh a : & @ extends State<AppBarBotb 6 % , f 6 k S #tomSample> with Sing( W [leTickerProviderStateMixin {
9   TabController _tabContm ? S lroller;
10
11   @override
12   void initState() {
13     super.initState();
14     _tabControll1 K [ S per = new TabContrt U B %oller(vsync: this, length: choiq b S / F m Uces.length);
15   }
16
17   @override
18   void dispose() {
19     _tabController.dispose();
20     super.dispose();
21   }
22
23   void _% { : knextPage(int delta) {
24     final int newIndex = _tabController.index + delta;
25     if (newIndex < 0 ||h ? M z & = newIndex >= _tabController.length)
26       return;
27     _tabController.animateTo(newIndex);
28   }
29
30   @override
3F 4 + J T n i1   Widget build(BuildContexR % X - + Z | r !t context) {
32     returw T u : Mn new MaterialApp(
33       home: new Scaffo= H B yld(
34         appBar: new AppBar(
35           title:` $ 6 i 8 cons9 E l p u v # @t Text('AppBar Bottom Widget'),
36           leading: new IconButton(
37             tooltip: 'Previous choice',
38             icon: const Icon(IconsA C J 6 2 s h ,.arD 7 @ c Zrow_back),
39             onPressed: () { _nextPage(-10 | ) . _ ? w); },
40           ),
41           actio9 ! 2 G S . W ons: <Widget>[
42             new IconButton(
43               icon: const Icon(Icons.arrow_forward),
44               tooltip: 'Next choice',
45               onPressed: () { _nextPage(1); },
46             ),
47           ],
48           bottom: new PreferredSize(
49             preferredSize: const Size.froq * 3 S @ Z C q OmHeight(48.0),
50             child: new Theme(
51               data: T$ | q B vheme.of(c3 e A ~ T - N %ontext).copyWith(accentColor: Colors.white),
52               childA z ~ #: new Container(
53                 height: 48.0,
54v 3 b X )                 alignment: Alignment.cen} o /ter,
55                 child: new TabPageSelec_ $ s J 3 2 : xtor(controller: _tabController),
56               ),
57             ),
58           ),
59C } x V 1 i J m b         ),
60         body: newM N V ) P TabBarView(
61           controller: _tabController,
62           childre s - , p In: choices.map((Choice choice) {
63             retu/  A ; nrn new Padding(
64               padding: con` { K bst EdgeInsets.ag G c x ell(16.0),
65               child: new ChoiceCard(choice: choice)` p _ I r @ J 2 D,
66             );
67           }).toList(),
68         ),
69       ),
70     );
71   }
72 }
73
74 class Choice {
75   const Choice({ this.title, this.ic M j K E j e con });
76   final Strij 3 X [ E % $ ?ng title;
77   final IconData icon;
78 }
79
80 const List<Choice> choices = const <Choice>[
81   const Choice(title: 'CAM C O t [ b - n R', icon:s I a , F & k IcP / ` $ 8 P +ons.directions_car),
82   const Chj W d _ # f 2oice(title: 'BICYCLE', icon: Icons.directions_bike),
83   const Choice(title: 'BOAT', icon: Icons.directions_boat),
84   const Choice(title: 'BUS', icon: Icons.directionN s u I ,s_bus),
85   const Choice(title: 'TRAIN', icon:j l P ] J Icons.directioL h 1 c 0 ] { P tns_railway),
86   conv c [ x & x tst Choice(title: 'WALK', iconu o - + .: Icons.directions_walk),
87 ];D 0 M a C
88
89 class ChoiceCard exV 5 1 (tends StatelessWidget {
90   const ChoiceCard({ Key key, this.cG + 2 _ c V shoice }) : super(key: key);
91
92l ~ 9 0 ! | Y Z F   final Choice choice;
93
94   @overridem R - ; - ,
95   Widget buQ S ?ild(BuildContext context) {
96     final TextStyle textStyle = Theme.of(context).textTheme.display1;
9I F U Q 0 87     return new Card(
98       color: Colors.white,
99       child: new Center(
100         child6 % Q 5: new Column(
101           mainAxisSI s kize: MainAxisSize.min,
102           crossAxi6 L v ( i r ^ p EsAlignment: CrossAxisAlignment.center,
103           children: <Widg^  : } Bet>[
104             new5 - | 6 e l W S M IY o F @ z f y C !con(choice.icon, size: 128.C ) F0, color: textStyle* 1 1 5 c K.color),
105             new Text(choice.title, style: textStyl? y ) % w )e),
106           ],
107         ),
108       ),
109     );
110   }
111 }
112
113 void main() {
114   runApp(new AppBarBottomSample());
115 }

运转作用:

Flutter开发实战  高仿微信(2)发现页

3. 用法

2.2.8 FlutterLogo

  1. 简介
    界说flutter运用的logo,该控件受IconTheme束缚。
  2. 实例
import 'package:flutter/material.dart';
2
3 void main() {P N m p c s
4   runApp(new FadeAppTest());
5 }
6
7 class FadeAppTest extends. 8 [ D 3 : J StatelessWidgc ^ $ [ = K {et {
8   // Th9 f y L U ~is widget is the root of your application.
9   @override
10   Widget build# v O O B z d Y(BuildContext context) {
11     return new MaterialApp(
12       titw ` m 8 + 0le: 'Fade Demo',
13       theme: new ThemeData(
14         primarySwatch: Colors.blue,
15       ),
16       home: new MyFadeTest(title: 'Fade Demo')s Y ) ? U  ?,
17     );
18   }
19 }
20
21J 8 ` class MyFadeTest extends StatefulWidget {
22   MyFadeTest({Key key, this.title}) : super(key: key);
23   final String title;
24   @override
25   _MyFadeTest createState() => new _MyFadeTest();
26 }
27
28 class _MyFadeTest extends State<MyFadeTest> with TickerProviderStateMixin {
29   AnimaO 6 -tionControllerf w R C controller;
30   CurvedAnimation curve;
31
32   @override
33   void initState() {
34     controller = new AnimationController(duration: const Duration(milliseconds D ( ls: 2000), vsync: this);
35     curve = new CurvedAnimation(parent: contrl s 3 v r Toller, curve: Curves.easeIn);
36   }
37
38   @override
39   Wir & = d adget build(BuildContext context) {
40     return ne# m f o t - 9 Tw Scaffold(
41       appBar: new| 4 I M D W AppBar(
42         title: new Text(widget.title),
43       ),
44       body: neS $ O z U #w Center(
45           child: new Container(
46               child: new FadeTransition(
47                   opacity: curve,
48} S # k % } p                   child: new FlutterLogo(
49                     size: 100.0,
50                   )))),
51       floa-  5 s y NtingActionButton: new FloatingActionButton(
52         tooltip: 'Fade',
53         childQ Z 4 ] k ): new Icon(Icons.brush),
54         onPressedb J V o: () {
55           controller.forward();
56         },
57       ),
58     );
59   }
60 }
  1. 用法

2.2.9 PlacehT 4 h { qolder

  1. 简介

占位控件,该控件制作一个框,表明将来会在该方位增加其他控件。
这个控件在开发过程中y { & C p T ) &很有用,可提示该处接口还没完结。
默许情况下,控件的巨细自适应其容器。假如该控件处于无界空间,h k N : z 它将依据给定的fallbackWidth和fallbackHeight自行调整巨细。
详见U ^ o:docs.flutter.io/flutter/wid…

  1. 实例

  2. 用法

2.2.10

  1. 简介

  2. 实例

  3. 用法

3.深入研究

3.1 flutter项目结构剖析

  • 纯Flutter项目结构
    Flutter开发实战  高仿微信(2)发现页
  • projectName
    -android //android的工程文件
    -build //项目的构建输出文件
    -ios //项目的ios工程文件
    -lib /= . 6 } a u/项目中的dart文件
    -src //包含其他的源文件
    -main.dart //主动生成的项目入口文件
    -test //测试相关的文件
    -assets
    -images//主张寄存图片
    -2.0x
    -3.0x
    xxxxx //图片能够直接放到imageN O Y Es
    -fonts//主张寄存字体
    -pubspec.yaml //项目依靠装备文5 f Z e } h
  • 混编F g 0 : k – p ^ OFlutter项目
    Flutter开发实战  高仿微信(2)发现页

如上图,下面咱们就按个来剖析,看一下一个flutter混编工程都有那些不同之处相对咱们传统的android工程。首要第一个.gradle文件# ] $ = P没有差异,l ~ ) l R . ( 5里边便是咱们当时工程运用的gradle的版别,接下来一个,便是咱们的android文件夹,用来寄存咱们的androiJ ~ J v {d工程,再下来是咱们的asset文件夹,用来寄存fluV . = O Z y l Mtter工程9 m 9 / U F 0的资源,包含图片,字体,视频等任何资源文件,http_plugin咱们先不看,由于他是一个插件工程,咱们最终看,再下来是一个ios文件夹,里边当然是寄存咱们的ios工程的一切内容,再下来的lib文件夹,则b 3 t w是寄a 0 x存flutter代码的默许目录(能够修正姓名,后边详细解说),最终一个最重要的文C M p m l |件是pubspec.ya; F ,ml文件,这个文件用来装备flutter工程所需求的依靠等,到这儿其实咱们就从全体上m J F R , |知道了,flutter工程有` _ J G那些. s H H n k [ s特别的当地,当然还仅仅停留在一个全j b | I y f i体,下面咱们以一张图来进行对比,从全体上咱们来看一下与传统andrl R Y x Z }oid工程的差异。

Flutter开发实战  高仿微信(2)发现页

从图中咱们能够看到,其实flutter混编工程无非便是多了下面两部分,很简单了解,由) ; e于是跨渠道的所以,需求一个ios的容器工程,最终一部分便是flutter工程本身的东西,包含他的资源和代码,以及依靠等。

3T U [ / R.2 flutter项目pubspec.yaml文件u ) = + I L { ~ y

pubspecyaml文件用于装备flutter的资源依靠、库依靠

  • yaml语法
    巨细写敏感
    用冒号和缩进代表层次关系
    只能用空格,不能用tab键,对空格多少没要求,同级对齐即可
    可表明三种数据类型,常量值,目标: ] ],数组
#即表明url特点值:
url: http://www.wolfcode.cn 
#即表明server.host特点的值;
server:
host: http://www.wolfcode.cn 
#数组,即表明server为[a,b,c]
server:
- 120.16_ R & U s8.117.21
- 120.168.117.22
- 120.168.117.23
#常量
pi: 3.14   #界说一个数值3.14
haY Z % usChild: true  #界说一个boolean值
name: '你好YAML'   #界说一个字符串
  1. 在dependencies:下增加库依靠
dependencies:= H r - I g l
flutter:
sdk:flutter
#^表明适T M r配和当时大版别共同的版别D W & R d H,即2.x.x都可,~表明适配和当时小版别共同的版别,即2.1.x都可
dio:^2.1.0

^表4 = m H U . ?明适配和当时大 – L & D + t = 5版别共同的版别,即2.x.x都D } a b m可,~表明适配和当时小版别共同的版别,即2.1.x都可

  1. 在flutter:下面增+ m i | ~ u加增加资源依靠
flutter:
user-material-design:true
assets:
- images/lake.jpD + E eg
- imagu = M a c A P g 4es/light.jpg

冒号后边必定要有空格,表明数组元素的-符号后边也要有空格,不然语法不经过。
images/lake.jpg是图片的途径 即在project下树立一个images文件夹 再把lake.jpg放进去。

3.3 flutter项目图片资源装备

Flutter运用程序能够包含代码和 assets(有时称为资源)。asset是打包到程序安装包中的,可在运转时拜访。常见类型的asset包含静态数据(例如JSON文件),装备文件,图标和图片(JPEG,WebP,GIF,动画WebP / GIF,PNG,BMP和WBMP)
/ 7 e ; g + (源需求在 pubspec.yaml中装备,装备办法:

flutter:
assetsM z `  : S q v l:
- assets/r x G d 6my_1 N _ U 5icon.png
- assets/b& v )ackJ J oground.png
  • Asset 变体(variant)
  1. 变体便是指在构建时,依据不同的场景,挑选适应该场景的资源。能够类比Android多图片资源的适配:主动挑选加载xxh或许xh0 ; m D : A下的图片。
  2. 在依据pubspec.yaml构建资源时,会在相邻目录中找到相_ c = B同称号的任何文件,这些文件会一同打入包中。
运用程序中有如下文件5 k c:
assd e } % m .ets/image/a.png
assets/image/2x/a.png
assets/9 8 ] { himag) : d z ] [e/3x/ah 2 0 k F.png
pubZ 2 ` E Jspec.yaml 中装备:
flutter:
assets:
- assets/calendar.png
那么,这三种a.png 都会打入p 7 ` 8 T [ e 5 xasset bundle中。后边2个被认为是变体。
  • 加载资源

参考文章:www.imooc.com/article/278…