1. 程式人生 > IOS開發 >Flutter開發實戰 高仿微信(2)發現頁

Flutter開發實戰 高仿微信(2)發現頁

  • 初級基礎系列

Flutter開發實戰初級(1)ListView詳解

Flutter開發實戰初級(2)佈局詳解

  • 專案實戰系列

Flutter開發實戰 高仿微信(1)首頁

Flutter開發實戰 高仿微信(2)發現頁

Flutter開發實戰 高仿微信(2)發現頁

1.專案程式碼

1.1 微信發現頁面簡述

  1. 在上一篇《flutter開發微信之一》中講解了專案框架的簡單搭建,整個APP分為四個tabbar:微信,通訊錄,發現,我。其中發現是最簡單一個頁面,先從最容易的頁面入手,實現發現頁面主頁搭建。

1.2 APP框架優化

1.2.1 配置APP Logo和啟動圖片

  1. IOS 啟動圖片配置
    在這裡插入圖片描述
  2. Android啟動圖片配置
    在這裡插入圖片描述

1.2.2 配置資源圖片

  1. flutter 專案資源在pubspec.yaml中配置

    在這裡插入圖片描述

  2. 在程式碼中使用圖片資源的方式:

  3. 不同解析度的圖片使用 跟Android的多圖片適配相同,將不同解析度下的圖片放到對應的目錄即可,如下:

    在這裡插入圖片描述
    使用程式碼:

new Image.asset("assets/images/a.png");
複製程式碼
  1. flutter 在專案中載入資源的兩種方式:
  • 通過rootBundle物件來載入(每個Flutter應用都有一個rootBundle物件,可以訪問主asset bundle) . 如果你所在的業務場景下,拿不到context(不在widget中),那就使用這個吧,否則使用下面的方式。
import 'package:flutter/services.dart';
Widget _createBody() {
    return new FutureBuilder(
    future: rootBundle.loadString('assets/a.json'),builder: (context,snapshot){
        if(snapshot.hasData) {
        return new Text(snapshot.data.toString());
        }
    },);
複製程式碼
  • 通過DefaultAssetBundle 來獲取當前BuildContext 的 AssetBundle,推薦使用。比方法一要靈活。可以自己制定。
import 'package:flutter/services.dart';
Widget _createBody() {
    return new FutureBuilder(
    future: DefaultAssetBundle.of(context).loadString('assets/a.json'),);
複製程式碼

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 = "/Profile 2";

  //strings
  static const String appName = "Flutter UIKit";

  //fonts  字型相關
  static const String quickFont = "Quicksand";
  static const String ralewayFont = "Raleway";
  static const String quickBoldFont = "Quicksand_Bold.otf";
  static const String quickNormalFont = "Quicksand_Book.otf";
  static const String quickLightFont = "Quicksand_Light.otf";

  //images
  static const String imageDir = "assets/images";
  static const String pkImage = "$imageDir/pk.jpg";

  //login  比如登入頁面用到的文字
  static const String enter_code_label = "Phone Number";
  static const String enter_code_hint = "10 Digit Phone Number";

  //gneric 通用的文字
  static const String error = "Error";
  static const String success = "Success";

  static const MaterialColor ui_kit_color = Colors.grey;

//colors
  static List<Color> kitGradients = [
    // new Color.fromRGBO(103,218,255,1.0),
    // new Color.fromRGBO(3,169,244,
    // new Color.fromRGBO(0,122,193,
    Colors.blueGrey.shade800,Colors.black87,];
  static List<Color> kitGradients2 = [
    Colors.cyan.shade600,Colors.blue.shade900
  ];

  //randomcolor
  static final Random _random = new Random();

  /// Returns a random color.
  static Color next() {
    return new Color(0xFF000000 + _random.nextInt(0x00FFFFFF));
  }
}
複製程式碼

1.2.3.2 國際化

詳情參考:國際化官方教程

在這裡插入圖片描述

1.2.4 新增依賴

在pubspec.yaml 中新增依賴 注意,只有在新增平臺所需相關依賴時,才需要去Android 工程中的gradle中新增依賴。

1.2.5 新建四個主頁對應四個tabbar

1.3 發現頁面佈局

2.知識點

2.1 flutter佈局

2.1.1 Row 水平佈局

  1. 簡介

flex水平佈局控制元件,能夠將子控制元件水平排列,是基於Web的flexbox的佈局模式設計的。 Row子控制元件有靈活與不靈活的兩種,Row首先列出不靈活的子控制元件,減去它們的總寬度,計算還有多少可用的空間。然後Row按照Flexible.flex屬性確定的比例在可用空間中列出靈活的子控制元件。要控制靈活子控制元件,需要使用Expanded控制元件。 注意該控制元件不支援滑動,如果子控制元件超過剩餘空間,會報錯,如果想支援水平滑動,考慮使用ListView。 如果只有一個子控制元件,可以使用 Align or Center控制元件定義該子控制元件位置。

  1. 例項
 1 new Row(
 2   children: <Widget>[
 3     new Expanded(
 4       child: new Text('Deliver features faster',textAlign: TextAlign.center),5     ),6     new Expanded(
 7       child: new Text('Craft beautiful UIs',8     ),9     new Expanded(
10       child: new FittedBox(
11         fit: BoxFit.contain,// otherwise the logo will be tiny
12         child: const FlutterLogo(),13       ),14     ),15   ],16 )
複製程式碼
  1. 用法

2.1.2 Column 垂直佈局

  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('Through the night,we have one shot to live another day'),7     new Text('We cannot let a stray gunshot give us away'),8     new Text('We will fight up close,seize the moment and stay in it'),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)),12   ],13 )
