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

??????Button 在日常中是必不可少的,小菜嘗試過不同類型的 Button杂数,也根據(jù)需求自定義過,今天小菜系統(tǒng)的學(xué)習(xí)一下最基本的 Button卧惜;

??????Flutter 中沒有 Button Widget心褐,但提供了很多不同類型的 Child Button Widget肆糕;小菜分析源碼整體可分為 RawMaterialButtonIconButton 兩類藻懒;

??????其中 RaisedButton / FlatButton / OutlineButton 繼承自 MaterialButtonMaterialButton 是對(duì) RawMaterialButton 的封裝却邓;而BackButton / CloseButton / PopupMenuButton 繼承自 IconButton镀琉;最終 RawMaterialButtonIconButton 都是由 ConstrainedBox 填充繪制峦嗤;

IconButton 系列

??????IconButton 系列屬于圖標(biāo)按鈕,使用相對(duì)簡單屋摔;其核心是 InkResponse 水波紋效果烁设;

IconButton

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

??????分析源碼,其中 icononPressed 是必須要設(shè)置的钓试,其余屬性根據(jù)需求而適當(dāng)調(diào)整署尤;

案例嘗試
  1. 小菜首先嘗試最基本的 IconButton;長按會(huì)由 tooltip 提醒亚侠,點(diǎn)擊為默認(rèn)主題色曹体;
IconButton(icon: Icon(Icons.android), tooltip: 'IconButton tootip1',
    onPressed: () => Toast.show('IconButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM));
  1. 小菜嘗試其中幾個(gè)屬性;其中 icon 顏色為 cyan硝烂,點(diǎn)擊高亮背景色為 deepPurple箕别,水波紋顏色為 redAccent;注意當(dāng) icon 自身設(shè)置顏色時(shí) 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. 小菜嘗試不可點(diǎn)擊時(shí)串稀,icon 顏色為 disabledColor 設(shè)置的 green;同樣若 icon 本身設(shè)置了顏色狮杨,disabledColor 不生效母截;注意:onPressed: nullonPressed: ()=> null 不同,前者代表無點(diǎn)擊事件橄教;后者代表有點(diǎn)擊事件清寇,只是點(diǎn)擊無操作喘漏;
IconButton(icon: Icon(Icons.android), disabledColor: Colors.green, onPressed: null);
  1. iconWidget 采用 Icon / Image / ImageIcon 等均可;
IconButton(icon: Image.asset('images/ic_launcher.png'), iconSize: 40.0, onPressed: null);

BackButton

??????BackButton 作用非常明確华烟,一般用作返回上一個(gè)頁面翩迈;

源碼分析
const BackButton({ Key key, this.color })

??????分析源碼,BackButton 繼承自 IconButton盔夜,只允許設(shè)置圖標(biāo)顏色负饲,圖標(biāo)樣式 AndroidiOS 不同且不可修改;點(diǎn)擊時(shí)會(huì)優(yōu)先判斷 maybePop 是否可以返回上一頁喂链;

案例嘗試
BackButton();
BackButton(color: Colors.green);

CloseButton

??????CloseButton 一般用作導(dǎo)航欄關(guān)閉按鈕與 BackButton 類似返十;

源碼分析
const CloseButton({ Key key }) : super(key: key);

??????分析源碼,CloseButton 繼承自 IconButton椭微,無需設(shè)置任何屬性吧慢;點(diǎn)擊時(shí)會(huì)優(yōu)先判斷 maybePop 是否可以返回上一頁;

案例嘗試
CloseButton();

RawMaterialButton 系列

RawMaterialButton

??????RawMaterialButtonMaterialButton 的基礎(chǔ)赏表,核心是由 MaterialInkWell 等組成检诗;但不可用當(dāng)前 ThemeButtonTheme 來計(jì)算未指定參數(shù)的默認(rèn)值;

源碼分析
const RawMaterialButton({
    Key key,
    @required this.onPressed,
    this.onHighlightChanged,            // 高亮變化的回調(diào)
    this.textStyle,                     // 文字屬性
    this.fillColor,                     // 填充顏色
    this.highlightColor,                // 背景高亮顏色
    this.splashColor,                   // 水波紋顏色
    this.elevation = 2.0,               // 陰影
    this.highlightElevation = 8.0,      // 高亮?xí)r陰影
    this.disabledElevation = 0.0,       // 不可點(diǎn)擊時(shí)陰影
    this.padding = EdgeInsets.zero,     // 內(nèi)容周圍邊距
    this.constraints = const BoxConstraints(minWidth: 88.0, minHeight: 36.0),   // 默認(rèn)按鈕尺寸
    this.shape = const RoundedRectangleBorder(),    // 形狀樣式
    this.animationDuration = kThemeChangeDuration,  // 動(dòng)畫效果持續(xù)時(shí)長
    this.clipBehavior = Clip.none,                  // 抗鋸齒剪切效果
    MaterialTapTargetSize materialTapTargetSize,    // 點(diǎn)擊目標(biāo)的最小尺寸
    this.child,
})

??????分析源碼可知瓢剿,RawMaterialButton 沒有設(shè)置寬高的屬性逢慌,可根據(jù) padding 或外層依賴 Container 適當(dāng)調(diào)整位置和大小间狂;默認(rèn)最小尺寸為 88px * 36px攻泼;

案例嘗試

??????小菜定義了一個(gè)基本的按鈕,并監(jiān)聽其高亮改變時(shí)狀態(tài)鉴象,與我們常見的按鈕基本一致忙菠;

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))

