天天看點

Flutter 61: 圖解基本 Button 按鈕小結 (一)

      Button 在日常中是必不可少的,小菜嘗試過不同類型的 Button,也根據需求自定義過,今天小菜系統的學習一下最基本的 Button;

      Flutter 中沒有 Button Widget,但提供了很多不同類型的 Child Button Widget;小菜分析源碼整體可分為 RawMaterialButton 和 IconButton 兩類;

      其中 RaisedButton / FlatButton / OutlineButton 繼承自 MaterialButton 且 MaterialButton 是對 RawMaterialButton 的封裝;而BackButton / CloseButton / PopupMenuButton 繼承自 IconButton;最終 RawMaterialButton 和 IconButton 都是由 ConstrainedBox 填充繪制;

Flutter 61: 圖解基本 Button 按鈕小結 (一)

IconButton 系列

      IconButton 系列屬于圖示按鈕,使用相對簡單;其核心是 InkResponse 水波紋效果;

IconButton

源碼分析
const IconButton({
    Key key,
    this.iconSize = 24.0,   // 圖示大小
    this.padding = const EdgeInsets.all(8.0),   // 圖示周圍間距
    this.alignment = Alignment.center,          // 圖示位置
    @required this.icon,    // 圖示資源
    this.color,             // 圖示顔色
    this.highlightColor,    // 點選高亮顔色
    this.splashColor,       // 水波紋顔色
    this.disabledColor,     // 不可點選時高亮顔色
    @required this.onPressed,
    this.tooltip            // 長按提示
})           

      分析源碼,其中 icon 和 onPressed 是必須要設定的,其餘屬性根據需求而适當調整;

案例嘗試
  1. 小菜首先嘗試最基本的 IconButton;長按會由 tooltip 提醒,點選為預設主題色;