複製程式碼
  1. 用法

2.1.3 Stack 層佈局

  1. 簡介

  2. 例項

  3. 用法

2.1.4 主軸

  1. 簡介

  2. 例項

  3. 用法

2.1.5

  1. 簡介

  2. 例項

  3. 用法

2.2 flutter基本元件

Flutter控制元件本身通常由許多小型、單用途的控制元件組成,結合起來產生強大的效果,例如,Container是一種常用的控制元件,由負責佈局、繪畫、定位和大小調整的幾個控制元件組成,具體來說,Container是由LimitedBox、ConstrainedBox、 Align、Padding、DecoratedBox和Transform控制元件組成,而不是將Container子類化來產生自定義效果,您可以用這種新穎的方式組合這些以及其他簡單的控制元件。

類的層次結構是扁平的,以最大化可能的組合數量。

在這裡插入圖片描述

在寫應用程式時,經常會使用StatelessWidget和StatefulWidget編寫新控制元件,兩者的差別在於你是否要管理控制元件的狀態。一個控制元件的主要任務是實現build函式,定義控制元件中其他較低層次的控制元件。build函式將依次構建這些控制元件,直到底層渲染物件。

  • Flutter控制元件和Android,IOS原生控制元件比較
Flutter控制元件 Android控制元件 IOS控制元件
AppBar ActionBar/ToolBar UINavgationBar
ListView ListView/RecyclerView UITableView
ListView ListView/RecyclerView UITableView
Text TextView UILabel
Center ViewGroup ---
Container RelativeLayout --
FloatingActionButton FloatingActionButton(design庫裡面的) ---
BottomNavigationBar BottomNavigation(design庫裡面的) ---
RaisedButton/Button Button --
Column LinearLayout的android:orientation="vertical" --
Row android:orientation="horizontal" --
DecorationImage ImageView --
Image ImageView UIImageView
Stack FrameLayout/RelativeLayout --
Algin alginParentXXX屬性 --
resizeToAvoidBottomPadding android:windowSoftInputMode=” adjustResize屬性
SingleChildScrollView ScrollView UIScrollView
CustomScrollerView Recyclerview --

2.2.1 Container

  1. 簡介

容器,一個常用的控制元件,由基本的繪製、位置和大小控制元件組成。負責建立矩形的可視元素,可以用BoxDecoration來設計樣式,比如背景、邊框和陰影,Container也有邊距、填充和大小限制,另外,還可以在三維空間利用矩陣進行變換。 沒有子控制元件的容器儘可能大,除非傳入的大小約束是無限的,在這種情況下,它們儘可能小。有子控制元件的容器將自己的尺寸給他們的孩子。我們可以通過width、height和 constraints屬性控制size。

  1. 例項
