天天看點

Flutter 27: 易忽略的【小而巧】的技術點彙總 (四)

      小菜繼續整理 Flutter 中日常用到的小知識點。

1. CachedNetworkImage 緩存圖檔

      對于加載網絡圖檔時,添加一個加載動畫或網絡圖檔異常時添加一個錯誤圖檔會給使用者一個良好的體驗,此時

CachedNetworkImage

可以幫我們解決這個問題。CachedNetworkImage 是一個三方 pub 庫,引入的基本方式省略;

      CachedNetworkImage 中有兩個屬性很重要:

  1. placeholder 用來在加載圖檔時的緩沖過程,可以是動态 loading 亦或者 Widget 等;
  2. errorWidget 用來網絡圖檔加載異常時展現,可自定義進行展示。

      Tips: 在使用加載 loading 或預設圖檔時,建議限制 loading 和預設圖檔的大小,這樣不會出現預設圖檔比加載網絡圖更大的效果。

Widget _cachedNetImgWid() {
  return Container(
      color: Colors.grey,
      child: Center(
          child: CachedNetworkImage(
        height: 300.0,
        placeholder: Container(
            width: 50.0, height: 50.0, child: CircularProgressIndicator()),
        errorWidget: Container(
            height: 300.0, child: Image.asset('images/icon_wrong.jpg')),
        imageUrl:
            'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1544938569112&di=feeab11968f3870520482630563c4f54&imgtype=0&src=http%3A%2F%2Fi1.hdslb.com%2Fbfs%2Farchive%2Fac5c906111130579c6909aae47f6656e20d0906b.jpg',
      )));
}           

2. TextInputAction 鍵盤底部按鈕

      小菜在使用 TextField 文本框時會對鍵盤進行操作,為了良好對使用者體驗。在鍵盤右下角會有不同的按鈕樣式。例如搜尋頁面在輸入完成搜尋資訊後展示搜尋的按鈕更便捷。此時需要考慮 TextInputAction 屬性,可自定義展示内容。Flutter 提供了13種狀态,但需注意的是有些是區分 Android 和 iOS 的,使用時需加注意。

Widget _textFiledWid() {
  return Padding(padding: EdgeInsets.all(10.0),child:ListView(children: <Widget>[
    Padding(padding: EdgeInsets.all(8.0),child:Text('鍵盤右下角按鈕-done')),
    TextField(textInputAction: TextInputAction.done),
    Padding(padding: EdgeInsets.all(8.0),child:Text('鍵盤右下角按鈕-go')),
    TextField(textInputAction: TextInputAction.go),
    Padding(padding: EdgeInsets.all(8.0),child:Text('鍵盤右下角按鈕-newline')),
    TextField(textInputAction: TextInputAction.newline),
    Padding(padding: EdgeInsets.all(8.0),child:Text('鍵盤右下角按鈕-next')),
    TextField(textInputAction: TextInputAction.next),
    Padding(padding: EdgeInsets.all(8.0),child:Text('鍵盤右下角按鈕-search')),
    TextField(textInputAction: TextInputAction.search),
    Padding(padding: EdgeInsets.all(8.0),child:Text('鍵盤右下角按鈕-send')),
    TextField(textInputAction: TextInputAction.send),
    Padding(padding: EdgeInsets.all(8.0),child:Text('鍵盤右下角按鈕-join')),
    TextField(textInputAction: TextInputAction.join),
  ]));
}           

3. DefaultTextStyle 預設文本樣式

      小菜在學習過程中發現一個很友善的

DefaultTextStyle

,用來處理目前頁面統一的文本樣式。與 Android 中對文本進行自定義 style 很相似。

      在目前頁面中設定統一的 DefaultTextStyle 預設文本樣式,在目前頁面中用到的 Text 預設應用的都是該樣式,若需要調整部分樣式,直接設定 TextStyle 即可;若不需要重用該樣式,設定 inherit: false 屬性即可,但 textAlign 并不在該效果内。

