Flutter 你須要知道的那些事 01

公衆號「AndroidTraveler」首發。git

1. width 屬性

對於設置控件寬度填充父控件這件事情,在 Android 裏面,只須要設置 MATCH_PARENT 便可。github

可是在 Flutter 裏面卻不是這樣,由於 Flutter 要具體的數值。api

因此咱們能夠這樣考慮,假設我這個值很是大,比全部市面上的設備寬度還要大,那麼是否是表現出來就是充滿父控件了。bash

因此這邊的作法是設置爲無限,即 double.infiniteapp

咱們以一個經常使用場景來講明。less

好比設置圖片填充屏幕寬度。ide

剛開始沒有設置的代碼以下:測試

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
          appBar: AppBar(
            title: Text('My Flutter'),
          ),
          body: Center(
            child: Image.asset('assets/images/example.jpeg'),
          ),
        )
    );
  }
}
複製代碼

效果:ui

能夠看到沒有設置的狀況下,顯示會根據圖片自身的寬高顯示。this

這個時候若是設置 width 爲無窮大,修改代碼以下:

child: Image.asset('assets/images/example.jpeg', width: double.infinity,),
複製代碼

效果

什麼狀況,沒起做用?

這個時候不要慌,咱們來給你們分析分析。

之後你們遇到相似問題也能夠這樣分析。

咱們經過給 Image 外面套上一層 Container,而後設置背景顏色來對比一下。

代碼以下:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      appBar: AppBar(
        title: Text('My Flutter'),
      ),
      body: Center(
        child: Container(
          color: Colors.blue,
          //left
//          child: Image.asset('assets/images/example.jpeg',),
          //right
          child: Image.asset('assets/images/example.jpeg', width: double.infinity,),
        ),
      ),
    ));
  }
}
複製代碼

效果以下:

能夠看到,設置寬度以後,Image 確實是填充了寬度,只不過因爲圖片自己沒有那麼寬,所以看起來就覺得是沒有起做用。

那麼如何讓圖片能夠填充寬度呢?

這個就涉及到圖片的填充模式了。

2. fit 屬性

點擊 Image 的 fit 屬性進入源碼能夠看到以下:

/// How to inscribe the image into the space allocated during layout.
///
/// The default varies based on the other fields. See the discussion at
/// [paintImage].
final BoxFit fit;
複製代碼

咱們再點一下 BoxFit,能夠看到以下:

/// How a box should be inscribed into another box.
///
/// See also [applyBoxFit], which applies the sizing semantics of these values
/// (though not the alignment semantics).
enum BoxFit {
  /// Fill the target box by distorting the source's aspect ratio. /// /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_fill.png) fill, /// As large as possible while still containing the source entirely within the /// target box. /// /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_contain.png) contain, /// As small as possible while still covering the entire target box. /// /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_cover.png) cover, /// Make sure the full width of the source is shown, regardless of /// whether this means the source overflows the target box vertically. /// /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_fitWidth.png) fitWidth, /// Make sure the full height of the source is shown, regardless of /// whether this means the source overflows the target box horizontally. /// /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_fitHeight.png) fitHeight, /// Align the source within the target box (by default, centering) and discard /// any portions of the source that lie outside the box. /// /// The source image is not resized. /// /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_none.png) none, /// Align the source within the target box (by default, centering) and, if /// necessary, scale the source down to ensure that the source fits within the /// box. /// /// This is the same as `contain` if that would shrink the image, otherwise it /// is the same as `none`. /// /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_scaleDown.png) scaleDown, } 複製代碼

相信你們看到源碼的註釋應該很清楚每一個值的意義了。

若是你還不清楚,能夠點擊註釋裏面對應的連接去查看示意圖。

好比以咱們這個實際應用場景填充寬度爲例,那麼咱們能夠看到 fitWidth 應該是符合咱們要求的,咱們點擊註釋的連接,跳轉能夠看到圖片以下:

很形象的作了幾種狀況的示意。咱們設置了 Image 的 fit 屬性以下:

child: Image.asset('assets/images/example.jpeg', width: double.infinity, fit: BoxFit.fitWidth,),
複製代碼

效果:

能夠看到已經知足咱們的需求了。

舒適提示:測試完以後不要忘記去掉測試的 Container 以及對應顏色哦~

3. print

咱們知道在 Android 裏面,當咱們 try catch 以後,咱們打印異常基本會寫出相似下面代碼:

Log.e(TAG, "exception="+e);
複製代碼

在 Flutter 也有異常捕獲。

你可能會習慣的寫出以下代碼:

print('exception='+e);
複製代碼

可是切記,不要使用上面的寫法。

由於當 e 爲 null 時,上面的 print 不會執行打印。

這可能會誤導你。由於你在成功的時候加上打印語句,異常捕獲也加上打印語句。可是程序就是沒有打印。你就會以爲很奇怪。

實際上當 e 爲 null 時,print 語句會報錯,+ 號鏈接的左右不能是 null,因此不會正常打印。所以請避免上面的寫法。能夠用下面的替換寫法:

//替換寫法一
print('exception=');
print(e);
//替換寫法二
print('exception='+(e ?? ''));
//替換寫法三
var printContent = e ?? '';
print('exception='+printContent);
複製代碼

4. GestureDetector

咱們知道若是要給一個 Widget 增長點擊事件,最簡單的方法就是套一層 GestureDetector。

可是有時候你這樣作了,卻發現有些「隱患」,或者說,有些你意料不到的事情。

這裏用一個場景來告訴你,你平時可能沒有發現的細節。

微博裏面有點贊這個小組件,咱們寫下以下代碼:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      appBar: AppBar(
        title: Text('My Flutter'),
      ),
      body: Row(
        children: <Widget>[
          Image.asset('assets/images/2.0x/like.png', width: 20, height: 20,),
          SizedBox(width: 5,),
          Text('30')
        ],
      ),
    ));
  }
}
複製代碼

效果以下:

假設咱們要求給這個點贊組件加上點擊事件,那麼咱們直接給 Row 套上 GestureDetector Widget。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      appBar: AppBar(
        title: Text('My Flutter'),
      ),
      body: GestureDetector(
        onTap: (){
          print('onTap');
        },
        child: Row(
          children: <Widget>[
            Image.asset('assets/images/2.0x/like.png', width: 20, height: 20,),
            SizedBox(width: 5,),
            Text('30')
          ],
        ),
      ),
    ));
  }
}
複製代碼

點擊點贊組件確實會打印 onTap,可是若是你點擊了點贊圖標和數字中間的白色區域,你會發現點擊事件沒有回調,沒有打印。

這個時候有兩種解決方法:

1. 給空白組件設置 color 屬性,顏色值設置透明

對於 Container 設置的 padding 能夠直接設置,對於咱們這裏例子的 SizeBox 須要改成以下:

SizedBox(width: 15, child: Container(color: Colors.transparent,),),
複製代碼

爲了方便測試,這邊將寬度改成 15。

因此對於設置 GestureDetector 的 Container,若是沒有設置 color 屬性,那麼點擊空白不會回調。

2. 設置 GestureDetector 的 behavior 屬性(推薦方式)

其實若是你須要空白區域也響應點擊,只須要設置一下 GestureDetector 的 behavior 屬性便可。

behavior 默認值爲 HitTestBehavior.deferToChild,咱們這裏將其設置爲 HitTestBehavior.translucent

代碼以下:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      appBar: AppBar(
        title: Text('My Flutter'),
      ),
      body: GestureDetector(
        behavior: HitTestBehavior.translucent,
        onTap: (){
          print('onTap');
        },
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Image.asset('assets/images/2.0x/like.png', width: 20, height: 20,),
            SizedBox(width: 15),
            Text('30')
          ],
        ),
      ),
    ));
  }
}
複製代碼

這裏的點贊圖片我直接從網上獲取的,你測試能夠用隨便一張圖片代替驗證。或者用兩個文原本驗證也是能夠的。

相關文章
相關標籤/搜索