老孟導讀:一個月前分享的《超過百萬的StackOverflow Flutter 問題-第一期》受到很多朋友的喜歡,非常感謝大家的支持,在文章末尾有第一期的鏈接,希望此文能對你有所幫助。
No connected devices
這個問題估計大部分都遇到過,解決方法如下:
- 執行flutter doctor Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, v1.12.13+hotfix.9, on Mac OS X 10.14.6 18G1012, locale zh-Hans-CN) [!] Android toolchain - develop for Android devices (Android SDK version 29.0.2) ! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses [✓] Xcode - develop for iOS and macOS (Xcode 11.3.1) [✓] Android Studio (version 3.5) [✓] Connected device (1 available) ! Doctor found issues in 1 category. 保證沒有紅色的叉。
- 啟動手機或者模擬器(Android系統大於16),開啟USB 調試模式,不同手機開啟方法略有不同,以華為手機為例:進入設置->系統->關於手機,快速連續點擊版本號5次,提示打開開發者模式,返回設置,此時會出現開發人員選項菜單,進入,打開開發人員選項和USB 調試,彈出授權菜單,同意即可。
- 打開Android Studio,查看連接的手機:
- 如果依然無法連接手機,打開Android Studio設置界面: 選擇最近的API。
- 到此基本就可以解決了,如果還無法連接,那基本就是adb的問題,很可能是adb端口被佔用,關於adb的解決方案可百度,引起adb問題有很多種情況。
創建Toast提示
在Material Design設計規範中Snackbars就是Toast提示,Snackbar用法如下:
<code>Scaffold.of(context).showSnackBar(SnackBar( content: Text("Sending Message"), ));/<code>
這個效果在國內來不是很接受,所以一般使用第三方插件fluttertoast
<code>Fluttertoast.showToast( msg: "This is Toast messaget", toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.CENTER, timeInSecForIos: 1 );/<code>
創建一個圓角Button
創建圓角Button的方式有很多種,下面介紹幾種簡單的:
- 使用 FlatButton 和 RaisedButton shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(18.0), side: BorderSide(color: Colors.red) ),
- 使用ClipRRect ClipRRect( borderRadius: BorderRadius.circular(40), child: RaisedButton( onPressed: () {}, child: Text("Button"), ), )
- 使用ButtonTheme ButtonTheme( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), child: RaisedButton( onPressed: () {}, child: Text("Button"), ), )
添加啟動頁
Flutter應用程序啟動時會出現一段時間的白屏,因為程序要啟動引擎,所以App第一次啟動比較慢,在原生端會顯示一段時間的白色啟動頁,我們把這個白色啟動頁做為應用程序的啟動頁,替換為自己的圖片,此方案的啟動頁只能是一張圖片,無法交互,如果需要啟動頁有交互效果建議使用Flutter做。
Android端替換啟動頁圖片,打開android/app/src/main/res/drawable/launch_background.xml文件,效果如下:
<code> /<code>
修改為:
<code> /<code>
將splash.png圖片拷貝到drawable文件夾下。
iOS端,打開ios/Runner/Assets.xcassets/LaunchImage.imageset下面的3張LaunchImage.png圖片替換,保持名稱不變。
修改應用程序的包名/BundleIdentifier
Android平臺上打開android/app/build.gradle:
<code>defaultConfig { applicationId "com.example.fluttersample" minSdkVersion 16 targetSdkVersion 28 versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" }/<code>
修改applicationId屬性即可。
iOS平臺打開ios/Runner/Info.plist,修改CFBundleIdentifier的值:
<code>CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER)/<code>
如何給一個控件添加邊框
<code>new Container( margin: const EdgeInsets.all(15.0), padding: const EdgeInsets.all(3.0), decoration: BoxDecoration( border: Border.all(color: Colors.blueAccent) ), child: Text("My Awesome Border"), )/<code>
讓Button充滿父組件
<code>SizedBox.expand( child: RaisedButton(...), )/<code>
或者
<code>SizedBox( width: double.infinity, // height: double.infinity, child: RaisedButton(...), )/<code>
或者
<code>ConstrainedBox( constraints: const BoxConstraints(minWidth: double.infinity), child: RaisedButton(...), )/<code>
或者
<code>ButtonTheme( minWidth: double.infinity, child: MaterialButton( onPressed: () {}, child: Text('Raised Button'), ), ),/<code>
如何在Column中添加ListView
給ListView指定高度:
<code>Column( children: [ Container( height: 50, child: ListView(), ) ], )/<code>
或者鋪滿Column:
<code>Column( children: [ Expanded( child: horizontalList, ) ], );/<code>
如何給圖片添加圓角
<code>ClipRRect( borderRadius: BorderRadius.circular(8.0), child: Image.network( '', ), )/<code>
或者
<code>CircleAvatar( radius: 20, backgroundImage: NetworkImage('https://via.placeholder.com/140x100') )/<code>
或者
<code>ClipOval( child: Image.network( "image_url", height: 100, width: 100, fit: BoxFit.cover, ), ),/<code>
或者
<code>Container( width: 100.0, height: 150.0, decoration: BoxDecoration( image: DecorationImage( fit: BoxFit.cover, image: NetworkImage('Path to your image') ), borderRadius: BorderRadius.all(Radius.circular(8.0)), color: Colors.redAccent, ),/<code>
如何去掉TextField的下劃線
<code>InputDecoration( border: InputBorder.none, hintText: 'Username', ), ),/<code>
如果防止UI隨著手機的旋轉而在橫豎屏間切換
設置支持的方向:
<code>class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); return new MaterialApp(...); } }/<code>
打開ios/Runner/Info.plist,設置支持的方向:
<code> UIInterfaceOrientationPortrait /<code>
顯示/隱藏控件
使用Opacity
<code>Opacity( opacity: .0, child: , )/<code>
或者
<code>Visibility( visible: false, child: , )/<code>
或者
<code>Offstage( offstage: true, child: , )/<code>
如何截取Android的返回按鍵並處理
使用WillPopScope
<code>@override Widget build(BuildContext context) { return new WillPopScope( onWillPop: () async => false, child: new Scaffold( appBar: new AppBar( title: new Text("data"), leading: new IconButton( icon: new Icon(Icons.ac_unit), onPressed: () => Navigator.of(context).pop(), ), ), ), ); }/<code>
如何設置RaisedButton控件的width
<code>ButtonTheme( minWidth: 200.0, height: 100.0, child: RaisedButton( onPressed: () {}, child: Text("test"), ), );/<code>
或者
<code>SizedBox( width: 100, // specific value child: RaisedButton(...) )/<code>
設置AppBar的height
使用PreferredSize:
<code>class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Example', home: Scaffold( appBar: PreferredSize( preferredSize: Size.fromHeight(50.0), // here the desired height child: AppBar( // ... ) ), body: // ... ) ); } }/<code>
如何格式化時間
Dart API本身沒有格式化時間的接口,使用intl:
<code>import 'package:intl/intl.dart'; DateTime now = DateTime.now(); String formattedDate = DateFormat('yyyy-MM-dd – kk:mm').format(now);/<code>
通過List繪製一組控件
<code>Widget getTextWidgets(List strings) { List list = new List(); for(var i = 0; i < strings.length; i++){ list.add(new Text(strings[i])); } return new Row(children: list); }/<code>
或者
<code>Row(children: strings.map((item) => new Text(item)).toList())/<code>
或者
<code>var list = ["one", "two", "three", "four"]; child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ for(var item in list ) Text(item) ], ), /<code>
如何設置GridView中組件的height
使用childAspectRatio,設置如下:
<code>class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => new _MyHomePageState(); } class _MyHomePageState extends State { List widgetList = ['A', 'B', 'C']; @override Widget build(BuildContext context) { var size = MediaQuery.of(context).size; /*24 is for notification bar on Android*/ final double itemHeight = (size.height - kToolbarHeight - 24) / 2; final double itemWidth = size.width / 2; return new Scaffold( appBar: new AppBar( title: new Text(widget.title), ), body: new Container( child: new GridView.count( crossAxisCount: 2, childAspectRatio: (itemWidth / itemHeight), controller: new ScrollController(keepScrollOffset: false), shrinkWrap: true, scrollDirection: Axis.vertical, children: widgetList.map((String value) { return new Container( color: Colors.green, margin: new EdgeInsets.all(1.0), child: new Center( child: new Text( value, style: new TextStyle( fontSize: 50.0, color: Colors.white, ), ), ), ); }).toList(), ), ), ); } }/<code>
如何修改狀態條顏色
使用flutter_statusbarcolor
<code>import 'package:flutter_statusbarcolor/flutter_statusbarcolor.dart'; void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { FlutterStatusbarcolor.setStatusBarColor(Colors.white); return MaterialApp( title: app_title, theme: ThemeData( primarySwatch: Colors.blue, ), home: HomePage(title: home_title), ); } }/<code>
或者
<code>SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle( statusBarColor: Colors.white ));/<code>
Column的子控件底部居中,左對齊
<code>return Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.end, children: [ //your elements here ], );/<code>
交流
老孟Flutter博客地址(近200個控件用法):http://laomengit.com
歡迎加入Flutter交流群(微信:laomengit)、關注公眾號【老孟Flutter】