1.ListView和GridView嵌套滑动冲突问题
ListView(
shrinkWrap: true,//增加
children: [
new GridView.count(
physics: new NeverScrollableScrollPhysics(),//增加
shrinkWrap: true,//增加
crossAxisCount: 3,
children:[]
],
)
关键代码:
GridView添加 physics: new NeverScrollableScrollPhysics() 和 shrinkWrap: true
2.Tab切换或滑动的状态保存问题
如果是底部导航栏切换推荐使用IndexedStack
组件,会自动保存状态,也可按如下方案:
1.State
组件实现AutomaticKeepAliveClientMixin
2.重写wantKeepAlive
为true
实例:
class _TabViewWidgetState extends State with AutomaticKeepAliveClientMixin{
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return SizeBox();
}
@override
bool get wantKeepAlive => true;
3.库名冲突
比如自定义绘制 ParagraphBuilder
的pushStyle
方法,你会发现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
关于这一块的详细解释,请参考这里,篇幅有限,不详细解析哈。
- ValueNotifier不更新
检查ValueNotifier里的对象和新的更改的对象是否是同一个,例如集合,如果操作的是同一个集合,那么是不会触发更新的 - 简单总结一下局部更新的一些组件:
-
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即可。