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.庫名衝突
比如自定義繪製 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即可。