06、從頭開始整 Flutter--基本小部件-button(1)

本節(jié)大綱

PS:轉(zhuǎn)載請注明出處
作者: TigerChain
地址: http://www.lxweimin.com/p/46808a247562
本文出自 TigerChain 簡書 從頭開始整 Flutter系列

教程簡介

  • 1、閱讀對象
    本篇教程適合新手閱讀,老手直接略過
  • 2、教程難度
    初級,本人水平有限,文章內(nèi)容難免會(huì)出現(xiàn)問題,如果有問題歡迎指出,謝謝

正文

本文主要介紹 MaterialButton 和它的孩子們 FlatButton、RaisedButton 和 OutlineButton

一、無所不在的 Button

(1)、一些 Button 舉例

Button 在一個(gè)項(xiàng)目是必不可少的,前端好多 UI 庫都把 button 專門封裝成一個(gè)小組件要么是直接是 css 樣式庫調(diào)用即可,比如 bootstrap、ElementUi、buttons,拿 buttons「隨便舉個(gè)例子說一下」來說,其中的部分圖片

buttons 部分效果

(2)、Button 的實(shí)現(xiàn)方式

一般情況下,做一個(gè) Button 都是抽象成一個(gè)組件,然后給其設(shè)置對應(yīng)的樣式即可,比如 buttons 或是 bootstrap 的 button 都是給設(shè)置不同的 css 樣式 來顯示不同的效果,在 Android 中通過自定義 View 來通過屬性設(shè)置顯示不同的按鈕樣式,基本上實(shí)現(xiàn)方式原理都是一毛一樣的

二、Flutter 中的 Buttons

在 Flutter 中一切萬物皆組件, Buttons「Flutter 中并沒有這個(gè)組件,這里為了說 Flutter 的 Button 組件多用了一個(gè)集合表示一下」 也不例外,也是一個(gè)組件,F(xiàn)lutter 中的 Buttons 基本上分為兩類

1、 MaterialButton 類 Button

  • FlatButton:扁平化按鈕
  • RaisedButton:凸起的按鈕
  • OutlineButton:帶邊框的按鈕

以上三個(gè) button 都屬于 MaterialButton 的子類

2、其它 Button

  • FloatingActionButton
  • IconButton
  • ButtonBar
  • DropdownButton
  • 等等其它 Button 還包括自定義的 Button 組件

我們先看 MaterialButton ,MaterialButton 搞定了,它的子類還不是菜,無非就是擴(kuò)展了一下而已嗎

三、MaterialButton 家族

從上面我們了解到 MaterialButton 和其子類一組成了四在家族「目前來說,保不齊后面更新了還會(huì)有更多,我們不說三方組件,只說系統(tǒng)支持的」,那么"擒賊先擒王",我們先看看老大 MaterialButton

(1)、MaterialButton

屬性解析

不廢話看構(gòu)造方法

const MaterialButton({
    Key key,
    @required this.onPressed,
    this.onHighlightChanged,
    this.textTheme,
    this.textColor,
    this.disabledTextColor,
    this.color,
    this.disabledColor,
    this.focusColor,
    this.hoverColor,
    this.highlightColor,
    this.splashColor,
    this.colorBrightness,
    this.elevation,
    this.focusElevation,
    this.hoverElevation,
    this.highlightElevation,
    this.disabledElevation,
    this.padding,
    this.shape,
    this.clipBehavior = Clip.none,
    this.focusNode,
    this.materialTapTargetSize,
    this.animationDuration,
    this.minWidth,
    this.height,
    this.child,
  }) : super(key: key);

設(shè)置的屬性的還是比較多的,這里挑重點(diǎn)解釋一下

屬性 說明
onPressed 按鈕按下事事件
onHighlightChanged 可以用來監(jiān)聽按鈕的按下和放開過程
textTheme 文本主題
textColor 按鈕文本顏色
disabledTextColor 按鈕禁用按鈕上的文本顏色
color 按鈕的顏色
disabledColor 按鈕禁用時(shí)的顏色
highlightColor 長按后按鈕的顏色
splashColor 點(diǎn)擊長按水波紋的顏色
elevation 陰影的范圍大小
padding 按鈕內(nèi)邊距
shape 按鈕的形狀樣式
minWidth 按鈕最小寬度
height 按鈕的高度
child 一般是 Text 文本組件
實(shí)例操練

1、color 屬性

用來設(shè)置按鈕顏色

顯示效果

顯示效果

核心代碼

MaterialButton color 核心代碼

PS:這里注意一點(diǎn),就是如果不寫 onPressed 方法或是 onPressed: 后面直接給個(gè) null 那么給按鈕設(shè)置顏色是無效的「所以說 color 也是按鈕的可用時(shí)顏色,不可用顏色有 disabledColor 屬性呢」

