Flutter开发问题合集

1.ListView和GridView嵌套滑动冲突问题

ListView(
          shrinkWrap: true,//增加
          children: <Widget>[
            new GridView.count(
            physics: new NeverScrollableScrollPhysics(),//增加
            shrinkWrap: true,//增加
            crossAxisCount: 3,
            children:<Widget>[]
          ],
        )

关键代码:

GridView添加 physics: new NeverScrollableScrollPhysics() 和 shrinkWrap: true

2.Tab切换或滑动的状态保存问题

如果是底部导航栏切换推荐使用IndexedStack组件,会自动保存状态,也可按如下方案:
1.State组件实现AutomaticKeepAliveClientMixin
2.重写wantKeepAlive为true
实例:

class _TabViewWidgetState extends State<TabViewWidget> with AutomaticKeepAliveClientMixin{

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return SizeBox();
  }

  @override
  bool get wantKeepAlive => true;

3.库名冲突

比如自定义绘制 ParagraphBuilderpushStyle方法,你会发现TextStyle导入的包始终是爆红的,这是因为库名冲突了,解决方案:

import 'dart:ui' as other; //重点 命一个别名

class MyDraw extends CustomPainter{
  @override
  void paint(Canvas canvas, Size size) {
    final textStyle = other.TextStyle( //前面加一个别名就好了
       .........
    );
 
    final paragraphBuilder = ParagraphBuilder(paragraphStyle)
      ..pushStyle(textStyle)
    .....代码省略
  }
}

需要注意的是别名最好不要和类名一样,因为如果需要调用静态方法或者导入方法会报错,造成别名和类名的冲突

4 jsonDecode解析出来的map是什么类型?

打印一下就知道,结果是LinkedHashMap

5 Positioned 大小问题

Positioned需要定义3个方向的属性才会有宽高属性,否则是无法确定宽高的,子组件也无宽高那么就会报错,示例如下:

Positioned(
  ....
top: 0,
 left: 0,
 right: 0,
)

6 TextField的一些问题解决方案

1.去掉底部文字计数器
在InputDecoration属性里设置counterText :' '
2.TextField无边框文字居中问题

经过测试TextField设置了border: InputBorder.none无边框后文字无法居中,设置了边框后又可以。所以实现无边框和文字居中的方案是添加一个透明边框:

border: OutlineInputBorder(
                                        borderSide: BorderSide(
                                          color: Colors.transparent,
                                        ),
                                      ),
                                      enabledBorder: OutlineInputBorder(
                                        borderSide: BorderSide(
                                          color: Colors.transparent,
                                        ),
                                      ),
                                      disabledBorder: OutlineInputBorder(
                                        borderSide: BorderSide(
                                          color: Colors.transparent,
                                        ),
                                      ),
                                      focusedBorder: OutlineInputBorder(
                                        borderSide: BorderSide(
                                          color: Colors.transparent,
                                        ),
                                      )
2.TextField换行问题

有时候需要实现个备份填写等长文本,需要限制字数和自动换行,可以这么实现:

Container(
                alignment: Alignment.topLeft,
                decoration: BoxDecoration(
                    borderRadius: BorderRadius.all(Radius.circular(8)),
                    color: editBackground),
                child: TextField(
                  keyboardType: TextInputType.multiline, //多文本
                  minLines: 1, 
                  maxLines: 20,  //一定要设置,不然不会换行,具体设置多大视需求而定
                  maxLength: 200, //设置了这个底部就会出现文字计数器
                  decoration: InputDecoration(
                      isDense: true,  //解决多行文本之间的间距
                      border: OutlineInputBorder(
                        borderSide: BorderSide(
                          color: Colors.transparent,
                        ),
                      ),
                      enabledBorder: OutlineInputBorder(
                        borderSide: BorderSide(
                          color: Colors.transparent,
                        ),
                      ),
                      disabledBorder: OutlineInputBorder(
                        borderSide: BorderSide(
                          color: Colors.transparent,
                        ),
                      ),
                      focusedBorder: OutlineInputBorder(
                        borderSide: BorderSide(
                          color: Colors.transparent,
                        ),
                      )),
                ),
              )

7. setStatue更新问题

1.setStatue出现不能更新的问题,需要着重检查更新布局的context, 父布局一定是具有State状态管理功能的组件,否则不能更新
2.弹窗dialog不能直接调用setStatue进行更新,因为context是不一样的,ui刷新并不能更新到弹窗,怎么办呢,可使用StatefulBuilder局部更新组件来进行更新. 简单使用:

StatefulBuilder(
                      builder: (BuildContext context,
                          void Function(void Function()) _statue) {
                        return InkWell(
                          onTap: () => {
                          _statue(() {  //调用_statue来完成局部更新,调用后StatefulBuilder里的组件会重新刷新一遍
                        mBean.oilTag = "$i$title";  
                         })
                          },
                          child: Container(
                            alignment: Alignment.centerRight,
                            child: Text(
                              isNotEmpty(mBean.oilTag) ? mBean.oilTag! : "请选择",
                              style: TextStyle(
                                  color: isNotEmpty(mBean.oilTag)
                                      ? colorText
                                      : color999),
                            ),
                          ),
                        );
                      },
                    )

或者直接使用弹窗的context进行更新,示例如下:

(context as Element).markNeedsBuild(); //标记这个context下的组件需要更新

这样弹窗会从上到下更新一遍ui
关于这一块的详细解释,请参考这里,篇幅有限,不详细解析哈。

  1. ValueNotifier不更新
    检查ValueNotifier里的对象和新的更改的对象是否是同一个,例如集合,如果操作的是同一个集合,那么是不会触发更新的
  2. 简单总结一下局部更新的一些组件:
  • StatefulBuilder: 该组件相当于是一个小型的StatefulWidget,暴露出一个方法用于局部更新
  • ValueListenableBuilder: 当监听的数据有变化时更新,一般配合ValueNotifier使用
  • StreamBuilder: 流数据变化监听,AsyncSnapshot会有多种状态,使用connectionState可以获取对应的状态,适合网络请求等耗时操作
  • FutureBuilder: Future方法监听, 与StreamBuilder 差不多,但是传入的是一个Future方法,需要注意当调用全局的setState会有重复刷新的问题,需要额外处理规避

8.流(Stream)的使用

分享一篇讲解的分享好的文章
“四大天王”:StreamController,Sink,Stream,StreamSubscription 的详细说明

9.集成地图问题

集成地图提示

java.lang.NoClassDefFoundError: Failed resolution of: Lcom/amap/api/maps/AMapOptions;

检查一遍发现AMapOptions有这个类呀,怎么会找不到,后面发现这个类和源码里导入的类包名不一样,我使用的是2D地图的类,而flutter里的是使用的3D的,破案了,把安卓里引入的地图包从2d改成3d即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章