欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

超过百万的* Flutter 问题

程序员文章站 2022-07-10 20:58:51
老孟导读:今天分享*上高访问量的20大问题,这些问题给我一种特别熟悉的感觉,我想你一定或多或少的遇到过,有的问题在*上有几十万的阅读量,说明很多人都遇到了这些问题,把这些问题整理分享给大家,每期20个,每隔2周分享一次。 如何实现Android平台的w ......

超过百万的* Flutter 问题

老孟导读:今天分享*上高访问量的20大问题,这些问题给我一种特别熟悉的感觉,我想你一定或多或少的遇到过,有的问题在*上有几十万的阅读量,说明很多人都遇到了这些问题,把这些问题整理分享给大家,每期20个,每隔2周分享一次。

如何实现android平台的wrap_content 和match_parent

你可以按照如下方式实现:

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频繁执行future方法

错误用法:

@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) {
       
      },
    );
  }
}

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

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

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(() {});
}

此用法导致每次切换时都会重建页面。

解决办法,使用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切换导致重建(build)问题

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

tabbarview(
  controller: this._tabcontroller,
  children: <widget>[
    _buildtabview1(),
    _buildtabview2(),
  ],
)

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

var _newskey = pagestoragekey('news');
var _technologykey = pagestoragekey('technology');

tabbarview(
  controller: this._tabcontroller,
  children: <widget>[
    _buildtabview1(_newskey),
    _buildtabview2(_technologykey),
  ],
)

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

在stack中设置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,
          ),
        )
      ],
    ),
  ),
)

此时红色盒子充满父组件,解决办法,给红色盒子组件包裹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数据呢:

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

default value of optional parameter must be constant

上面的异常在类构造函数的时候会经常遇见,如下面的代码就会出现此异常:

class barrageitem extends statefulwidget {
  barrageitem(
      { this.text,
      this.duration = duration(seconds: 3)});

异常信息提示:可选参数必须为常量,修改如下:

const duration _kduration = duration(seconds: 3);

class barrageitem extends statefulwidget {
  barrageitem(
      {this.text,
      this.duration = _kduration});

定义一个常量,dart中常量通常使用k开头,_表示私有,只能在当前包内使用,别问我为什么如此命名,问就是源代码中就是如此命名的。

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

materialapp(
 debugshowcheckedmodebanner: false
)

如何使用16进制的颜色值

下面的用法是无法显示颜色的:

color(0xb74093)

因为color的构造函数是argb,所以需要加上透明度,正确用法:

color(0xffb74093)

ff表示完全不透明。

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

链接:

如何给textfield设置初始值

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中,如下代码就会报此异常:

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);
}

注意此时的context是homepage的,homepage并没有包含在scaffold中,所以并不是调用在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

在执行flutter命令时经常遇到上面的问题,

解决办法一:

1、mac或者linux在终端执行如下命令:

killall -9 dart

2、window执行如下命令:

taskkill /f /im dart.exe

解决办法二:

删除flutter sdk的目录下/bin/cache/lockfile文件。

无法调用setstate

不能在statelesswidget控件中调用了,需要在statefulwidget中调用。

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

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 动态获取焦点和失去焦点

获取焦点:

focusscope.of(context).requestfocus(_focusnode);

_focusnode为textfield的focusnode:

_focusnode = focusnode();

textfield(
	focusnode: _focusnode,
	...
)

失去焦点:

_focusnode.unfocus();

如何判断当前平台

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

其实这本身不是flutter的问题,但在开发中经常遇到,在android pie版本及以上和ios 系统上默认禁止访问http,主要是为了安全考虑。

android解决办法:

./android/app/src/main/androidmanifest.xml配置文件中application标签里面设置networksecurityconfig属性:

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

./android/app/src/main/res目录下创建xml文件夹(已存在不用创建),在xml文件夹下创建network_security_config.xml文件,内容如下:

<?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地址:

170+组件详细用法:

如果你对flutter还有疑问或者技术方面的疑惑,欢迎加入flutter交流群(微信:laomengit)。

同时也欢迎关注我的flutter公众号【老孟程序员】,公众号首发flutter的相关内容。

flutter生态建设离不开你我他,需要大家共同的努力,点赞也是其中的一种,如果文章帮助到了你,希望点个赞。