flutter開發(fā)中一些技巧和坑點

獲取設(shè)備寬高

double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;

Android設(shè)置狀態(tài)欄透明

  1. 原生修改
public class MainActivity extends FlutterActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    {
         // api大于21設(shè)置狀態(tài)欄透明
        getWindow().setStatusBarColor(0);
    }
    GeneratedPluginRegistrant.registerWith(this);
  }
}
  1. flutter修改(么有測試過,自己測試下反正不難)
// 輸出渲染
void main() {
  runApp(App());
  if (Platform.isAndroid) {
    // 以下兩行 設(shè)置android狀態(tài)欄為透明的沉浸。寫在組件渲染之后,是為了在渲染后進(jìn)行set賦值,覆蓋狀態(tài)欄,寫在渲染之前MaterialApp組件會覆蓋掉這個值。
    SystemUiOverlayStyle systemUiOverlayStyle = SystemUiOverlayStyle(statusBarColor: Colors.transparent);
    SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
  }
}

區(qū)別final與const

在Dart中,當(dāng)你不需要去改變一個變量的時候,應(yīng)該使用final或者const,而不是使用var去聲明一個變量。一個final變量只允許被賦值一次,必須在定義時或者構(gòu)造函數(shù)參數(shù)表中將其初始化。
const所修飾的是編譯時常量,我們在編譯時就已經(jīng)知道了它的值,它的值是不可改變的。
const比final更加嚴(yán)格,看以下例子:

final List<String> list = [];
list.add('1'); // 正確

const List<String> list = [];
list.add('1'); // 錯誤,運行時報錯:Cannot add to an unmodifiable list

final timestamp = new DateTime.now().millisecondsSinceEpoch; // 正確

const timestamp = new DateTime.now().millisecondsSinceEpoch; // 錯誤,編譯前報錯:Const variables must be initialized with a constant value

FocusScope轉(zhuǎn)移焦點,隱藏輸入法

166723349530a968.gif
Container(
        height: 500.0,
        child: new GestureDetector(
          onTap: () {
            // 通過GestureDetector捕獲點擊事件,再通過FocusScope將焦點轉(zhuǎn)移至空焦點      new FocusNode()
            FocusScope.of(context).requestFocus(FocusNode());
          },
          child: Container(
              margin: EdgeInsets.all(30.0),
              child: ListView(children: <Widget>[
                TextField(
                  decoration: InputDecoration(labelText: 'Username'),
                ),
                TextField(
                  decoration: InputDecoration(labelText: 'Password'),
                )
              ])),
        ),
      ),
  • 這里傳遞給FocusScope的context不能在MaterialApp下面,即你需要將這部分代碼放到獨立的一個Widget里面

定時任務(wù)

  1. 在我們的開發(fā)之中難免要用到定時,比如我們常用的獲取驗證碼的需求,下面請看利用定時器來實現(xiàn)這一功能需求
  • 定義3個變量
int _seconds = 0;
String _verifyStr  = "獲取驗證碼";
/// 定時器Timer
Timer _timer;
  • 實現(xiàn)timer,代碼很清晰,簡單的說我設(shè)了10秒的倒計時,利用Timer.periodic方法來執(zhí)行,間隔時間是1秒
/// 倒計時
  _startTimer() {
    _seconds = 10;

    _timer = Timer.periodic(new Duration(seconds: 1), (timer){
      if(_seconds == 0){
        _cancleTimer();
        return;
      }
      _seconds--;
      _verifyStr = "${_seconds}s";
      if (_seconds == 0){
        _verifyStr = "重新發(fā)送";
      }
      setState(() {});
    });
  }

  _cancleTimer(){
    _timer?.cancel();
  }

@override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
   /// 頁面銷毀的時候,清除timer
    _cancleTimer();
  }
  • 執(zhí)行,并不是每次按都執(zhí)行_startTimer,加上判斷條件只有_seconds == 0時才執(zhí)行效果如下圖
new Container(
          padding: const EdgeInsets.only(top: 15.0, left: 15.0),
          child: new RaisedButton(
            /// 觸發(fā)定時任務(wù)
            onPressed: (_seconds == 0)?(){
              _startTimer();
            }:null,
            child: new Text(_verifyStr),
            shape: new RoundedRectangleBorder(
              borderRadius: new BorderRadius.all(new Radius.circular(15.0)),
            ),
            textColor: Colors.blue,
            color: Colors.yellowAccent,
            disabledColor: Colors.yellowAccent,
            disabledTextColor: Colors.blue,
          ),
        ),