new Container(
   constraints: new BoxConstraints.expand(
    height: Theme.of(context).textTheme.display1.fontSize * 1.1 + 200.0,),padding: const EdgeInsets.all(8.0),color: Colors.teal.shade700,alignment: Alignment.center,child: new Text('Hello World',style: Theme.of(context).textTheme.display1.copyWith(color: Colors.white)),foregroundDecoration: new BoxDecoration(
     image: new DecorationImage(
       image: new NetworkImage('https://www.example.com/images/frame.png'),
       centerSlice: new Rect.fromLTRB(270.0,180.0,1360.0,730.0),transform: new Matrix4.rotationZ(0.1),)
複製程式碼
  1. 用法

2.2.2 Image

  1. 簡介

顯示影象的控制元件,Image控制元件有多種建構函式: new Image,用於從ImageProvider獲取影象。 new Image.asset,用於使用key從AssetBundle獲取影象。 new Image.network,用於從URL地址獲取影象。 new Image.file,用於從File獲取影象。

為了自動執行畫素密度感知資源解析度,使用AssetImage指定影象,需要確保在控制元件樹中的圖片控制元件上方存在MaterialApp、WidgetsApp和MediaQuery控制元件。

不同的手機有不同的畫素比率,這時就需要根據手機的畫素比率來載入不同圖片,做法很簡單,只需要在圖片同級目錄下建立2.0x/…和3.0x/…的目錄就可以了。

我們在pubspec.yaml這個檔案裡指定本地圖片路徑

# To add assets to your application,add an assets section,like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
複製程式碼
  1. 例項

  2. 用法

2.2.3 Text

  1. 簡介

  2. 例項 下面的例項有7個不同樣式的文字控制元件:

1 import 'package:flutter/material.dart';
 2 class TextDemo extends StatelessWidget {
 3   @override
 4   Widget build(BuildContext 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號',13             style: new TextStyle(
14               color: const Color(0xffff0000),15               decoration: TextDecoration.lineThrough,16               decorationColor: const Color(0xff000000),17               fontSize: 25.0,18             ),19           ),20           new Text(
21             '橙色+下劃線+24號',22             style: new TextStyle(
23               color: const Color(0xffff9900),24               decoration: TextDecoration.underline,25               fontSize: 24.0,26             ),27           ),28           new Text(
29             '虛線上劃線+23號+傾斜',30             style: new TextStyle(
31               decoration: TextDecoration.overline,32               decorationStyle: TextDecorationStyle.dashed,33               fontSize: 23.0,34               fontStyle: FontStyle.italic,35             ),36           ),37           new Text(
38             'serif字型+24號',39             style: new TextStyle(
40               fontFamily: 'serif',41               fontSize: 26.0,42             ),43           ),44           new Text(
45             'monospace字型+24號+加粗',46             style: new TextStyle(
47               fontFamily: 'monospace',48               fontSize: 24.0,49               fontWeight: FontWeight.bold,50             ),51           ),52           new Text(
53             '天藍色+25號+2行跨度',54             style: new TextStyle(
55               color: const Color(0xff4a86e8),56               fontSize: 25.0,57               height: 2.0,58             ),59           ),60           new Text(
61             '24號+2個字母間隔',62             style: new TextStyle(
63               fontSize: 24.0,64               letterSpacing: 2.0,65             ),66           ),67         ]
68       ),69     );
70   }
71 }
72 void main() {
73   runApp(
74     new MaterialApp(
75       title: 'Flutter教程',76       home: new TextDemo(),77     ),78   );
79 }
複製程式碼

執行效果:

在這裡插入圖片描述
3. 用法

2.2.4 Icon

  1. 簡介

圖示控制元件,按照IconData中所描述的規則繪製,如Material中預定義的IconDatas。 該控制元件不可互動,要實現可互動的圖示,可以考慮使用Material中的 IconButton。 該控制元件必須在 Directionality控制元件裡使用,通常這是由WidgetsApp或 MaterialApp自動引入的。詳見:docs.flutter.io/flutter/wid…

  1. 例項

  2. 用法