FloatingActionButton

??????FloatingActionButtonRawMaterialButton 的封裝,主要用于浮動(dòng)在屏幕內(nèi)容之上纺弊,一般是位于底部左右角或中間牛欢;一般一個(gè)頁面只有一個(gè);

源碼分析
const FloatingActionButton({
    Key key,
    this.child,
    this.tooltip,                           // 長按提醒
    this.foregroundColor,                   // 按鈕上子元素顏色
    this.backgroundColor,                   // 背景色
    this.heroTag = const _DefaultHeroTag(), // Hero 動(dòng)畫標(biāo)簽
    this.elevation = 6.0,                   // 陰影
    this.highlightElevation = 12.0,         // 高亮?xí)r陰影
    @required this.onPressed,
    this.mini = false,                      // 尺寸大小淆游,分為 mini 和 default
    this.shape = const CircleBorder(),      // 樣式形狀
    this.clipBehavior = Clip.none,          // 抗鋸齒剪切效果
    this.materialTapTargetSize,             // 點(diǎn)擊目標(biāo)的最小尺寸
    this.isExtended = false,                // 是否采用 .extended 方式
})
案例嘗試
  1. 小菜嘗試一個(gè)基本的 FloatingActionButton傍睹;長按會(huì)有 tooltip 提示;
floatingActionButton: FloatingActionButton(child: Icon(Icons.android), tooltip: 'FloatingActionButton ToolTip',
    onPressed: () => Toast.show('FloatingActionButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM));
  1. foregroundColor 為按鈕上層子元素顏色犹菱,若子元素本身設(shè)置顏色則不生效拾稳;backgroundColor 為按鈕背景色;
foregroundColor: Colors.redAccent.withOpacity(0.7),
backgroundColor: Colors.green.withOpacity(0.4),
  1. elevation 按鈕默認(rèn)陰影高度腊脱,即 z軸高度访得;highlightElevation 為點(diǎn)擊高亮?xí)r陰影高度;
elevation: 0.0,
highlightElevation: 10.0,
  1. mini 是否展示成小尺寸模式陕凹;materialTapTargetSize 為配置目標(biāo)的最小點(diǎn)擊尺寸悍抑,padded 為默認(rèn)的 48px * 48pxAndroid 推薦尺寸鳄炉;shrinkWrap 為縮小到 Material 提供的最小尺寸;
mini: true,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
  1. shape 為樣式尺寸传趾;clipBehavior 為抗鋸齒效果;
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(14.0))),
clipBehavior: Clip.antiAlias,
  1. heroTag 動(dòng)畫標(biāo)簽泥技,默認(rèn)的是 FloatingActionButtonAnimator.scaling浆兰;且 heroTag 默認(rèn)是相同的,可以自定義為唯一標(biāo)簽珊豹;小菜設(shè)置上一頁面與當(dāng)前頁面 FloatingActionButtonheroTag 相同簸呈;
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);
  }
}
  1. FloatingActionButton 提供了 .extended 方式創(chuàng)建代表標(biāo)簽樣式的,非正方形的按鈕樣式店茶;其余屬性無差蜕便;