GIF.gif

利用 Container的BoxDecoration裝飾實現(xiàn)漸變

  • 例子如下
 Container(
        decoration: BoxDecoration(gradient: LinearGradient(
          colors: [const Color(0xFFFFFFEE), const Color(0xFF999999),const Color(0xFF862547),],
          tileMode: TileMode.repeated, // repeats the gradient over the canvas
        ),),
  • 效果如下


    漸變.png
  • BoxDecoration的屬性

const BoxDecoration({
    this.color, // 盒子顏色
    this.image, // 圖片
    this.border, 邊框顏色和線寬度
    this.borderRadius, // 圓角度
    this.boxShadow, // 陰影
    this.gradient, // 漸變
    this.backgroundBlendMode, // 混合Mode
    this.shape = BoxShape.rectangle,  // 形狀
  }) 
  • 邊框圓角實現(xiàn)
decoration: new BoxDecoration(
  border: new Border.all(color: Color(0xFFFF0000), width: 1.0), // 邊色與邊寬度
  color: Color(0xFF999999), //  盒子顏色
  //        borderRadius: new BorderRadius.circular((15.0)), // 圓角度
  borderRadius: new BorderRadius.vertical(top: Radius.elliptical(20, 50)), // 也可控件一邊圓角大小
),
  • Dart知識點(?. / ??)
  1. ?. 運算符在左邊為null的情況下會阻斷右邊的調(diào)用。
  2. ?? 運算符表示在左側(cè)表達(dá)式為null時為其設(shè)置默認(rèn)值。

對于表達(dá)式:

tar[a]?.tars(b)

如果tar為null或tar[a]為null或tars(b)的值為null,都會導(dǎo)致表達(dá)式為null。

  1. operator重載操作符
    operator 是 Dart 的一個關(guān)鍵字,它和運算符(如=,+,-)一起使用,表示一個 運算符重載函數(shù),在理解時可將operator和運算符(如operator=)視為一個函數(shù)名

關(guān)于混編中退出flutter頁面的時候黑屏的情況

if(Navigator.canPop(context)){
  Navigator.pop(context, true);
}else {
  SystemNavigator.pop();
}

關(guān)于ListView中嵌套使用ListView,請在子組件中設(shè)置以下屬性

shrinkWrap: true,

底部彈窗默認(rèn)點擊消失,如何保持面板點擊不消失

  • 可以子組件外面包一層GestureDetector并設(shè)置onTap為false,攔截點擊事件可以使點擊底部面板區(qū)域時不消失。
 showModalBottomSheet(
        context: context,
        builder: (context) {
          return GestureDetector(
            onTap: () => false,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                titleWidget,
                twoWidget,
                Expanded(
                  child: BottomUserRankingPage(
                    context,
                    lists: lists,
                  ),
                ),
              ],
            ),
          );
        });

實現(xiàn)跳轉(zhuǎn)到廣告按back返回是主界面

 Navigator.of(context).pushReplacementNamed('/Main');
 Navigator.of(context).push(WebPage);

如何強制豎屏

void main() {
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
    .then((_) {
      runApp(new MyApp());
    });
}

在線上的app,如果flutter報錯,那一片紅可是非常的辣眼睛,給用戶的體驗也很不好,其實我們可以自定義錯誤頁面

ErrorWidget.builder = (FlutterErrorDetails details) {
    print(details.toString());
    return Center(
      child: Text("Sorry 我下班了"),
    );
  };

在Flutter中,加載本地圖片會存在一個加載過程。比如點擊圖標(biāo)做圖標(biāo)的切換時,那么首次會發(fā)生閃動的情況。尤其是做類似引導(dǎo)頁這類需求是,通過左右滑動切換圖片時會發(fā)生比較明顯的白屏一閃而過。

解決方法很簡單,就是使用 precacheImage,它將圖像預(yù)存到圖像緩存中。如果圖像稍后被使用,它會被加載得更快。

precacheImage(AssetImage("assets/mylogo"), context);

在iOS 13中遇到了http網(wǎng)頁打不開的問題,添加以下文字到Info.plist
yourdomain.com 是你請求的鏈接的域名

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>yourdomain.com</key>
            <dict>
                <key>NSExceptionAllowInsecureHTTPLoads</key>
                <true/>
            </dict>
        </dict>
        <key>NSAllowsArbitraryLoadsInWebContent</key>
        <true/>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容