2.2.5 RaisedButton

  1. 簡介

Material Design 風格的浮動按鈕,以方形紙片樣式懸停在介面上,點選後會產生墨水擴散效果。 避免在dialog和card控制元件裡使用,一般彈出式的控制元件建議使用扁平化按鈕,減少佈局層次疊加。詳見:docs.flutter.io/flutter/mat…

  1. 例項

  2. 用法 使用時,要實現onPressed回撥方法,否則按鈕處於禁用狀態,預設顯示disabledColor樣式的扁平化按鈕,並且此時更改按鈕的顏色不會生效。 注意該控制元件的父控制元件必須是Material控制元件。 如果你只需要點選後產生墨水擴散效果,但不想使用按鈕,請考慮直接使用InkWell控制元件。 如有必要,該按鈕將拉伸以適應子控制元件大小。

2.2.6 Scaffold

  1. 簡介

Scaffold 實現了基本的Material Design佈局結構。也就是說, MaterialApp 的 child 是 Scaffold Widget。 在Material設計中定義的單個介面上的各種佈局元素,在 Scaffold 中都有支援,比如 左邊欄(Drawers)、snack bars、以及 bottom sheets。

Scaffold 有下面幾個主要屬性:

  • appBar:顯示在介面頂部的一個 AppBar,也就是 Android 中的 ActionBar 、Toolbar

  • body:當前介面所顯示的主要內容 Widget

  • floatingActionButton:Material設計中所定義的 FAB,介面的主要功能按鈕

  • persistentFooterButtons:固定在下方顯示的按鈕,比如對話方塊下方的確定、取消按鈕

  • drawer:側邊欄控制元件

  • backgroundColor: 內容的背景顏色,預設使用的是 ThemeData.scaffoldBackgroundColor 的值

  • bottomNavigationBar: 顯示在頁面底部的導航欄

  • resizeToAvoidBottomPadding:類似於 Android 中的 android:windowSoftInputMode=”adjustResize”,控制介面內容 body 是否重新佈局來避免底部被覆蓋了,比如當鍵盤顯示的時候,重新佈局避免被鍵盤蓋住內容。預設值為 true。

顯示 snackbar 或者 bottom sheet 的時候,需要使用當前的 BuildContext 引數呼叫 Scaffold.of 函式來獲取 ScaffoldState 物件,然後使用 ScaffoldState.showSnackBar 和 ScaffoldState.showBottomSheet 函式來顯示。

要特別注意 Scaffold.of 的引數 BuildContext, 如果包含該 BuildContext 的 Widget 是 Scaffold 的父 Widget,則 Scaffold.of 是無法查詢到對應的 ScaffoldState 物件的,Scaffold.of 返回的是父物件中最近的 Scaffold 中的 ScaffoldState 物件。 比如,如果在 Scaffold 的 build 函式中,使用 build 的 BuildContext 引數是可以的:

 1 @override
 2 Widget build(BuildContext context) {
 3   return new RaisedButton(
 4     child: new Text('SHOW A SNACKBAR'),5     onPressed: () {
 6       Scaffold.of(context).showSnackBar(new SnackBar(
 7         content: new Text('Hello!'),8       ));
 9     },10   );
11 }
複製程式碼
  1. 例項 如果 build 函式返回一個 Scaffold 物件,則由於 Scaffold 物件是這個 Widget 的子物件,所以使用這個 build 的 BuildContext 引數是不能查詢到 ScaffoldState 物件的,這個時候,通過在 Scaffold 中使用一個 Builder 來提供一個新的 BuildConext :
@override
 2 Widget build(BuildContext context) {
 3   return new Scaffold(
 4     appBar: new AppBar(
 5       title: new Text('Demo')
 6     ),7     body: new Builder(
 8       // Create an inner BuildContext so that the onPressed methods
 9       // can refer to the Scaffold with Scaffold.of().
10       builder: (BuildContext context) {
11         return new Center(
12           child: new RaisedButton(
13             child: new Text('SHOW A SNACKBAR'),14             onPressed: () {
15               Scaffold.of(context).showSnackBar(new SnackBar(
16                 content: new Text('Hello!'),17               ));
18             },20         );
21       },22     ),23   );
24 }
複製程式碼

另外還可以把 build 函式中的 Widget 分別建立,分別引入新的 BuildContext 來獲取 Scaffold。

  1. 用法

2.2.7 Appbar

  1. 簡介

AppBar 和 SliverAppBar 是Material Design中的 App Bar,也就是 Android 中的 Toolbar,關於 Toolbar 的設計指南請參考Material Design中 Toolbar 的內容。 AppBar 和 SliverAppBar 都是繼承StatefulWidget 類,都代表 Toobar,二者的區別在於 AppBar 位置的固定的應用最上面的;而 SliverAppBar 是可以跟隨內容滾動的。

他們的主要屬性如下:

  • leading:在標題前面顯示的一個控制元件,在首頁通常顯示應用的 logo;在其他介面通常顯示為返回按鈕

  • title: Toolbar 中主要內容,通常顯示為當前介面的標題文字

  • actions:一個 Widget 列表,代表 Toolbar 中所顯示的選單,對於常用的選單,通常使用 IconButton 來表示;對於不常用的選單通常使用 PopupMenuButton 來顯示為三個點,點選後彈出二級選單

  • bottom:一個 AppBarBottomWidget 物件,通常是 TabBar。用來在 Toolbar 標題下面顯示一個 Tab 導航欄

  • elevation:紙墨設計中控制元件的 z 座標順序,預設值為 4,對於可滾動的 SliverAppBar,當 SliverAppBar 和內容同級的時候,該值為 0, 當內容滾動 SliverAppBar 變為 Toolbar 的時候,修改 elevation 的值

  • flexibleSpace:一個顯示在 AppBar 下方的控制元件,高度和 AppBar 高度一樣,可以實現一些特殊的效果,該屬性通常在 SliverAppBar 中使用

  • backgroundColor:APP bar 的顏色,預設值為 ThemeData.primaryColor。改值通常和下面的三個屬性一起使用

  • brightness:App bar 的亮度,有白色和黑色兩種主題,預設值為 ThemeData.primaryColorBrightness

  • iconTheme:App bar 上圖示的顏色、透明度、和尺寸資訊。預設值為 ThemeData.primaryIconTheme

  • textTheme: App bar 上的文字樣式。預設值為 ThemeData.primaryTextTheme

  • centerTitle: 標題是否居中顯示,預設值根據不同的作業系統,顯示方式不一樣

  1. 例項
import 'package:flutter/material.dart';
  2 
  3 class AppBarBottomSample extends StatefulWidget {
  4   @override
  5   _AppBarBottomSampleState createState() => new _AppBarBottomSampleState();
  6 }
  7 
  8 class _AppBarBottomSampleState extends State<AppBarBottomSample> with SingleTickerProviderStateMixin {
  9   TabController _tabController;
 10 
 11   @override
 12   void initState() {
 13     super.initState();
 14     _tabController = new TabController(vsync: this,length: choices.length);
 15   }
 16 
 17   @override
 18   void dispose() {
 19     _tabController.dispose();
 20     super.dispose();
 21   }
 22 
 23   void _nextPage(int delta) {
 24     final int newIndex = _tabController.index + delta;
 25     if (newIndex < 0 || newIndex >= _tabController.length)
 26       return;
 27     _tabController.animateTo(newIndex);
 28   }
 29 
 30   @override
 31   Widget build(BuildContext context) {
 32     return new MaterialApp(
 33       home: new Scaffold(
 34         appBar: new AppBar(
 35           title: const Text('AppBar Bottom Widget'),36           leading: new IconButton(
 37             tooltip: 'Previous choice',38             icon: const Icon(Icons.arrow_back),39             onPressed: () { _nextPage(-1); },40           ),41           actions: <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.fromHeight(48.0),50             child: new Theme(
 51               data: Theme.of(context).copyWith(accentColor: Colors.white),52               child: new Container(
 53                 height: 48.0,54                 alignment: Alignment.center,55                 child: new TabPageSelector(controller: _tabController),56               ),57             ),58           ),59         ),60         body: new TabBarView(
 61           controller: _tabController,62           children: choices.map((Choice choice) {
 63             return new Padding(
 64               padding: const EdgeInsets.all(16.0),65               child: new ChoiceCard(choice: choice),66             );
 67           }).toList(),68         ),69       ),70     );
 71   }
 72 }
 73 
 74 class Choice {
 75   const Choice({ this.title,this.icon });
 76   final String title;
 77   final IconData icon;
 78 }
 79 
 80 const List<Choice> choices = const <Choice>[
 81   const Choice(title: 'CAR',icon: Icons.directions_car),82   const Choice(title: 'BICYCLE',icon: Icons.directions_bike),83   const Choice(title: 'BOAT',icon: Icons.directions_boat),84   const Choice(title: 'BUS',icon: Icons.directions_bus),85   const Choice(title: 'TRAIN',icon: Icons.directions_railway),86   const Choice(title: 'WALK',icon: Icons.directions_walk),87 ];
 88 
 89 class ChoiceCard extends StatelessWidget {
 90   const ChoiceCard({ Key key,this.choice }) : super(key: key);
 91 
 92   final Choice choice;
 93 
 94   @override
 95   Widget build(BuildContext context) {
 96     final TextStyle textStyle = Theme.of(context).textTheme.display1;
 97     return new Card(
 98       color: Colors.white,99       child: new Center(
100         child: new Column(
101           mainAxisSize: MainAxisSize.min,102           crossAxisAlignment: CrossAxisAlignment.center,103           children: <Widget>[
104             new Icon(choice.icon,size: 128.0,color: textStyle.color),105             new Text(choice.title,style: textStyle),106           ],107         ),108       ),109     );
110   }
111 }
112 
113 void main() {
114   runApp(new AppBarBottomSample());
115 }
複製程式碼