2、textColor 屬性

用來設(shè)置文本顏色的屬性

顯示效果

顯示效果

核心代碼

MaterialButton textColor 核心代碼

同樣 onPressed 方法不能為空或?yàn)?null,否則 textColor 無效

3、splashColor 屬性

按鈕按下的水波紋顏色設(shè)置

顯示效果

顯示效果

核心代碼

MaterialButton splashColor 核心代碼

同樣 onPressed 方法不能為空或?yàn)?null,否則 splashColor 無效「按鈕都禁用了點(diǎn)擊肯定沒效果」

4、highlightColor 屬性

按鈕長按高亮顏色

顯示效果

顯示效果

核心代碼

MaterialButton highlightColor 核心代碼

5、elevation 屬性

按鈕陰影大小,默認(rèn)是 2 可以從源碼中看到

elevation 默認(rèn)值來源

顯示效果

顯示效果

核心代碼

MaterialButton elevation 核心代碼

6、padding 屬性

設(shè)置按鈕內(nèi)邊距

顯示效果

顯示效果

核心代碼

MaterialButton padding 核心代碼

等屏幕寬按鈕實(shí)現(xiàn)

我們想一下,根據(jù)我們的已有知識如何實(shí)現(xiàn)一個(gè)等屏幕寬的按鈕呢,細(xì)心的朋友可能想到使用 Container 的 width 就可以,沒錯(cuò)我們可以使用它實(shí)現(xiàn),我們來介紹三種方式實(shí)現(xiàn)等屏幕寬的按鈕

  • (1)、使用 Container 的寬來實(shí)現(xiàn)

我們讓 Container 的寬為等屏幕寬度即可

顯示效果

顯示效果

核心代碼

我們來封裝一個(gè)組件是否根據(jù) Container 的寬來設(shè)定按鈕的寬度

根據(jù) Container 的寬度設(shè)置按鈕寬度

我們看到我們在 materialButton3 組件方法中又封裝了一個(gè)組件方法 commonEqualMaterialButton 用來判斷是否根據(jù) MaterialButton 的 minWidth 來確定按鈕寬度

根據(jù) MaterialButton 的 minWidth 設(shè)置按鈕寬度

我們看如何調(diào)用

Container width 確定按鈕寬度代碼調(diào)用

我們可以看到通過以上調(diào)用代碼會(huì)走 MaterialButton3 的 if 代碼片斷,那么按鈕的寬度就會(huì)由 Container 的 width:double.infinity 來確定了是等屏幕寬的

  • (2)、使用 MaterialButton 的 minWidth 來設(shè)置

通過上面代碼的封裝我們已經(jīng)也看到了,當(dāng)然我們還可以通過使用 MaterialButton 的 minWidth 來設(shè)置按鈕的寬度

顯示效果

顯示效果

核心代碼

上面封裝過了,我們直接調(diào)用即可

 materialButton3('等屏幕寬2、 使用其 minwidth 實(shí)現(xiàn)',false),
  • (3)、使用 Row 配合 Expanded 來實(shí)現(xiàn)

我們上節(jié)完成了等分的例子說了 Expanded 組件,如果上節(jié)中是一個(gè)子組件那么不就是等屏幕寬了么

顯示效果

顯示效果

核心代碼

Row 和 Expanded 實(shí)現(xiàn)等屏寬按鈕

7、shape 屬性

按鈕的形狀我們在開發(fā)中運(yùn)用的也比較多,一般是圓角按鈕和直角按鈕比較常用,在 Flutter 中 shape 使用 ShapeBorder 來表示,ShapeBorder 是一個(gè)抽象類,所以我們直接看它的子類

ShapeBorder 的子類

我們可以看到還有和 input 相關(guān)的 Border,我們挑幾個(gè)重要的說一下以下幾個(gè)常用的

  • roundedRectangleBorder // 矩形圓角邊框
  • CircleBorder // 圓形邊框
  • StadiumBorder // 圓角邊框
  • BeveledRectangleBorder// 斜角邊框,可以實(shí)現(xiàn)直角

為了方便起見,我們封裝一個(gè)共用的組件方法,只是根據(jù)設(shè)置不同的 shape 就給我顯示不同的效果,如下:

shape 的封裝
  • (1)、先看 RoundedRectangleBorder

圓角矩形,前面我們說過 Container 的 decoration 的 BoxDecoration RoundedRectangleBorder border 和 borderRadius 用法和其差不多,我們看其構(gòu)造方法

const RoundedRectangleBorder({
this.side = BorderSide.none,
this.borderRadius = BorderRadius.zero,
}) : assert(side != null),
   assert(borderRadius != null);

