發表日期:2018-12 文章編輯:小燈 瀏覽次數:3246
還未安裝環境的童鞋可以看下這個flutter環境安裝
不錯的學習網站:
1.flutter官方中文網站:https://flutterchina.club/docs/
2.Flutter七日游(張風捷特烈):https://juejin.im/user/5b42c0656fb9a04fe727eb37
3.咸魚官方博客:https://zhuanlan.zhihu.com/xytech
ps:前2個都比較基礎,最后一個比較深入
計劃將基礎控件,布局控件結束后,再進行自定義繪制控件
widget: 小器具,裝飾品,窗口小部件;這里統一稱為控件
要學flutter,肯定要先學會怎么使用控件
統計了一部分控件,做了一個表格:
| widget | flutter | android |
|---|---|---|
| 文本 | Text | TextView |
| 按鈕 | ||
| 漂浮按鈕 | RaisedButton | Button |
| 扁平按鈕 | FlatButton | |
| 邊框按鈕 | OutlineButton | |
| 圖片按鈕 | IconButton | ImageButton |
| 浮動動作按鈕 | FloatingActionButton | FloatingActionButton |
| 編輯框 | TextField | EditText |
| 圖片 | Image | ImageView |
| 圖標 | Icon | |
| 復選框 | Checkbox | CheckBox |
| 單選框 | Radio | RadioButton |
| 單選開關 | Switch | Switch |
| 底部彈框 | SnackBar | SnackBar |
| 滾動控件 | SingleChildScrollView | ScrollView |
| 線性滾動列表 | ListView | RecyclerView(LinearLayoutManager) |
| 網格滾動列表 | GridView | RecyclerView(GridLayoutManager) |
| 自定義滾動 | CustomScrollView | RecyclerView(StaggeredGridLayoutManager) |
| 滾動條 | ScrollBar | |
| 彈框 | Dialog | AlertDialog |
| 進度條 | ProgressIndicator | ProgressBar |
| 圓形進度條 | CircularProgressIndicator | |
| 線性進度條 | LinearProgressIndicator | |
| 滑動條 | Slider | SeekBar |
| 導航欄 | AppBar | ToolBar |
| 選項欄 | TapBar+TapBarView | |
| 底部導航欄 | BottomNavigationBar | |
| 分割線 | Divider | |
| 側滑菜單 | Drawer | DrawerLayout |
| 底抽屜 | BottomSheet | BottomSheet |
| 流式標簽 | Chip | Chip |
| 圓形頭像 | CircleAvatar |
控件很多,怎么學習來快呢?(ps:自我感覺)
學習之前,我們需要明確2個感念:
androidstudio的三個快捷鍵| 快捷鍵 | 作用 |
|---|---|
| stless | 創建一個StatelessWidget |
| stful | 創建一個StatefullWidget |
| stanim | 創建一個StatefullWidget ,且包含動畫 |
準備工作完成
接下來我們以ScrollBar為例,來學習這個控件:
工程目錄我們創建一個新的flutter工程時,系統會創建一大堆文件,那么我們的dart代碼是在哪呢?
dart代碼就在同級目錄下的lib文件中
這里會發現同時存在android和ios 2個文件夾,對的,flutter編譯后的應用是同時支持雙端的(ps:或者說是三端,fuchsia已經在布局了)
enum TargetPlatform { /// Android: <https://www.android.com/> android,/// Fuchsia: <https://fuchsia.googlesource.com/> fuchsia,/// iOS: <http://www.apple.com/ios/> iOS, } 回歸正題,系統會創建一個main.dart文件
import 'package:flutter/material.dart'; //main 程序的主入口 void main() => runApp(MyApp()); //運行一個MaterialApp控件 class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( //應用的圖標名稱 title: 'Flutter Demo', //主題 theme: ThemeData( primarySwatch: Colors.blue, ), //主界面 home: MainPage() ); } } 這里代碼基本固定了,你肯定要使用MaterialApp控件的,否則不好看(我這里不說不符合規范)
class MainPage extends StatelessWidget { @override Widget build(BuildContext context) { //腳手架 return Scaffold( //相當于toolbar,導航欄 appBar: AppBar( title: Text("flutter"), ), //正文 body: ScrollBarDemo ); } } 我們要開始創建一個ScrollBar了,先看下其的源碼:
class Scrollbar extends StatefulWidget { /// typically a [Scrollable] widget. const Scrollbar({ Key key, @required this.child, }) : super(key: key);/// Typically a [ListView] or [CustomScrollView]. final Widget child;@override _ScrollbarState createState() => _ScrollbarState(); } 源碼說需要傳遞一個child,且必須為Scrollable,然后給了2個選擇[ListView] 或 [CustomScrollView]
構造函數中的{}表示可選命名參數,@required表示child這個參數必須傳遞
Scrollable我們可以大膽的猜測,能滾動的控件肯定都包涵這個控件,所以我們選類似android中的那個ScrollView的控件SingleChildScrollView
然后我們寫下代碼
class ScrollBarDemo extends StatelessWidget { @override Widget build(BuildContext context) { return Scrollbar( child: SingleChildScrollView( child:Container() ) ); } } 接下來看看SingleChildScrollView
class SingleChildScrollView extends StatelessWidget { const SingleChildScrollView({ Key key, this.scrollDirection = Axis.vertical, this.reverse = false, this.padding, bool primary, this.physics, this.controller, this.child, }) : ...,super(key: key);//省略了斷言 final Axis scrollDirection; //滾動方向,水平和垂直 final bool reverse; //是否反向,默認不啟用 final EdgeInsetsGeometry padding;//間距 final ScrollController controller;//滑動控制器 final bool primary;//默認true final ScrollPhysics physics;//超過物理邊界后的動畫效果 final Widget child; ... @override Widget build(BuildContext context) { ... //內部創建了一個Scrollable控件 final Scrollable scrollable = Scrollable( axisDirection: axisDirection, controller: scrollController, physics: physics, viewportBuilder: (BuildContext context, ViewportOffset offset) { return _SingleChildViewport( axisDirection: axisDirection, offset: offset, child: contents, ); }, ); return primary && scrollController != null ? PrimaryScrollController.none(child: scrollable) : scrollable; } } 源碼可以看出,所有參數都是可選的,也就是說child其實也可以不傳的,但這樣就整個界面就是空白的
class ScrollBarDemo extends StatelessWidget { final String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @override Widget build(BuildContext context) { return Scrollbar( child: SingleChildScrollView( child:Container( color: Colors.redAccent, width: 360, child: Column( //創建一個Text控件列表 children: str.split("").map((c) => Text(c, textScaleFactor: 2.0,)).toList(), ) ) ) ); } } 關于布局、監聽、路由、手勢等接下來在介紹
小小的總結一下
1.遇到一個widget,先看它的構造函數(可能有多個)
a. StatelessWidget,看其build方法做了什么
b. StatefulWidget,先找到createState(),然后在state類中看其build方法做了什么
2.配合源碼中的英文注釋加以理解
3.動手實踐一番,測試效果
最后說明一下,flutter生成的代碼都封裝在libflutter.so中,不再是以前的.class文件
github代碼:https://github.com/leaf-fade/flutterDemo
小尾巴:文章有錯誤的地方請不吝指出,會及時更改