超過百萬的StackOverflow Flutter 問題-第二期

超過百萬的StackOverflow Flutter 問題-第二期

老孟導讀:一個月前分享的《超過百萬的StackOverflow Flutter 問題-第一期》受到很多朋友的喜歡,非常感謝大家的支持,在文章末尾有第一期的鏈接,希望此文能對你有所幫助。

No connected devices

這個問題估計大部分都遇到過,解決方法如下:

  1. 執行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. 保證沒有紅色的叉。
  2. 啟動手機或者模擬器(Android系統大於16),開啟USB 調試模式,不同手機開啟方法略有不同,以華為手機為例:進入設置->系統->關於手機,快速連續點擊版本號5次,提示打開開發者模式,返回設置,此時會出現開發人員選項菜單,進入,打開開發人員選項和USB 調試,彈出授權菜單,同意即可。
  3. 打開Android Studio,查看連接的手機:
  4. 如果依然無法連接手機,打開Android Studio設置界面: 選擇最近的API。
  5. 到此基本就可以解決了,如果還無法連接,那基本就是adb的問題,很可能是adb端口被佔用,關於adb的解決方案可百度,引起adb問題有很多種情況。

創建Toast提示

Material Design設計規範中Snackbars就是Toast提示,Snackbar用法如下:

<code>Scaffold.of(context).showSnackBar(SnackBar(
      content: Text("Sending Message"),
    ));/<code>
超過百萬的StackOverflow Flutter 問題-第二期

這個效果在國內來不是很接受,所以一般使用第三方插件fluttertoast

<code>Fluttertoast.showToast(
        msg: "This is Toast messaget",
        toastLength: Toast.LENGTH_SHORT,
        gravity: ToastGravity.CENTER,
        timeInSecForIos: 1
    );/<code>
超過百萬的StackOverflow Flutter 問題-第二期

創建一個圓角Button

創建圓角Button的方式有很多種,下面介紹幾種簡單的:

  1. 使用 FlatButton 和 RaisedButton shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(18.0), side: BorderSide(color: Colors.red) ),
  2. 使用ClipRRect ClipRRect( borderRadius: BorderRadius.circular(40), child: RaisedButton( onPressed: () {}, child: Text("Button"), ), )
  3. 使用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>
超過百萬的StackOverflow Flutter 問題-第二期

讓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】


分享到:


相關文章: