如何实现Android平台的wrap_content 和match_parent

你可以按照如下方式实现:
1、Width = Wrap_content Height=Wrap_content:

  1. Wrap(
  2. children: <Widget>[your_child])

2、Width = Match_parent Height=Match_parent:

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

3、Width = Match_parent ,Height = Wrap_conten:

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

4、Width = Wrap_content ,Height = Match_parent:

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

如何避免FutureBuilder频繁执行future方法

错误用法:

  1. @override
  2. Widget build(BuildContext context) {
  3. return FutureBuilder(
  4. future: httpCall(),
  5. builder: (context, snapshot) {
  6. },
  7. );
  8. }

正确用法:

  1. class _ExampleState extends State<Example> {
  2. Future<int> future;
  3. @override
  4. void initState() {
  5. future = Future.value(42);
  6. super.initState();
  7. }
  8. @override
  9. Widget build(BuildContext context) {
  10. return FutureBuilder(
  11. future: future,
  12. builder: (context, snapshot) {
  13. },
  14. );
  15. }
  16. }

底部导航切换导致重建问题

在使用底部导航时经常会使用如下写法:

  1. Widget _currentBody;
  2. @override
  3. Widget build(BuildContext context) {
  4. return Scaffold(
  5. body: _currentBody,
  6. bottomNavigationBar: BottomNavigationBar(
  7. items: <BottomNavigationBarItem>[
  8. ...
  9. ],
  10. onTap: (index) {
  11. _bottomNavigationChange(index);
  12. },
  13. ),
  14. );
  15. }
  16. _bottomNavigationChange(int index) {
  17. switch (index) {
  18. case 0:
  19. _currentBody = OnePage();
  20. break;
  21. case 1:
  22. _currentBody = TwoPage();
  23. break;
  24. case 2:
  25. _currentBody = ThreePage();
  26. break;
  27. }
  28. setState(() {});
  29. }

此用法导致每次切换时都会重建页面。
解决办法,使用IndexedStack

  1. int _currIndex;
  2. @override
  3. Widget build(BuildContext context) {
  4. return Scaffold(
  5. body: IndexedStack(
  6. index: _currIndex,
  7. children: <Widget>[OnePage(), TwoPage(), ThreePage()],
  8. ),
  9. bottomNavigationBar: BottomNavigationBar(
  10. items: <BottomNavigationBarItem>[
  11. ...
  12. ],
  13. onTap: (index) {
  14. _bottomNavigationChange(index);
  15. },
  16. ),
  17. );
  18. }
  19. _bottomNavigationChange(int index) {
  20. setState(() {
  21. _currIndex = index;
  22. });
  23. }

TabBar切换导致重建(build)问题

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

  1. TabBarView(
  2. controller: this._tabController,
  3. children: <Widget>[
  4. _buildTabView1(),
  5. _buildTabView2(),
  6. ],
  7. )

此时切换tab时,页面会重建,解决方法设置PageStorageKey

  1. var _newsKey = PageStorageKey('news');
  2. var _technologyKey = PageStorageKey('technology');
  3. TabBarView(
  4. controller: this._tabController,
  5. children: <Widget>[
  6. _buildTabView1(_newsKey),
  7. _buildTabView2(_technologyKey),
  8. ],
  9. )

Stack 子组件设置了宽高不起作用

在Stack中设置100x100红色盒子,如下:

  1. Center(
  2. child: Container(
  3. height: 300,
  4. width: 300,
  5. color: Colors.blue,
  6. child: Stack(
  7. children: <Widget>[
  8. Positioned.fill(
  9. child: Container(
  10. height: 100,
  11. width: 100,
  12. color: Colors.red,
  13. ),
  14. )
  15. ],
  16. ),
  17. ),
  18. )

此时红色盒子充满父组件,解决办法,给红色盒子组件包裹Center、Align或者UnconstrainedBox,代码如下:

  1. Positioned.fill(
  2. child: Align(
  3. child: Container(
  4. height: 100,
  5. width: 100,
  6. color: Colors.red,
  7. ),
  8. ),
  9. )

如何在State类中获取StatefulWidget控件的属性

  1. class Test extends StatefulWidget {
  2. Test({this.data});
  3. final int data;
  4. @override
  5. State<StatefulWidget> createState() => _TestState();
  6. }
  7. class _TestState extends State<Test>{
  8. }