IconButton(icon: Icon(Icons.android), tooltip: 'IconButton tootip1',
    onPressed: () => Toast.show('IconButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM));           
  1. 小菜嘗試其中幾個屬性;其中 icon 顔色為 cyan,點選高亮背景色為 deepPurple,水波紋顔色為 redAccent;注意當 icon 自身設定顔色時 color 屬性不生效;
IconButton(icon: Icon(Icons.android), tooltip: 'IconButton tootip2',
    color: Colors.cyan,
    highlightColor: Colors.deepPurple.withOpacity(0.4),
    splashColor: Colors.redAccent,
    onPressed: () => Toast.show('IconButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM));           
  1. 小菜嘗試不可點選時,icon 顔色為 disabledColor 設定的 green;同樣若 icon 本身設定了顔色,disabledColor 不生效;注意:onPressed: null 與 onPressed: ()=> null 不同,前者代表無點選事件;後者代表有點選事件,隻是點選無操作;
IconButton(icon: Icon(Icons.android), disabledColor: Colors.green, onPressed: null);           
  1. icon 為 Widget 采用 Icon / Image / ImageIcon 等均可;
IconButton(icon: Image.asset('images/ic_launcher.png'), iconSize: 40.0, onPressed: null);           
Flutter 61: 圖解基本 Button 按鈕小結 (一)

BackButton

      BackButton 作用非常明确,一般用作傳回上一個頁面;

const BackButton({ Key key, this.color })           

      分析源碼,BackButton 繼承自 IconButton,隻允許設定圖示顔色,圖示樣式 Android 與 iOS 不同且不可修改;點選時會優先判斷 maybePop 是否可以傳回上一頁;

BackButton();
BackButton(color: Colors.green);           

CloseButton

      CloseButton 一般用作導航欄關閉按鈕與 BackButton 類似;

const CloseButton({ Key key }) : super(key: key);           

      分析源碼,CloseButton 繼承自 IconButton,無需設定任何屬性;點選時會優先判斷 maybePop 是否可以傳回上一頁;

CloseButton();           
Flutter 61: 圖解基本 Button 按鈕小結 (一)

RawMaterialButton 系列

RawMaterialButton

      RawMaterialButton 是 MaterialButton 的基礎,核心是由 Material 和 InkWell 等組成;但不可用目前 Theme 或 ButtonTheme 來計算未指定參數的預設值;

const RawMaterialButton({
    Key key,
    @required this.onPressed,
    this.onHighlightChanged,            // 高亮變化的回調
    this.textStyle,                     // 文字屬性
    this.fillColor,                     // 填充顔色
    this.highlightColor,                // 背景高亮顔色
    this.splashColor,                   // 水波紋顔色
    this.elevation = 2.0,               // 陰影
    this.highlightElevation = 8.0,      // 高亮時陰影
    this.disabledElevation = 0.0,       // 不可點選時陰影
    this.padding = EdgeInsets.zero,     // 内容周圍邊距
    this.constraints = const BoxConstraints(minWidth: 88.0, minHeight: 36.0),   // 預設按鈕尺寸
    this.shape = const RoundedRectangleBorder(),    // 形狀樣式
    this.animationDuration = kThemeChangeDuration,  // 動畫效果持續時長
    this.clipBehavior = Clip.none,                  // 抗鋸齒剪切效果
    MaterialTapTargetSize materialTapTargetSize,    // 點選目标的最小尺寸
    this.child,
})           

      分析源碼可知,RawMaterialButton 沒有設定寬高的屬性,可根據 padding 或外層依賴 Container 适當調整位置和大小;預設最小尺寸為 88px * 36px;

      小菜定義了一個基本的按鈕,并監聽其高亮改變時狀态,與我們常見的按鈕基本一緻;

RawMaterialButton(
    padding: EdgeInsets.all(20.0),
    child: Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
      Padding(child: Icon(Icons.android), padding: EdgeInsets.only(right: 10.0)),
      Text('RawMaterialButton', style: TextStyle(color: Colors.brown))
    ]),
    textStyle: TextStyle(color: Colors.pink, fontSize: 18.0),
    fillColor: Colors.greenAccent.withOpacity(0.4),
    highlightColor: Colors.cyan,
    splashColor: Colors.deepPurple.withOpacity(0.4),
    onPressed: () => Toast.show('RawMaterialButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM),
    onHighlightChanged: (state) => Toast.show('onHighlightChanged -> $state', context, duration: Toast.LENGTH_SHORT, gravity: Toast.CENTER))           
Flutter 61: 圖解基本 Button 按鈕小結 (一)

FloatingActionButton

      FloatingActionButton 是 RawMaterialButton 的封裝,主要用于浮動在螢幕内容之上,一般是位于底部左右角或中間;一般一個頁面隻有一個;

const FloatingActionButton({
    Key key,
    this.child,
    this.tooltip,                           // 長按提醒
    this.foregroundColor,                   // 按鈕上子元素顔色
    this.backgroundColor,                   // 背景色
    this.heroTag = const _DefaultHeroTag(), // Hero 動畫标簽
    this.elevation = 6.0,                   // 陰影
    this.highlightElevation = 12.0,         // 高亮時陰影
    @required this.onPressed,
    this.mini = false,                      // 尺寸大小,分為 mini 和 default
    this.shape = const CircleBorder(),      // 樣式形狀
    this.clipBehavior = Clip.none,          // 抗鋸齒剪切效果
    this.materialTapTargetSize,             // 點選目标的最小尺寸
    this.isExtended = false,                // 是否采用 .extended 方式
})           
  1. 小菜嘗試一個基本的 FloatingActionButton;長按會有 tooltip 提示;
floatingActionButton: FloatingActionButton(child: Icon(Icons.android), tooltip: 'FloatingActionButton ToolTip',
    onPressed: () => Toast.show('FloatingActionButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM));           
Flutter 61: 圖解基本 Button 按鈕小結 (一)
  1. foregroundColor 為按鈕上層子元素顔色,若子元素本身設定顔色則不生效;backgroundColor 為按鈕背景色;
foregroundColor: Colors.redAccent.withOpacity(0.7),
backgroundColor: Colors.green.withOpacity(0.4),           
Flutter 61: 圖解基本 Button 按鈕小結 (一)
  1. elevation 按鈕預設陰影高度,即 z軸高度;highlightElevation 為點選高亮時陰影高度;
elevation: 0.0,
highlightElevation: 10.0,           
Flutter 61: 圖解基本 Button 按鈕小結 (一)
  1. mini 是否展示成小尺寸模式;materialTapTargetSize 為配置目标的最小點選尺寸,padded 為預設的 48px * 48px 為 Android 推薦尺寸;shrinkWrap 為縮小到 Material 提供的最小尺寸;
mini: true,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,           
Flutter 61: 圖解基本 Button 按鈕小結 (一)
  1. shape 為樣式尺寸;clipBehavior 為抗鋸齒效果;
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(14.0))),
clipBehavior: Clip.antiAlias,           
Flutter 61: 圖解基本 Button 按鈕小結 (一)
  1. heroTag 動畫标簽,預設的是 FloatingActionButtonAnimator.scaling;且 heroTag 預設是相同的,可以自定義為唯一标簽;小菜設定上一頁面與目前頁面 FloatingActionButton 的 heroTag 相同;
floatingActionButtonAnimator: MyAnimation(),

heroTag: "aceTag",

class MyAnimation extends FloatingActionButtonAnimator {
  double _x, _y;

  @override
  Offset getOffset({Offset begin, Offset end, double progress}) {
    _x = begin.dx + (end.dx - begin.dx) * progress;
    _y = begin.dy + (end.dy - begin.dy) * progress;
    return Offset(_x * 0.5, _y * 0.9);
  }

  @override
  Animation<double> getRotationAnimation({Animation<double> parent}) {
    return Tween<double>(begin: 1.0, end: 1.0).animate(parent);
  }

  @override
  Animation<double> getScaleAnimation({Animation<double> parent}) {
    return Tween<double>(begin: 1.0, end: 1.0).animate(parent);
  }
}           
Flutter 61: 圖解基本 Button 按鈕小結 (一)
  1. FloatingActionButton 提供了 .extended 方式建立代表标簽樣式的,非正方形的按鈕樣式;其餘屬性無差;
floatingActionButton: FloatingActionButton.extended(
    onPressed: () => Toast.show('FloatingActionButton.extended', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM),
    icon: Icon(Icons.android),
    label: Text('Android'));           
Flutter 61: 圖解基本 Button 按鈕小結 (一)
  1. 針對特殊的個性化,FloatingActionButton 展示的大小可能會有所不同;小菜嘗試了幾種方式;
  2. 通過最基本的 RawMaterialButton 實作 FloatingActionButton 樣式,外層添加 Container 限制大小;小菜比較推薦方式一,靈活性更高;
// 方式一
floatingActionButton: Container(
    width: 100.0, height: 100.0,
    color: Colors.greenAccent.withOpacity(0.4),
    child: RawMaterialButton(
        shape: CircleBorder(),
        elevation: 0.0,
        child: Icon(Icons.android),
        onPressed: () {}))           
Flutter 61: 圖解基本 Button 按鈕小結 (一)
  1. 借助 FittedBox 将按鈕整體放大到 Container 限制範圍内;
// 方式二
floatingActionButton: Container(
    width: 100.0, height: 100.0,
    child: FittedBox(
        child: FloatingActionButton(child: Icon(Icons.android), onPressed: () {})))           
Flutter 61: 圖解基本 Button 按鈕小結 (一)
  1. SizeBox 與 FittedBox 限制方式不同,隻是整體範圍變大,其内部按鈕按 Material 建議樣式展示;
// 方式三
floatingActionButton: SizedBox(
    width: 100.0, height: 100.0,
    child: FloatingActionButton(child: Icon(Icons.android), onPressed: () {}))           
Flutter 61: 圖解基本 Button 按鈕小結 (一)
  1. scale 與 FittedBox 類似,按比例縮放;
// 方式四
floatingActionButton: Transform.scale(
    scale: 1.5,
    child: FloatingActionButton(child: Icon(Icons.android), onPressed: () {}))           
Flutter 61: 圖解基本 Button 按鈕小結 (一)

      Button 涉及的内容較多,擴充性很強,小菜分兩節進行學習嘗試;有些了解可能還不到位,有問題請多多指導!

來源: 阿策小和尚

繼續閱讀