超過百萬的StackOverflow Flutter 問題

老孟導(dǎo)讀:今天分享StackOverflow上高訪問量的20大問題,這些問題給我一種特別熟悉的感覺,我想你一定或多或少的遇到過,有的問題在stackoverflow上有幾十萬的閱讀量,說明很多人都遇到了這些問題,把這些問題整理分享給大家,每期20個(gè),每隔2周分享一次。

如何實(shí)現(xiàn)Android平臺的wrap_content 和match_parent

你可以按照如下方式實(shí)現(xiàn):

1、Width = Wrap_content Height=Wrap_content:

Wrap(
  children: <Widget>[your_child])

2、Width = Match_parent Height=Match_parent:

Container(
        height: double.infinity,
    width: double.infinity,child:your_child)

3、Width = Match_parent ,Height = Wrap_conten:

Row(
  mainAxisSize: MainAxisSize.max,
  children: <Widget>[*your_child*],
);

4、Width = Wrap_content ,Height = Match_parent:

Column(
  mainAxisSize: MainAxisSize.max,
  children: <Widget>[your_child],
);

如何避免FutureBuilder頻繁執(zhí)行future方法

錯(cuò)誤用法:

@override
Widget build(BuildContext context) {
  return FutureBuilder(
    future: httpCall(),
    builder: (context, snapshot) {
     
    },
  );
}

正確用法:

class _ExampleState extends State<Example> {
  Future<int> future;

  @override
  void initState() {
    future = Future.value(42);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: future,
      builder: (context, snapshot) {
       
      },
    );
  }
}

底部導(dǎo)航切換導(dǎo)致重建問題

在使用底部導(dǎo)航時(shí)經(jīng)常會使用如下寫法:

Widget _currentBody;

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: _currentBody,
    bottomNavigationBar: BottomNavigationBar(
      items: <BottomNavigationBarItem>[
        ...
      ],
      onTap: (index) {
        _bottomNavigationChange(index);
      },
    ),
  );
}

_bottomNavigationChange(int index) {
  switch (index) {
    case 0:
      _currentBody = OnePage();
      break;
    case 1:
      _currentBody = TwoPage();
      break;
    case 2:
      _currentBody = ThreePage();
      break;
  }
  setState(() {});
}

此用法導(dǎo)致每次切換時(shí)都會重建頁面。

解決辦法,使用IndexedStack

int _currIndex;

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: IndexedStack(
        index: _currIndex,
        children: <Widget>[OnePage(), TwoPage(), ThreePage()],
      ),
    bottomNavigationBar: BottomNavigationBar(
      items: <BottomNavigationBarItem>[
        ...
      ],
      onTap: (index) {
        _bottomNavigationChange(index);
      },
    ),
  );
}

_bottomNavigationChange(int index) {
  setState(() {
      _currIndex = index;
    });
}

TabBar切換導(dǎo)致重建(build)問題

通常情況下,使用TabBarView如下:

TabBarView(
  controller: this._tabController,
  children: <Widget>[
    _buildTabView1(),
    _buildTabView2(),
  ],
)

此時(shí)切換tab時(shí),頁面會重建,解決方法設(shè)置PageStorageKey

var _newsKey = PageStorageKey('news');
var _technologyKey = PageStorageKey('technology');

TabBarView(
  controller: this._tabController,
  children: <Widget>[
    _buildTabView1(_newsKey),
    _buildTabView2(_technologyKey),
  ],
)

Stack 子組件設(shè)置了寬高不起作用

在Stack中設(shè)置100x100紅色盒子,如下:

Center(
  child: Container(
    height: 300,
    width: 300,
    color: Colors.blue,
    child: Stack(
      children: <Widget>[
        Positioned.fill(
          child: Container(
            height: 100,
            width: 100,
            color: Colors.red,
          ),
        )
      ],
    ),
  ),
)

此時(shí)紅色盒子充滿父組件,解決辦法,給紅色盒子組件包裹Center、Align或者UnconstrainedBox,代碼如下:

Positioned.fill(
  child: Align(
    child: Container(
      height: 100,
      width: 100,
      color: Colors.red,
    ),
  ),
)

如何在State類中獲取StatefulWidget控件的屬性

class Test extends StatefulWidget {
  Test({this.data});
  final int data;
  @override
  State<StatefulWidget> createState() => _TestState();
}

class _TestState extends State<Test>{

}

如下,如何在_TestState獲取到Test的data數(shù)據(jù)呢:

  1. 在_TestState也定義同樣的參數(shù),此方式比較麻煩,不推薦。
  2. 直接使用widget.data(推薦)。

default value of optional parameter must be constant

上面的異常在類構(gòu)造函數(shù)的時(shí)候會經(jīng)常遇見,如下面的代碼就會出現(xiàn)此異常:

class BarrageItem extends StatefulWidget {
  BarrageItem(
      { this.text,
      this.duration = Duration(seconds: 3)});

異常信息提示:可選參數(shù)必須為常量,修改如下:

const Duration _kDuration = Duration(seconds: 3);

class BarrageItem extends StatefulWidget {
  BarrageItem(
      {this.text,
      this.duration = _kDuration});

定義一個(gè)常量,Dart中常量通常使用k開頭,_表示私有,只能在當(dāng)前包內(nèi)使用,別問我為什么如此命名,問就是源代碼中就是如此命名的。

如何移除debug模式下右上角“DEBUG”標(biāo)識

MaterialApp(
 debugShowCheckedModeBanner: false
)

如何使用16進(jìn)制的顏色值

下面的用法是無法顯示顏色的:

Color(0xb74093)

因?yàn)镃olor的構(gòu)造函數(shù)是ARGB,所以需要加上透明度,正確用法:

Color(0xFFb74093)

FF表示完全不透明。

如何改變應(yīng)用程序的icon和名稱

鏈接:https://blog.csdn.net/mengks1987/article/details/95306508

如何給TextField設(shè)置初始值

class _FooState extends State<Foo> {
  TextEditingController _controller;

  @override
  void initState() {
    super.initState();
    _controller = new TextEditingController(text: '初始值');
  }

  @override
  Widget build(BuildContext context) {
    return TextField(
          controller: _controller,
        );
  }
}

Scaffold.of() called with a context that does not contain a Scaffold

Scaffold.of()中的context沒有包含在Scaffold中,如下代碼就會報(bào)此異常:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('老孟'),
      ),
      body: Center(
        child: RaisedButton(
          color: Colors.pink,
          textColor: Colors.white,
          onPressed: _displaySnackBar(context),
          child: Text('show SnackBar'),
        ),
      ),
    );
  }
}

_displaySnackBar(BuildContext context) {
  final snackBar = SnackBar(content: Text('老孟'));
  Scaffold.of(context).showSnackBar(snackBar);
}

注意此時(shí)的context是HomePage的,HomePage并沒有包含在Scaffold中,所以并不是調(diào)用在Scaffold中就可以,而是看context,修改如下:

_scaffoldKey.currentState.showSnackBar(snackbar); 

或者:

Scaffold(
    appBar: AppBar(
        title: Text('老孟'),
    ),
    body: Builder(
        builder: (context) => 
            Center(
            child: RaisedButton(
            color: Colors.pink,
            textColor: Colors.white,
            onPressed: () => _displaySnackBar(context),
            child: Text('老孟'),
            ),
        ),
    ),
);

Waiting for another flutter command to release the startup lock

在執(zhí)行flutter命令時(shí)經(jīng)常遇到上面的問題,

解決辦法一:

1、Mac或者Linux在終端執(zhí)行如下命令:

killall -9 dart

2、Window執(zhí)行如下命令:

taskkill /F /IM dart.exe

解決辦法二:

刪除flutter SDK的目錄下/bin/cache/lockfile文件。

無法調(diào)用setState

不能在StatelessWidget控件中調(diào)用了,需要在StatefulWidget中調(diào)用。

設(shè)置當(dāng)前控件大小為父控件大小的百分比

1、使用FractionallySizedBox控件

2、獲取父控件的大小并乘以百分比:

MediaQuery.of(context).size.width * 0.5

Row直接包裹TextField異常:BoxConstraints forces an infinite width

解決方法:

Row(
    children: <Widget>[
        Flexible(
            child: new TextField(),
        ),
  ],
),

TextField 動態(tài)獲取焦點(diǎn)和失去焦點(diǎn)

獲取焦點(diǎn):

FocusScope.of(context).requestFocus(_focusNode);

_focusNode為TextField的focusNode:

_focusNode = FocusNode();

TextField(
    focusNode: _focusNode,
    ...
)

失去焦點(diǎn):

_focusNode.unfocus();

如何判斷當(dāng)前平臺

import 'dart:io' show Platform;

if (Platform.isAndroid) {
  // Android-specific code
} else if (Platform.isIOS) {
  // iOS-specific code
}

平臺類型包括:

Platform.isAndroid
Platform.isFuchsia
Platform.isIOS
Platform.isLinux
Platform.isMacOS
Platform.isWindows

Android無法訪問http

其實(shí)這本身不是Flutter的問題,但在開發(fā)中經(jīng)常遇到,在Android Pie版本及以上和IOS 系統(tǒng)上默認(rèn)禁止訪問http,主要是為了安全考慮。

Android解決辦法:

./android/app/src/main/AndroidManifest.xml配置文件中application標(biāo)簽里面設(shè)置networkSecurityConfig屬性:

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application android:networkSecurityConfig="@xml/network_security_config">
         <!-- ... -->
    </application>
</manifest>

./android/app/src/main/res目錄下創(chuàng)建xml文件夾(已存在不用創(chuàng)建),在xml文件夾下創(chuàng)建network_security_config.xml文件,內(nèi)容如下:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system" />
        </trust-anchors>
    </base-config>
</network-security-config>

IOS無法訪問http

./ios/Runner/Info.plist文件中添加如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    ...
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
</dict>
</plist>

交流

Github地址:https://github.com/781238222/flutter-do

170+組件詳細(xì)用法:http://laomengit.com

如果你對Flutter還有疑問或者技術(shù)方面的疑惑,歡迎加入Flutter交流群(微信:laomengit)。

同時(shí)也歡迎關(guān)注我的Flutter公眾號【老孟程序員】,公眾號首發(fā)Flutter的相關(guān)內(nèi)容。

Flutter生態(tài)建設(shè)離不開你我他,需要大家共同的努力,點(diǎn)贊也是其中的一種,如果文章幫助到了你,希望點(diǎn)個(gè)贊。

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

相關(guān)閱讀更多精彩內(nèi)容

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