如下,如何在_TestState获取到Test的data数据呢:

  1. 在_TestState也定义同样的参数,此方式比较麻烦,不推荐。
  2. 直接使用widget.data(推荐)。

    default value of optional parameter must be constant

    上面的异常在类构造函数的时候会经常遇见,如下面的代码就会出现此异常:
    1. class BarrageItem extends StatefulWidget {
    2. BarrageItem(
    3. { this.text,
    4. this.duration = Duration(seconds: 3)});
    异常信息提示:可选参数必须为常量,修改如下:
    1. const Duration _kDuration = Duration(seconds: 3);
    2. class BarrageItem extends StatefulWidget {
    3. BarrageItem(
    4. {this.text,
    5. this.duration = _kDuration});
    定义一个常量,Dart中常量通常使用k开头,_表示私有,只能在当前包内使用,别问我为什么如此命名,问就是源代码中就是如此命名的。

    如何移除debug模式下右上角“DEBUG”标识

    1. MaterialApp(
    2. debugShowCheckedModeBanner: false
    3. )

    如何使用16进制的颜色值

    下面的用法是无法显示颜色的:
    1. Color(0xb74093)
    因为Color的构造函数是ARGB,所以需要加上透明度,正确用法:
    1. Color(0xFFb74093)
    FF表示完全不透明。

    如何改变应用程序的icon和名称

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

    如何给TextField设置初始值

    1. class _FooState extends State<Foo> {
    2. TextEditingController _controller;
    3. @override
    4. void initState() {
    5. super.initState();
    6. _controller = new TextEditingController(text: '初始值');
    7. }
    8. @override
    9. Widget build(BuildContext context) {
    10. return TextField(
    11. controller: _controller,
    12. );
    13. }
    14. }

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

    Scaffold.of()中的context没有包含在Scaffold中,如下代码就会报此异常:
    1. class HomePage extends StatelessWidget {
    2. @override
    3. Widget build(BuildContext context) {
    4. return Scaffold(
    5. appBar: AppBar(
    6. title: Text('老孟'),
    7. ),
    8. body: Center(
    9. child: RaisedButton(
    10. color: Colors.pink,
    11. textColor: Colors.white,
    12. onPressed: _displaySnackBar(context),
    13. child: Text('show SnackBar'),
    14. ),
    15. ),
    16. );
    17. }
    18. }
    19. _displaySnackBar(BuildContext context) {
    20. final snackBar = SnackBar(content: Text('老孟'));
    21. Scaffold.of(context).showSnackBar(snackBar);
    22. }
    注意此时的context是HomePage的,HomePage并没有包含在Scaffold中,所以并不是调用在Scaffold中就可以,而是看context,修改如下:
    1. _scaffoldKey.currentState.showSnackBar(snackbar);
    或者:
    1. Scaffold(
    2. appBar: AppBar(
    3. title: Text('老孟'),
    4. ),
    5. body: Builder(
    6. builder: (context) =>
    7. Center(
    8. child: RaisedButton(
    9. color: Colors.pink,
    10. textColor: Colors.white,
    11. onPressed: () => _displaySnackBar(context),
    12. child: Text('老孟'),
    13. ),
    14. ),
    15. ),
    16. );

    Waiting for another flutter command to release the startup lock

    在执行flutter命令时经常遇到上面的问题,
    解决办法一:
    1、Mac或者Linux在终端执行如下命令:
    1. killall -9 dart
    2、Window执行如下命令:
    1. taskkill /F /IM dart.exe
    解决办法二:
    删除flutter SDK的目录下/bin/cache/lockfile文件。

    无法调用setState

    不能在StatelessWidget控件中调用了,需要在StatefulWidget中调用。

    设置当前控件大小为父控件大小的百分比

    1、使用FractionallySizedBox控件
    2、获取父控件的大小并乘以百分比:
    1. MediaQuery.of(context).size.width * 0.5

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

    解决方法:
    1. Row(
    2. children: <Widget>[
    3. Flexible(
    4. child: new TextField(),
    5. ),
    6. ],
    7. ),

    TextField 动态获取焦点和失去焦点

    获取焦点:
    1. FocusScope.of(context).requestFocus(_focusNode);
    _focusNode为TextField的focusNode:
    1. _focusNode = FocusNode();
    2. TextField(
    3. focusNode: _focusNode,
    4. ...
    5. )
    失去焦点:
    1. _focusNode.unfocus();

    如何判断当前平台

    1. import 'dart:io' show Platform;
    2. if (Platform.isAndroid) {
    3. // Android-specific code
    4. } else if (Platform.isIOS) {
    5. // iOS-specific code
    6. }
    平台类型包括:
    1. Platform.isAndroid
    2. Platform.isFuchsia
    3. Platform.isIOS
    4. Platform.isLinux
    5. Platform.isMacOS
    6. Platform.isWindows

    Android无法访问http

    其实这本身不是Flutter的问题,但在开发中经常遇到,在Android Pie版本及以上和IOS 系统上默认禁止访问http,主要是为了安全考虑。
    Android解决办法:
    ./android/app/src/main/AndroidManifest.xml配置文件中application标签里面设置networkSecurityConfig属性:
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <manifest ... >
    3. <application android:networkSecurityConfig="@xml/network_security_config">
    4. <!-- ... -->
    5. </application>
    6. </manifest>
    ./android/app/src/main/res目录下创建xml文件夹(已存在不用创建),在xml文件夹下创建network_security_config.xml文件,内容如下:
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <network-security-config>
    3. <base-config cleartextTrafficPermitted="true">
    4. <trust-anchors>
    5. <certificates src="system" />
    6. </trust-anchors>
    7. </base-config>
    8. </network-security-config>

    IOS无法访问http

    ./ios/Runner/Info.plist文件中添加如下:
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    3. <plist version="1.0">
    4. <dict>
    5. ...
    6. <key>NSAppTransportSecurity</key>
    7. <dict>
    8. <key>NSAllowsArbitraryLoads</key>
    9. <true/>
    10. </dict>
    11. </dict>
    12. </plist>