我們看到 RoundedRectangleBorder 只有兩個(gè)屬性邊框和邊框圓角,我們直接看效果吧

顯示效果

顯示效果

我們來調(diào)用我們封裝后的代碼

RoundedRectangleBorder 調(diào)用封裝

封裝一個(gè) RoundedRectangleBorder 組件

RoundedRectangleBorder 組件方法封裝

上面我們調(diào)用過了,這樣就完成了效果圖樣式

  • (2)、 CircleBorder

從字面意思可以知道這個(gè) shape 是設(shè)置圓按鈕的,看構(gòu)造方法

const CircleBorder({ 
this.side = BorderSide.none }) 
: assert(side != null);

我們可以看到 CircleBorder 只有一個(gè) side 屬性并且不能為空「不是說我們非要傳遞,參數(shù)是可選的可以不傳,不能為空是因?yàn)樗心J(rèn)的值,它本身是不為空的」,我們來看我們做的效果吧

顯示效果

顯示效果

核心代碼

CircleBorder 核心代碼

我們直接調(diào)用上面我們封裝的方法把 CircleBorder 傳遞進(jìn)去即可

  • (3)、 StadiumBorder

StadiumBorder 半圓角矩形我們直接使用它就可以設(shè)置出來一個(gè)半圓角的按鈕,看其構(gòu)造方法

const StadiumBorder({
this.side = BorderSide.none}) 
: assert(side != null);

一樣也是只有一個(gè) side 屬性,我們來看我們寫的效果吧

顯示效果

顯示效果

核心代碼

沒什么好說的,繼續(xù)調(diào)用我們封裝的代碼即可

StadiumBorder 顯示效果代碼

在這里我們沒有設(shè)置 side 有興趣可以添加看看

  • (4)、 BeveledRectangleBorder

BeveledRectangleBorder 斜角矩形,我們看看構(gòu)造方法

const BeveledRectangleBorder({
this.side = BorderSide.none,
this.borderRadius = BorderRadius.zero,
}) : assert(side != null),
   assert(borderRadius != null);

我們可以看到它有兩個(gè)屬性 side 和 borderRadius,分別設(shè)置邊框和圓角大小,我們來看我們的效果

顯示效果

顯示效果

核心代碼

BeveledRectangleBorder 核心代碼

直接調(diào)用我們封裝的代碼即可,我們什么也不傳就是一個(gè)直角按鈕,當(dāng)然實(shí)現(xiàn)方式有多種,比如我們可以使用上面圓角方式實(shí)現(xiàn),把它的圓角設(shè)置為 0 就可以了

說了 BeveledRectangleBorder 是斜角矩形,那斜角體現(xiàn)在哪里呢? 我們給其設(shè)置 borderRadius 就可以實(shí)現(xiàn)斜角了,看顯示效果

顯示效果

核心代碼

BeveledRectangleBorder 斜角矩形按鈕

好了,對于 MaterialButton 的屬性我們就說這么多,我們把 MaterialButton 的幾大核心屬性都說了一下,那它的幾個(gè)子類那就跟玩似的,大概的說一下吧「就不像 MaterialButton 這么詳細(xì)的說了」

(2)、RaisedButton

RaisedButton 是凸起的按鈕,怎么樣的凸起呢?就是設(shè)置了一些陰影效果看起來有凸起的感覺,并且按下以后陰影會(huì)變大我們直接看效果

顯示效果

顯示效果

其實(shí)它就是是分兩種狀,普通狀態(tài)和按下狀態(tài),并且都有陰影,看起來就有凸起的效果

核心代碼

RaisedButton 默認(rèn)效果代碼

我們把 RaisedButton 做了一個(gè)簡單的封裝,然后我們給一個(gè)顏色看看

帶顏色的 RaisedButton

直接調(diào)用我們上面封裝的組件方法給個(gè)顏色即可,效果如下:

帶顏色的 RaisedButton 效果

這里就不多說了,玩過了 MaterialButton 它的其它屬性也不在話下嘗試著把玩一下即可

(3)、FlatButton

我們看 MaterialButton 第二個(gè)兒子 FlatButton,F(xiàn)latButton 是扁平化按鈕,默認(rèn)的背景是透明「默認(rèn)的 color 是 null」的也不帶陰影,按下后會(huì)有背景色但是還是沒有陰影,直接看效果吧

顯示效果

顯示效果

核心代碼

FlatButton 默認(rèn)效果代碼

這些效果使用 MaterialButton 都可以實(shí)現(xiàn),沒什么好說的,這里簡單的介紹一下即可

(4)、OutlineButton