floatingActionButton: FloatingActionButton.extended(
    onPressed: () => Toast.show('FloatingActionButton.extended', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM),
    icon: Icon(Icons.android),
    label: Text('Android'));
  1. 針對(duì)特殊的個(gè)性化,FloatingActionButton 展示的大小可能會(huì)有所不同贩幻;小菜嘗試了幾種方式轿腺;
    a. 通過最基本的 RawMaterialButton 實(shí)現(xiàn) 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: () {}))

b. 借助 FittedBox 將按鈕整體放大到 Container 約束范圍內(nèi)仿荆;

// 方式二
floatingActionButton: Container(
    width: 100.0, height: 100.0,
    child: FittedBox(
        child: FloatingActionButton(child: Icon(Icons.android), onPressed: () {})))

c. SizeBoxFittedBox 約束方式不同,只是整體范圍變大坏平,其內(nèi)部按鈕按 Material 建議樣式展示拢操;

// 方式三
floatingActionButton: SizedBox(
    width: 100.0, height: 100.0,
    child: FloatingActionButton(child: Icon(Icons.android), onPressed: () {}))

d. scaleFittedBox 類似,按比例縮放舶替;

// 方式四
floatingActionButton: Transform.scale(
    scale: 1.5,
    child: FloatingActionButton(child: Icon(Icons.android), onPressed: () {}))

??????Button 涉及的內(nèi)容較多令境,擴(kuò)展性很強(qiáng),小菜分兩節(jié)進(jìn)行學(xué)習(xí)嘗試顾瞪;有些理解可能還不到位展父,有問題請(qǐng)多多指導(dǎo)!

來源: 阿策小和尚

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末玲昧,一起剝皮案震驚了整個(gè)濱河市栖茉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌孵延,老刑警劉巖吕漂,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異尘应,居然都是意外死亡惶凝,警方通過查閱死者的電腦和手機(jī)吼虎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苍鲜,“玉大人思灰,你說我怎么就攤上這事』焯希” “怎么了洒疚?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長坯屿。 經(jīng)常有香客問我油湖,道長,這世上最難降的妖魔是什么领跛? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任乏德,我火速辦了婚禮,結(jié)果婚禮上吠昭,老公的妹妹穿的比我還像新娘喊括。我一直安慰自己,他們只是感情好矢棚,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布瘾晃。 她就那樣靜靜地躺著,像睡著了一般幻妓。 火紅的嫁衣襯著肌膚如雪蹦误。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天肉津,我揣著相機(jī)與錄音强胰,去河邊找鬼。 笑死妹沙,一個(gè)胖子當(dāng)著我的面吹牛偶洋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播距糖,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼玄窝,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了悍引?” 一聲冷哼從身側(cè)響起恩脂,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎趣斤,沒想到半個(gè)月后俩块,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年玉凯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了势腮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡漫仆,死狀恐怖捎拯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情盲厌,我是刑警寧澤署照,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站狸眼,受9級(jí)特大地震影響藤树,放射性物質(zhì)發(fā)生泄漏浴滴。R本人自食惡果不足惜拓萌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望升略。 院中可真熱鬧微王,春花似錦、人聲如沸品嚣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翰撑。三九已至罩旋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間眶诈,已是汗流浹背涨醋。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留逝撬,地道東北人浴骂。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像宪潮,于是被迫代替她去往敵國和親溯警。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容