執行效果:

在這裡插入圖片描述
3. 用法

2.2.8 FlutterLogo

  1. 簡介 定義flutter應用的logo,該控制元件受IconTheme約束。
  2. 例項
import 'package:flutter/material.dart';
 2 
 3 void main() {
 4   runApp(new FadeAppTest());
 5 }
 6 
 7 class FadeAppTest extends StatelessWidget {
 8   // This widget is the root of your application.
 9   @override
10   Widget build(BuildContext context) {
11     return new MaterialApp(
12       title: 'Fade Demo',13       theme: new ThemeData(
14         primarySwatch: Colors.blue,15       ),16       home: new MyFadeTest(title: 'Fade Demo'),17     );
18   }
19 }
20 
21 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   AnimationController controller;
30   CurvedAnimation curve;
31 
32   @override
33   void initState() {
34     controller = new AnimationController(duration: const Duration(milliseconds: 2000),vsync: this);
35     curve = new CurvedAnimation(parent: controller,curve: Curves.easeIn);
36   }
37 
38   @override
39   Widget build(BuildContext context) {
40     return new Scaffold(
41       appBar: new AppBar(
42         title: new Text(widget.title),43       ),44       body: new Center(
45           child: new Container(
46               child: new FadeTransition(
47                   opacity: curve,48                   child: new FlutterLogo(
49                     size: 100.0,50                   )))),51       floatingActionButton: new FloatingActionButton(
52         tooltip: 'Fade',53         child: new Icon(Icons.brush),54         onPressed: () {
55           controller.forward();
56         },57       ),58     );
59   }
60 }
複製程式碼
  1. 用法

2.2.9 Placeholder

  1. 簡介

佔位控制元件,該控制元件繪製一個框,表示將來會在該位置新增其他控制元件。 這個控制元件在開發過程中很有用,可提示該處介面還沒完成。 預設情況下,控制元件的大小自適應其容器。如果該控制元件處於無界空間,它將根據給定的fallbackWidth和fallbackHeight自行調整大小。 詳見:docs.flutter.io/flutter/wid…

  1. 例項

  2. 用法

2.2.10

  1. 簡介

  2. 例項

  3. 用法

3.深入研究

3.1 flutter專案結構分析

  • 純Flutter專案結構
    在這裡插入圖片描述
  • projectName -android //android的工程檔案 -build //專案的構建輸出檔案 -ios //專案的ios工程檔案 -lib //專案中的dart檔案 -src //包含其他的原始檔 -main.dart //自動生成的專案入口檔案 -test //測試相關的檔案 -assets -images//建議存放圖片 -2.0x -3.0x xxxxx //圖片可以直接放到images -fonts//建議存放字型 -pubspec.yaml //專案依賴配置檔案
  • 混編Flutter專案
    在這裡插入圖片描述

如上圖,下面我們就按個來分析,看一下一個flutter混編工程都有那些不同之處相對我們傳統的android工程。首先第一個.gradle檔案沒有區別,裡面就是我們當前工程使用的gradle的版本,接下來一個,就是我們的android資料夾,用來存放我們的android工程,再下來是我們的asset資料夾,用來存放flutter工程的資源,包括圖片,字型,視訊等任何資原始檔,http_plugin大家先不看,因為他是一個外掛工程,我們最後看,再下來是一個ios資料夾,裡面當然是存放我們的ios工程的所有內容,再下來的lib資料夾,則是存放flutter程式碼的預設目錄(可以修改名字,後面詳細講解),最後一個最重要的檔案是pubspec.yaml檔案,這個檔案用來配置flutter工程所需要的依賴等,到這裡其實我們就從整體上知道了,flutter工程有那些特別的地方,當然還只是停留在一個整體,下面我們以一張圖來進行對比,從整體上我們來看一下與傳統android工程的區別。

在這裡插入圖片描述
從圖中我們可以看到,其實flutter混編工程無非就是多了下面兩部分,很容易理解,因為是跨平臺的所以,需要一個ios的容器工程,最後一部分就是flutter工程本身的東西,包括他的資源和程式碼,以及依賴等。

3.2 flutter專案pubspec.yaml檔案

pubspecyaml檔案用於配置flutter的資源依賴、庫依賴

  • yaml語法 大小寫敏感 用冒號和縮排代表層次關係 只能用空格,不能用tab鍵,對空格多少沒要求,同級對齊即可 可表示三種資料型別,常量值,物件,陣列
#即表示url屬性值:
url: http://www.wolfcode.cn 
#即表示server.host屬性的值;
server:
    host: http://www.wolfcode.cn 
#陣列,即表示server為[a,b,c]
server:
    - 120.168.117.21
    - 120.168.117.22
	 - 120.168.117.23
#常量
pi: 3.14   #定義一個數值3.14
hasChild: true  #定義一個boolean值
name: '你好YAML'   #定義一個字串

複製程式碼
  1. 在dependencies:下新增庫依賴
dependencies:
  flutter:
    sdk:flutter
#^表示適配和當前大版本一致的版本,即2.x.x都可,~表示適配和當前小版本一致的版本,即2.1.x都可
  dio:^2.1.0
複製程式碼

^表示適配和當前大版本一致的版本,即2.x.x都可,~表示適配和當前小版本一致的版本,即2.1.x都可

  1. 在flutter:下面新增新增資源依賴
flutter:
  user-material-design:true
  assets:
    - images/lake.jpg
    - images/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) 資源需要在 pubspec.yaml中配置,配置方法:

flutter:
  assets:
    - assets/my_icon.png
    - assets/background.png
複製程式碼
  • Asset 變體(variant)
  1. 變體就是指在構建時,根據不同的場景,選擇適應該場景的資源。可以類比Android多圖片資源的適配:自動選擇載入xxh或者xh下的圖片。
  2. 在根據pubspec.yaml構建資源時,會在相鄰目錄中找到相同名稱的任何檔案,這些檔案會一起打入包中。
應用程式中有如下檔案:
assets/image/a.png
assets/image/2x/a.png
assets/image/3x/a.png

pubspec.yaml 中配置:
flutter:
assets:
- assets/calendar.png

那麼,這三種a.png 都會打入asset bundle中。後面2個被認為是變體。
複製程式碼
  • 載入資源

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