元件
輸入框
加背景顏色:decoration: InputDecoration( fillColor: Colors.white, filled: true,
修改寬高:修改TextField的高度可以通過decoration: InputDecoration的contentPadding進行修改
new TextField(
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(vertical: 10.0),
),
)
這種修改可以在沒有prefixIcon的時候生效,如果加入prefixIcon,就會出現一個最小的高度,
這時,按照如上方法修改如果高度較小的時候會修改失敗。
因而需要再TextField外層加一個BoxConstraints,程式碼如下:
new ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 25,
maxWidth: 200
),
child: new TextField(
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(vertical: 4.0),
hintText: '請輸入搜尋內容',
prefixIcon: Icon(Icons.search),
// contentPadding: EdgeInsets.all(10),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide.none),
filled: true,
fillColor: Color(0xffaaaaaa),
),
),
),
maxHeight為最大高度,可酌情進行更改,實際修改的高度依舊是contentPadding這個屬性。
maxWidth為最大寬度,可修改TextField的寬度。
較完整的輸入框:
Container(
width: Adapt.dp(326),
height: Adapt.dp(95),
child: TextField(
maxLines:99,
// keyboardType: TextInputType.number,
style: TextStyle(
color: MyColors.black_00,
fontSize: MyFonts.mediumminus,
),
// textAlign: TextAlign.center,
decoration: InputDecoration(
//加白色背景
fillColor: MyColors.grey_f5,
filled: true,
// hintText: "最低值",
hintStyle: TextStyle(
color: MyColors.grey_99,
fontSize: MyFonts.small),
contentPadding: EdgeInsets.fromLTRB(Adapt.dp(5.0),
Adapt.dp(7.0), Adapt.dp(5.0), Adapt.dp(6.0)),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(Adapt.dp(7))),
borderSide: BorderSide.none),
),
),
),
複製程式碼
加圓角
抽屜加圓角:
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: MyColors.white,
// borderRadius: BorderRadius.circular(Adapt.dp(20)),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(Adapt.dp(20)),
child: Drawer(
普通Container:
borderRadius: BorderRadius.only(topLeft: Radius.circular (Adapt.dp(20)) ,bottomLeft: Radius.circular (Adapt.dp(20),)),
複製程式碼
加邊框
decoration: BoxDecoration(
border: Border(right:BorderSide(
width: 1,color: Color(0xffddd)
))
),
複製程式碼
彈出抽屜
`Scaffold.of() called with a context that does not contain a Scaffold.`
如果出現此錯,用
GlobalKey<ScaffoldState> key=new GlobalKey();
void _handlerDrawerButton() {
key.currentState.openEndDrawer();
}
Widget build(BuildContext context) {
return Scaffold(
key: key,
backgroundColor: MyColors.grey_f5,
appBar: _appbar,
endDrawer: DrawerWidget(),或者Container(child:...)
body: Container(
),
);
}
複製程式碼
普通的InkWell圓角按鈕
InkWell(
onTap: () {
// _captchaPressed();//重置操作
},
child: Container(
height: Adapt.dp(44),
width: Adapt.dp(110),
alignment: Alignment(0, 0),
decoration: new BoxDecoration(
color: MyColors.white,
borderRadius: BorderRadius.all(
Radius.circular(Adapt.dp(22))),
border: new Border.all(width: 1, color: Colors.red),),
child: Text(
"重置",
style: TextStyle(
color: MyColors.text_font_black,
fontSize: MyFonts.large,
fontWeight: FontWeight.bold,)),
)),
網路版本:
Container(
margin: EdgeInsets.only(left: 40, top: 40),
child: new Material(
//INK可以實現裝飾容器
child: new Ink(
//用ink圓角矩形
// color: Colors.red,
decoration: new BoxDecoration(
//背景
color: Colors.white,
//設定四周圓角 角度
borderRadius: BorderRadius.all(Radius.circular(25.0)),
//設定四周邊框
border: new Border.all(width: 1, color: Colors.red),
),
child: new InkWell(
//圓角設定,給水波紋也設定同樣的圓角
//如果這裡不設定就會出現矩形的水波紋效果
borderRadius: new BorderRadius.circular(25.0),
//設定點選事件回撥
onTap: () {},
child: Container(
//設定 child 居中
alignment: Alignment(0, 0),
height: 50,
width: 300,
child: Text("點選 Container 圓角邊框"),
)),
),
),
),
複製程式碼
WidgetSpan
Text.rich(
TextSpan(children: <InlineSpan>[
TextSpan(text: "xxxxxxxxxxxx嚶嚶嚶嚶嚶嚶暈暈暈暈暈暈暈暈暈暈暈暈暈暈暈暈暈暈暈暈暈暈暈x"),
WidgetSpan(
child: Container(
color: Colors.blue,
width: 30.0,
height: 100.0,
)),
TextSpan(text: "xxy"),
]),
overflow: TextOverflow.ellipsis,
maxLines: 2,
)
複製程式碼
RaisedButton凸起按鈕
RaisedButton:
Container(
width: Adapt.dp(265),
height: Adapt.dp(40),
child: RaisedButton(
color: MyColors.ls,
shape: RoundedRectangleBorder(
side: BorderSide.none,
borderRadius: BorderRadius.all(Radius.circular(25))),
child: Text(
test['complete'],
style: TextStyle(
color: Colors.white, fontWeight: FontWeight.bold),
),
textColor: Theme.of(context).accentColor,
onPressed: () {
print('x');
})),
複製程式碼
渲染列表資料
1.ListView
Expanded(
child: ListView.builder(
shrinkWrap: true, //為true可以解決子控制元件必須設定高度的問題
physics:NeverScrollableScrollPhysics(),//禁用滑動事件
itemBuilder: (context, index) {
return _buildList(list[index]);
},
itemCount: list.length,
),
)
Widget _buildList(item) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
// onTap: CommonUtil.openPage(context, widget),
child: Container(
height: Adapt.dp(151),//也可以不加高度
margin: EdgeInsets.only(
bottom: Adapt.dp(13), right: Adapt.dp(13), left: Adapt.dp(13)),
padding: EdgeInsets.all(Adapt.dp(13)),
decoration: BoxDecoration(
color: MyColors.white, borderRadius: BorderRadius.circular(10)),
child: Row(
2.map
Expanded(
child: ListView(
children: getDistributorList(),
),
)
getDistributorList() {
return productNameList.map((item) {
return GestureDetector(
onTap: () {
},
behavior: HitTestBehavior.translucent,
child: Container(
padding: EdgeInsets.only(top: Adapt.dp(13)),
child: Row(
children: <Widget>[
Text(
item['name']??"",
style: TextStyle(
fontSize: MyFonts.mediumminus, color: MyColors.black_33),
)
],
),
),
);
}).toList();
}
複製程式碼
上滑框showModalBottomSheet
-
無法直接設定圓角;
-
元件最多隻能撐滿半螢幕,再多就出界了;
showDialog以及showModalBottomSheet狀態更新不重新整理解決方法
cloud.tencent.com/developer/a…
在listView中為每一個list增添控制器
void initState() {
// TODO: implement initState
super.initState();
// this.getTotalPrice();
for (int i = 0; i < productList.length; i++) {
// controller.add (TextEditingController(text: "1")) ;
productList[i]["getNum"] = "1";
}
}
return productList.map((item){
var textEditingController = new TextEditingController(text: item["getNum"]);
TextField(
controller: textEditingController,
onChanged: (text){
// _onChanceCount(item,text);
// setState(() {會彈回輸入框
item["getNum"]=text;
// });
},
複製程式碼
dialog的一些思考
https://juejin.im/post/5cc7dca3518825253d0348f3
https://github.com/liyabin1105/flutter_dialog/blob/master/lib/MyHomePage.dart
其他研究
flutter:教你自定義Dialog https://www.codercto.com/a/92081.html
https://blog.csdn.net/ulddfhv/article/details/91491918
https://www.jianshu.com/p/4bbbb5aa855d
ios風格彈框,帶輸入框
showCupertinoDialog(
context: context,
builder: (context) {
return CupertinoAlertDialog(
title: Text('提示'),
content: Card(
elevation: 0.0,
child: Column(
children: <Widget>[
Text('確認商品入庫?'),
SizedBox(height: 10,),
Container(height: 26,
// color: Colors.grey.shade50,
// padding: EdgeInsets.only(top: ),
child: TextField(
controller: null,
style: TextStyle(
color: MyColors.black_00,
fontSize: MyFonts.mediumminus,
// fontWeight: FontWeight.bold,
),
decoration: InputDecoration(
contentPadding: EdgeInsets.only(left: 16,top: 5,bottom: 4),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(Adapt.dp(13))),
borderSide: BorderSide.none),
hintText: '填寫備註',
filled: true,
fillColor: Colors.grey.shade50),
),)
],
),
),
actions: <Widget>[
CupertinoDialogAction(
onPressed: () {
Navigator.pop(context);
},
child: Text('取消',style: TextStyle(color: MyColors.black_33),),
),
CupertinoDialogAction(
onPressed: () {
Navigator.pop(context);
},
child: Text('確定',style: TextStyle(color: Colors.red),),
),
],
);
});
複製程式碼
Flutter使用CupertinoAlertDialog 報 'alertDialogLabel' was called on null.參考https://juejin.im/post/5c417d626fb9a049ec6b5d44
main.js
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
YabandLocalizationsDelegate.delegate,
const FallbackCupertinoLocalisationsDelegate(), //加入這個, 上面三個是我用來國際化的
],
class FallbackCupertinoLocalisationsDelegate
extends LocalizationsDelegate<CupertinoLocalizations> {
const FallbackCupertinoLocalisationsDelegate();
@override
bool isSupported(Locale locale) => true;
@override
Future<CupertinoLocalizations> load(Locale locale) =>
DefaultCupertinoLocalizations.load(locale);
@override
bool shouldReload(FallbackCupertinoLocalisationsDelegate old) => false;
}
複製程式碼
捕獲應用退出攔截彈出對話方塊
參考:www.cnblogs.com/pjl43/p/994…
Future<bool> _isSave(){
if(productList!=[]){
return
showDialog(
context: context,
builder: (context) =>
CustomDialog(
title: '提示',
content: '送貨單未儲存,確認退出?',
// confirmTextColor: Colors.red[400],
confirmCallback: () {
CommonUtil.closePage(context);
},
)
);
}else{
CommonUtil.closePage(context);
}
}
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: _isSave,
child: Scaffold(
resizeToAvoidBottomPadding: false,
appBar: MyAppBar(
title: "新增送貨單",
isBack: true,
backEvent: _isSave,//點圖示返回結果不觸發,結果按鍵就觸發了
複製程式碼
Tabbar不在頂部和底部的用法
import 'package:flutter/cupertino.dart';
import 'package:yilingpharmacy_doctor/common/CommonInsert.dart';
class MyPatientMainPage extends StatefulWidget {
@override
_MyPatientMainPageState createState() => _MyPatientMainPageState();
}
class _MyPatientMainPageState extends State<MyPatientMainPage>
with SingleTickerProviderStateMixin {
String dropdownValue = "線上";
var _tabController;
var _tabIndex = 0;
void initState() {
super.initState();
_tabController = new TabController(length: 2, vsync: this);
_tabController.addListener((){
setState(() {
_tabIndex = _tabController.index;
});
print(_tabController.index); });
}
@override
Widget build(BuildContext context) {
return Column(children: <Widget>[
// SizedBox(height: Adapt.screenH()*0.052,),
Container(
// alignment: Alignment.bottomLeft,
height: Adapt.screenH() * 0.153,
color: MyColors.lv,
padding: EdgeInsets.only(
top: Adapt.screenH() * 0.052,
),
child: Row(
children: <Widget>[
SizedBox(
width: Adapt.dp(10),
),
Container(
//兩種設定頭像的方法,這種會比較麻煩,
height: Adapt.dp(50),
width: Adapt.dp(50),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(Adapt.dp(25))),
child: LocalImageSelecter.getImage("b1_data_ic_yszczd"),
),
SizedBox(
width: Adapt.dp(11),
),
Container(
height: Adapt.dp(50),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 3,
),
Row(
children: <Widget>[
Text(
"劉海帆",
style: TextStyle(
fontSize: Adapt.dp(14),
color: Colors.white,
fontWeight: FontWeight.bold),
),
SizedBox(
width: Adapt.dp(13.5),
),
GestureDetector(
onTap: null,
child: Container(
width: Adapt.dp(54),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(Adapt.dp(2)),
),
child: Row(
children: <Widget>[
SizedBox(
width: Adapt.dp(6),
),
Text(
dropdownValue,
style: TextStyle(color: MyColors.lv),
),
SizedBox(
width: Adapt.dp(6),
),
LocalImageSelecter.getImage(
"b1_arrow_drop_green",
imageHeight: 10),
SizedBox(
width: Adapt.dp(5),
),
],
),
),
),
],
),
SizedBox(
height: Adapt.dp(12),
),
Row(
children: <Widget>[
Text(
'一級心理諮詢師、中科院心理健康指導師',
style: TextStyle(
fontSize: Adapt.dp(12), color: Colors.white),
),
],
)
],
),
)
],
)),
Container(
// color: Colors.black,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
flex: 1,
child: TabBar(
indicator: const BoxDecoration(),//不加下橫線
controller: _tabController,
tabs: <Widget>[
Tab(
child:
Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
"圖文問診",
style: _tabIndex==0?TextStyle(
color: MyColors.black_33,
fontSize: MyFonts.f_14,
fontWeight: FontWeight.bold):TextStyle(
color: MyColors.black_33,
fontSize: MyFonts.f_14,
),
),
_tabIndex==0?SizedBox(height: 12,):SizedBox(height: 15,),
_tabIndex==0?Container(color: MyColors.lv,height: 3,width: 20,):SizedBox()
],
)
),
Tab(
child:
Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
"問診預約",
style: _tabIndex==1?TextStyle(
color: MyColors.black_33,
fontSize: MyFonts.f_14,
fontWeight: FontWeight.bold):TextStyle(
color: MyColors.black_33,
fontSize: MyFonts.f_14,
),
),
_tabIndex==1?SizedBox(height: 12,):SizedBox(height: 15,),
_tabIndex==1?Container(color: MyColors.lv,height: 3,width: 20,):SizedBox()
],
)
),
],
),
)
],
),
// body: ,
),
Expanded(
child: TabBarView(
controller: _tabController,
children: <Widget>[Text("xx"), Text("xx")],
),
)
]);
}
}
複製程式碼
後期可以改造,animation controler 改造滑條
小bug:滑動過去,tab粗體效果顯示有點慢
Android Studio
開啟Android Studio主介面:
鍵盤操作Ctrl +Alt+S 開啟設定介面
左側搜尋框輸入keymap
比如想要查詢類的名稱補全,就可以在右邊的搜尋框內輸入class name關鍵字
可以進行相關的修改
shortcut就是快捷鍵的意思
abbreviation是指縮寫
複製程式碼
其他
顏色新增
color: const Color(0xFF0099ff), or /Colors.grey/
透明: child:Opacity(
opacity: 0,
child: Container(
width: 100.0,
height: 100.0,
margin: EdgeInsets.all(20.0),
color: Color(0xffff0000),
),
),
color: Colors.transparent或者rgbo
複製程式碼
延時載入
當setState() or markNeedsBuild() called during build.的時候用
void onDataChange2(val) {
if (mounted)
Future.delayed(Duration(milliseconds: 200)).then((e) {
setState(() {
isTab = val;
});
}
);
}
複製程式碼
遷移androidX(runtime和usetime不一致時)
stackoverflow.com/questions/5…
- 在專案級別build.gradle將類路徑更改為
com.android.tools.build:gradle:3.3.1
。 - 在應用程式級別build.gradle將您的
compileSdkVersion
和更改targetSdkVersion
為28。 - 現在,右鍵單擊flutter專案中的android目錄,轉到Flutter,然後單擊Android Studio中的Open Android模組。在新視窗中開啟專案。
- 現在,轉到工具欄中的“重構”,然後單擊“遷移到AndroidX”。
- 然後單擊“執行重構”並等待gradle構建。
改gradle版本
android/gradle/wrapper/grade-wrapper.properties
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
複製程式碼
全域性定時呼叫請求
一般登陸之後用,我在登陸進去之後的頁面用
class IndexPage extends StatefulWidget {
@override
_IndexPageState createState() => _IndexPageState();
}
class _IndexPageState extends State<IndexPage> {
void initState() {
super.initState();
countdown();
}
Timer countdownTimer;
void countdown() {
countdownTimer = new Timer.periodic(new Duration(seconds: 10), (timer) {
_getUnread();
});
}
_getUnread() async {//你想調的介面
if (LocalStorage.get(BaseCommon.USER_ID)!=null) {
var res = await HttpManager.netFetch(
context,
Address.findByAccountIdAndAlias(),
{"accountId": LocalStorage.get(BaseCommon.USER_ID)},
null,
null,
noTip: true);
if (res != null) {
LocalStorage.save("Unread", res.data['unread']);
LocalStorage.save("MessagePcketid", res.data['id']);
print('unread未讀介面');
print(LocalStorage.get(("Unread")).toString());
print('MessagePcketid未讀id介面');
print(LocalStorage.get(("MessagePcketid")).toString());
} else {
toast(BaseCommon.SERVER_ERROR);
}
}
}
複製程式碼
定時器
驗證碼那樣的
_countdownTimer =
new Timer.periodic(new Duration(seconds: 1), (timer) {
if (mounted) {
setState(() {
if (countDownNum > 1) {
countDownNum--;
} else {
showCountDown = false;
_countdownTimer.cancel();
_countdownTimer = null;
}
});
}
});
複製程式碼
限定TextField輸入內容
頁面右上角的彈出選單
Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: MyColors.bg,
appBar: MyAppBar(
title: test['myTeam'],
rightEvent: Container(height: 50,width: 30,child: new PopupMenuButton(
itemBuilder: (BuildContext context) => <PopupMenuEntry>[
PopupMenuItem(
child: GestureDetector(onTap: (){
ClipboardData data = new ClipboardData(text:'xx');
Clipboard.setData(data);
Toast.show(test['toast_copy_invitation_code_success'], context,
duration: Toast.LENGTH_SHORT, gravity: Toast.CENTER);
Navigator.pop(context);
},
child: Text(test['copy_invitation_code'],style: TextStyle(fontSize: 12),),)
),
PopupMenuItem(
child: GestureDetector(onTap: null,
child: Text(test['dissolveTeam'],style: TextStyle(fontSize: 12),),)
),
]),),
),
)
複製程式碼
複製到貼上板
GestureDetector(onTap: (){
ClipboardData data = new ClipboardData(text:'xx');
Clipboard.setData(data);
})
複製程式碼
元件:ClipboardData.dart
import 'package:flutter/services.dart';
class ClipboardData {
/// Creates data for the system clipboard.
const ClipboardData({this.text});
/// Plain text variant of this clipboard data.
final String text;
}
class Clipboard {
Clipboard._();
static const String kTextPlain = 'text/plain';
/// Stores the given clipboard data on the clipboard.
///將ClipboardData中的內容複製的貼上板
static Future<void> setData(ClipboardData data) async {
await SystemChannels.platform.invokeMethod<void>(
'Clipboard.setData',
<String, dynamic>{
'text': data.text,
},
);
}
}
//ClipboardData data = new ClipboardData(text:"1231231231231231");
//Clipboard.setData(data);
//showMyToast('已複製到貼上板');
複製程式碼
Flutter TabBarView切換頁面防止重新整理重置
還有一些bug,
進去他獲取到了資料,切換tab再回來他才出現頁面重新整理渲染
是因為在渲染的時候加了if(mounted的判斷,去掉就好
This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree
無視之。。
flutter中bottomNavigationBar切換元件儲存狀態方案
cloud.tencent.com/developer/a…
部分修改:
var _pages= [
new WebPage(),
new DiscoverPage(),
new UserPage(),
];
複製程式碼
資料來源
標準的ListView
建構函式適用於小列表。 為了處理包含大量資料的列表,最好使用ListView.builder
建構函式。
ListView
的建構函式需要一次建立所有專案,但ListView.builder
的建構函式不需要,它將在列表項滾動到螢幕上時建立該列表項。
https://flutterchina.club/cookbook/lists/long-lists/
final controller = new List<String>.generate(3, (i) => "controller$i");
//下面的報錯https://blog.csdn.net/dpl12/article/details/92012226
final List<String> items;
items:new List<String>.generate(1000, (i)=>"item $i")/
複製程式碼
延時重新整理
_dataRefresh(){
Future.delayed(Duration(milliseconds: 200)).then((e) {
_list = [];
_getDataList();
});
}
複製程式碼
打包
flutter build apk
打包需注意:
再打包 位置在-》不在原地方 android、app下,而在build/app下
C:\workFlutter\warehouse\build\app\outputs\apk\release