Widget _childDefaultTextWid() {
  return new SafeArea(
      top: false,
      child: Scaffold(
          appBar: new AppBar(
            title: Text('DefaultTextStyle Demo'),
          ),
          body: DefaultTextStyle(
            style: TextStyle(
                color: Colors.blueGrey, wordSpacing: 10.0, fontSize: 20.0),
            textAlign: TextAlign.center,
            child: Container(
                child: ListView(children: <Widget>[
              Text("Ha ha ha!預設文本樣式(局中/20.0)"),
              Text("Ha ha ha!與預設文本樣式部分不同",
                  style: TextStyle(color: Colors.redAccent),
                  textAlign: TextAlign.left),
              Text("Ha ha ha!", style: TextStyle(inherit: false)),
              Text("Ha ha ha!自己單獨樣式",
                  style: TextStyle(inherit: false, color: Colors.grey))
            ])),
          )));
}           

4. ExpansionTile 擴充Tile

      小菜在學習過程中嘗試了一下

ExpansionTile

,是一個可向下擴充空間的 Widget,如效果圖。

const ExpansionTile({
    Key key,
    this.leading,           // 前置圖示
    @required this.title,   // 标題内容
    this.backgroundColor,   // 背景色包括擴充空間整體背景色
    this.onExpansionChanged,// 擴充時監聽狀态
    this.children = const <Widget>[],   // 擴充空間
    this.trailing,          // 動畫效果
    this.initiallyExpanded = false,     // 初始化時是否展開
}) : assert(initiallyExpanded != null),
       super(key: key);           

      小菜嘗試過程中發現 ExpansionTile 雖然很友善,效果也很好,但是也有一些局限性,如下:

  1. 預設右側箭頭圖示是固定的,包括動畫旋轉角度等,不能直接調整,需要自定義;
  2. 點選擴充區域不會消失,需要自定義。
Widget _childExpanTileWid() {
  return new SafeArea(
      child: Scaffold(
          appBar: AppBar(title: Text('擴充 Tile')),
          body: Container(
              child: ExpansionTile(
                  title: Text('大禮包'),
                  leading: Icon(Icons.adjust),
                  backgroundColor: Colors.grey,
                  onExpansionChanged: (bool) {
                    _exState = bool;
                  },
                  children: <Widget>[
                Container(
                    decoration: BoxDecoration(borderRadius: BorderRadius.circular(3.0), color: Colors.white),
                    margin: EdgeInsets.all(5.0),
                    child: Column(children: <Widget>[
                      Row(children: <Widget>[
                        Padding(
                            padding: EdgeInsets.fromLTRB(10.0, 8.0, 0.0, 8.0),
                            child: Text('1. 可擷取雙倍會員積分;',
                                style: TextStyle(color: Colors.blue, fontSize: 16.0)))
                      ]),
                      Row(children: <Widget>[
                        Padding(
                            padding: EdgeInsets.fromLTRB(10.0, 8.0, 0.0, 8.0),
                            child: Text('2. 積分兌換獎品8折優惠;',
                                style: TextStyle(color: Colors.blue, fontSize: 16.0)))
                      ])
                    ]))
              ]))));
}           

5. Spacer 占位

Spacer

是小菜偶然間了解到的一個很強大的 Widget,Spacer 小菜的了解是占位元件,直接看效果圖更加直覺。Spacer 建立一個可調節的空間隔,可用于調整 Flex 容器(如行或列)中視窗小部件之間的間距;預設 flex: 1。

Widget _childSpacerWid() {
  return new SafeArea(
      top: false,
      child: Scaffold(
          appBar: new AppBar(
            title: Text('Spacer Demo'),
          ),
          body: Column(children: <Widget>[
            Row(children: <Widget>[
              Text('Begin', style: TextStyle(color: Colors.redAccent)),
              Spacer(),
              Text('Middle', style: TextStyle(color: Colors.greenAccent)),
              Spacer(flex: 2),
              Text('End', style: TextStyle(color: Colors.blue))
            ]),
            Row(children: <Widget>[
              Text('Begin', style: TextStyle(color: Colors.redAccent)),
              Spacer(),
              Text('Middle', style: TextStyle(color: Colors.greenAccent)),
              Text('End', style: TextStyle(color: Colors.blue))
            ]),
            Row(children: <Widget>[
              Text('Begin', style: TextStyle(color: Colors.redAccent)),
              Text('Middle', style: TextStyle(color: Colors.greenAccent)),
              Spacer(flex: 2),
              Text('End', style: TextStyle(color: Colors.blue))
            ])
          ])));
}           

      如果有不對的地方還希望多多指出。

繼續閱讀