我們看 MaterialButton 第三個(gè)兒子 OutlineButton,
OutlineButton 默認(rèn)是帶邊框的按鈕,且默認(rèn)沒有背景并且無陰影,但是按下后會(huì)出現(xiàn)背景并且無陰影,看效果

顯示效果

顯示效果

核心代碼

OutlineButton 效果代碼

OutlineButton 無非就是在 MaterialButton 的基礎(chǔ)「其實(shí)是 RaisedButton」上默認(rèn)重寫了 shape 等屬性而已,大概看一下源碼,也就是在 OutlineButton 的 build 方法中,我們看一下

[圖片上傳失敗...(image-cd3de1-1566137551597)]


outline_button_source_code.png

PS: 這里要看的是 OutlineButton 的 build 方法非它的 icon 的 build 方法

我們可以看到 OutlineButton 返回的是一個(gè) RaisedButton,并且默認(rèn)就是重寫了 shape 方法「帶了邊框等」并且陰影默認(rèn)都是 0 「就有一個(gè)高亮?xí)r的陰影默認(rèn)也是返回 0 」 ,其實(shí)學(xué)習(xí)組件就是看構(gòu)造方法和 build 方法來看它有哪些特性

目前來說,我們把 MaterialButton 家族的按鈕就介紹完了,只要把 MaterialButton 掌握了,其它的按鈕基本上沒啥好說的,我們在開發(fā)中當(dāng)然可以使用 MaterialButton 來實(shí)現(xiàn)我們的效果,可是知道了它的孩子就可以快速來實(shí)現(xiàn)我們想要效果的按鈕了,下面看一下其它的一些按鈕

四、IconButton

IconButton 不屬于 MaterialButton 家族,它繼承 StatelessWidget,從字面意思就可以看出它是一個(gè)帶圖標(biāo)的按鈕「是沒有文字的」,默認(rèn)情況下沒有背景,并且按下的時(shí)候會(huì)出現(xiàn)一個(gè)圓形的背景,來看構(gòu)造方法

  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.focusColor,
    this.hoverColor,
    this.highlightColor,
    this.splashColor,
    this.disabledColor,
    @required this.onPressed,
    this.focusNode,
    this.tooltip,
  }) 

從構(gòu)造方法中可以看到,IconButton 需要一個(gè) icon 和按下事件,其它的屬性 MaterialButton 中基本上都有,注意有一個(gè) tooltip 屬性「長按按鈕時(shí)出一個(gè)提示語」 ,我們來看效果

顯示效果

顯示效果

核心代碼

IconButton 效果代碼

帶 ICON 的文本按鈕

我們上面說了文本按鈕,也還說了 ICON 按鈕,那有沒有帶 ICON 的文本按鈕呢?答案是肯定的,其實(shí) RaisedButton、FlatButton、OutlineButton 內(nèi)置了一個(gè)帶 ICON 的構(gòu)造方法,我們直接使用 xxxButton.icon 就可以了,最簡單的使用方法是

FlatButton.icon(
    onPressed: (){},
    icon: Icon(Icons.lock), // ICON
    label: Text(' FlatButton.icon') // 文本
)

我們簡單的顯示一下:

顯示效果

顯示效果

我們可以看到這些默認(rèn)的效果和 RaisedButton、FlatButton、OutlineButton 默認(rèn)效果是一樣的,只不過多了個(gè) icon 而已,由于我們說過 button 的 child 一般情況來說是一個(gè)文本,但是它其實(shí)是一個(gè) widget ,本質(zhì)上可以多種組合,而 flutter 內(nèi)置的帶 icon 的文本組件就是使用組合「child 是一個(gè) Row 組件」來實(shí)現(xiàn)的,我們來看上面效果的代碼

核心代碼

xxxButton.icon 核心代碼

接下來我們來看看到底 ICON 文本是如何實(shí)現(xiàn)的,以 FlatButton.icon 為例子來說明,我們看其構(gòu)造方法,找到 _FlatButtonWithIcon 這個(gè)類,我們來具體的繼承實(shí)現(xiàn)「我們這里不是專門的源碼解析,只是大概過一下」,里面一段實(shí)現(xiàn) ICON 文本的按鈕的核心代碼

FlatButton.icon 實(shí)現(xiàn) icon 文本源碼

很清楚的看到使用 Row 組件,包裹了一個(gè) icon 和 lable 分析完畢

這節(jié)就說這么多,我們下節(jié)再介紹幾個(gè) button 比如 FloatingActionButton、ButtonBar 等,快動(dòng)手敲一下吧!


作者: TigerChain 訂閱查看更多內(nèi)容,公號「TigerChain」同步
本文出自 TigerChain從頭開始整 Flutter

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。