老孟導讀:一個月前分享的《超過百萬的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用法如下:
Scaffold.of(context).showSnackBar(SnackBar(
content: Text("Sending Message"),
));
複製程式碼
這個效果在國內來不是很接受,所以一般使用第三方外掛fluttertoast
Fluttertoast.showToast(
msg: "This is Toast messaget",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIos: 1
);
複製程式碼
建立一個圓角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檔案,效果如下:
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
複製程式碼
修改為:
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap
android:gravity="center"
android:src="@drawable/splash" />
</item>
</layer-list>
複製程式碼
將splash.png
圖片拷貝到drawable資料夾下。
iOS端,開啟ios/Runner/Assets.xcassets/LaunchImage.imageset下面的3張LaunchImage.png圖片替換,保持名稱不變。
修改應用程式的包名/BundleIdentifier
Android平臺上開啟android/app/build.gradle:
defaultConfig {
applicationId "com.example.fluttersample"
minSdkVersion 16
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
複製程式碼
修改applicationId屬性即可。
iOS平臺開啟ios/Runner/Info.plist,修改CFBundleIdentifier的值:
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
複製程式碼
如何給一個控制元件新增邊框
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"),
)
複製程式碼
讓Button充滿父元件
SizedBox.expand(
child: RaisedButton(...),
)
複製程式碼
或者
SizedBox(
width: double.infinity,
// height: double.infinity,
child: RaisedButton(...),
)
複製程式碼
或者
ConstrainedBox(
constraints: const BoxConstraints(minWidth: double.infinity),
child: RaisedButton(...),
)
複製程式碼
或者
ButtonTheme(
minWidth: double.infinity,
child: MaterialButton(
onPressed: () {},
child: Text('Raised Button'),
),
),
複製程式碼
如何在Column中新增ListView
給ListView指定高度:
Column(
children: <Widget>[
Container(
height: 50,
child: ListView(),
)
],
)
複製程式碼
或者鋪滿Column:
Column(
children: <Widget>[
Expanded(
child: horizontalList,
)
],
);
複製程式碼
如何給圖片新增圓角
ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image.network(
'',
),
)
複製程式碼
或者
CircleAvatar(
radius: 20,
backgroundImage: NetworkImage('https://via.placeholder.com/140x100')
)
複製程式碼
或者
ClipOval(
child: Image.network(
"image_url",
height: 100,
width: 100,
fit: BoxFit.cover,
),
),
複製程式碼
或者
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,
),
複製程式碼
如何去掉TextField的下劃線
InputDecoration(
border: InputBorder.none,
hintText: 'Username',
),
),
複製程式碼
如果防止UI隨著手機的旋轉而在橫豎屏間切換
設定支援的方向:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
return new MaterialApp(...);
}
}
複製程式碼
開啟ios/Runner/Info.plist,設定支援的方向:
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
複製程式碼
顯示/隱藏控制元件
使用Opacity
Opacity(
opacity: .0,
child: ,
)
複製程式碼
或者
Visibility(
visible: false,
child: ,
)
複製程式碼
或者
Offstage(
offstage: true,
child: ,
)
複製程式碼
如何擷取Android的返回按鍵並處理
@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(),
),
),
),
);
}
複製程式碼
如何設定RaisedButton控制元件的width
ButtonTheme(
minWidth: 200.0,
height: 100.0,
child: RaisedButton(
onPressed: () {},
child: Text("test"),
),
);
複製程式碼
或者
SizedBox(
width: 100, // specific value
child: RaisedButton(...)
)
複製程式碼
設定AppBar的height
使用PreferredSize:
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: // ...
)
);
}
}
複製程式碼
如何格式化時間
Dart API本身沒有格式化時間的介面,使用intl:
import 'package:intl/intl.dart';
DateTime now = DateTime.now();
String formattedDate = DateFormat('yyyy-MM-dd – kk:mm').format(now);
複製程式碼
通過List繪製一組控制元件
Widget getTextWidgets(List<String> strings)
{
List<Widget> list = new List<Widget>();
for(var i = 0; i < strings.length; i++){
list.add(new Text(strings[i]));
}
return new Row(children: list);
}
複製程式碼
或者
Row(children: strings.map((item) => new Text(item)).toList())
複製程式碼
或者
var list = ["one", "two", "three", "four"];
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
for(var item in list ) Text(item)
],
),
複製程式碼
如何設定GridView中元件的height
使用childAspectRatio,設定如下:
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> 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(),
),
),
);
}
}
複製程式碼
如何修改狀態條顏色
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),
);
}
}
複製程式碼
或者
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Colors.white
));
複製程式碼
Column的子控制元件底部居中,左對齊
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
//your elements here
],
);
複製程式碼
交流
老孟Flutter部落格地址(近200個控制元件用法):laomengit.com
歡迎加入Flutter交流群(微信:laomengit)、關注公眾號【老孟Flutter】: