Widget for Week: Button

Flutter 中 Button 的使用也非常簡單。
Flutter 中的 button 都是 MaterialButton ,這個是基類,所以常見的都是基于他衍生的,官方為我們提供了幾個常用的 button,[FlatButton],[OutlineButton],[RaisedButton],下面就一一介紹,并例舉一些常用的 case 的樣式處理。


image.png

本文基于源碼 1.10.2

  • RaisedButton :凸起的按鈕,其實就是Android中的Material Design風(fēng)格的Button ,繼承自MaterialButton
  • FlatButton :扁平化的按鈕,繼承自MaterialButton
  • OutlineButton :帶邊框的按鈕,繼承自MaterialButton,其實就是設(shè)置了 shape 的 RaisedButton
  • IconButton :圖標(biāo)按鈕,繼承自StatelessWidget,其實等同于上邊的 Button 設(shè)置 child 為 Icon

先來看一下 MaterialButton 的構(gòu)造函數(shù),屬性是蠻多的。。。從頭說起。

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.autofocus = false,
    this.materialTapTargetSize,
    this.animationDuration,
    this.minWidth,
    this.height,
    this.child,
  })
屬性 值類型 說明
onPressed VoidCallback 必填參數(shù),按下回調(diào),設(shè)置為 null 則表示禁用,會啟用禁用的樣式
child Widget Button 上要顯示的組件
textColor Color 組件的顏色,比如child 為 Text 時就是設(shè)置了 Text 的字體顏色
color Color button 的顏色
disabledColor Color 按鈕禁用時候的顏色
disabledTextColor Color 按鈕禁用的時候的child 顏色
splashColor Color 水波紋顏色
highlightColor Color 長按時按鈕的顏色
elevation double 陰影的范圍大小,值越大陰影范圍越大
padding EdgeInsetsGeometry 內(nèi)邊距
shape ShapeBorder 設(shè)置形狀
minWidth double 最小寬度
height double 高度

經(jīng)過上述屬性,基本上就能搭配出來你想要的任何的按鈕樣式了。

RaisedButton 和 FlatButton 都是直接繼承 MaterialButton,所以默認(rèn)使用的樣式大同小異,唯一區(qū)別就是 FlatButton扁平化,沒有凸起的背景色,所以比較適合給 Text 設(shè)置點擊事件的。

屬性介紹完畢,相信大家都有個印象,對比自己的 Android 或者 iOS 經(jīng)驗,也都能腦補(bǔ)出來樣式。。。
下邊就說一下開發(fā)中常用的一些樣式。

padding

很多時候,按鈕中間的文字,是需要給一點距離的,文字距離上下左右都有一定邊距,此時就需要用到 padding 屬性,如下代碼就是給 Text 四周設(shè)置了 20 的邊距,距離按鈕邊框,當(dāng)然你也可以用EdgeInsets.only()給具體的某一個(幾個)方向設(shè)置邊距,使用EdgeInsets.symmetric()給水平或者垂直方向設(shè)置邊距。

 RaisedButton(
              onPressed: () {
                _showSnackBar("RaisedButton 設(shè)置內(nèi)邊距20");
              },
              child: Text("RaisedButton 設(shè)置內(nèi)邊距20"),
              padding: const EdgeInsets.all(20),
            ),

shape

shape 的值是 ShapeBorder ,抽象類,他有幾個常見的實現(xiàn)類

  • BeveledRectangleBorder 帶斜角的長方形邊框
  • CircleBorder 圓形邊框
  • RoundedRectangleBorder 圓角矩形
  • StadiumBorder 兩端是半圓的邊框

對應(yīng)的都要兩個屬性:slide ,borderRadius

圓角矩形
如下代碼可實現(xiàn)圓角矩形的邊框形狀,當(dāng)然了如果你要是想實現(xiàn) iOS 樣式的大圓角的按鈕,只需要把 Radius 的值設(shè)置的大一點就行了。

RaisedButton(
              onPressed: () {},
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(10)),
              ),
              child: Text(
                "RaisedButton 圓角背景(小)",
                style: TextStyle(fontSize: 10),
              ),
            ),

iOS 樣式 按鈕
在 IOS 設(shè)備上,按鈕都是兩頭半圓樣式的,那么就可以簡單的實現(xiàn),兩種方案:
1.給RoundedRectangleBorder 的 Radius 設(shè)置的超級大
2.直接使用 StadiumBorder()設(shè)置為 shape

RaisedButton(
              onPressed: () {},
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(300)),
              ),
              child: Text(
                "RaisedButton 圓角背景(iOS 樣式)",
                style: TextStyle(fontSize: 10),
              ),
            ),
RaisedButton(
              onPressed: () {},
              shape: StadiumBorder(),
              child: Text(
                "StadiumBorder 兩頭半圓",
                style: TextStyle(fontSize: 10),
              ),
            ),

圓形按鈕
使用 CircleBorder 可以實現(xiàn)圓形的按鈕樣式

RaisedButton(
              onPressed: () {},
              padding: const EdgeInsets.all(20),
              shape: CircleBorder(),
              child: Text(
                "圓形樣式",
                style: TextStyle(fontSize: 10),
              ),
            ),

斜角的矩形
實現(xiàn)帶斜角的矩形,也很簡單,直接使用BeveledRectangleBorder就行了,BorderRadius 的值的大小,可以幫助你實現(xiàn)各式各樣的斜角。。。
值越大,斜的越厲害,如果設(shè)置為 0,就是標(biāo)準(zhǔn)的矩形。

RaisedButton(
              color: Colors.red,
              onPressed: () {},
              shape: BeveledRectangleBorder(
                  borderRadius: BorderRadius.circular(10)),
              child: Text(
                "StadiumBorder 兩頭半圓",
                style: TextStyle(fontSize: 10),
              ),
            ),

以上實現(xiàn)的一些樣式,都是純色的,單純的背景色,下邊再來實現(xiàn)一些帶邊框的樣式,
BorderShape 的幾個實現(xiàn)類里邊,都有兩個屬性:slide 和 borderRadius.
slide 屬性可以設(shè)置背景色,邊框顏色,邊框的背景等
borderRadius 就是設(shè)置弧形程度。

實現(xiàn)一個紅色邊框,寬度為 1,白色背景的邊框
紅色邊框用 side 里邊的 color 來設(shè)置,寬度用 width 設(shè)置

 RaisedButton(
              onPressed: () {},
              color: Colors.white,
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10),
                  side: BorderSide(color: Colors.red)),
              child: Text("RaisedButton"),
            ),

漸變色按鈕
Flutter 中的按鈕不支持實現(xiàn)漸變色,所以需要依靠 Container 來幫忙,只需要給按鈕的 child套一個 Container,給 Container 設(shè)置漸變色就行了。但是需要考慮到處理 button 自帶的默認(rèn)的內(nèi)邊距,一定要記得去掉,不然會很難看。。。

Theme(
              child: RaisedButton(
                onPressed: () {},
                elevation: 0.0,
                color: Colors.white,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10),
                ),
                child: Container(
                  child: Text("RaisedButton"),
                  padding: EdgeInsets.fromLTRB(16, 8, 16, 8),
                  decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(10),
                      gradient:
                          LinearGradient(colors: [Colors.green, Colors.red])),
                ),
              ),
              data: ThemeData().copyWith(
                  buttonTheme:
                      ButtonThemeData(padding: const EdgeInsets.all(0))),
            ),

不知道大家有沒有發(fā)現(xiàn),按鈕在使用過程中,有一個自己的默認(rèn)的寬高,仔細(xì)看看源碼,發(fā)現(xiàn)是在按鈕的主題里邊設(shè)置了,如下代碼,
所以如果你想去掉這個默認(rèn)值,可以在 Theme 里邊進(jìn)行設(shè)置,可以直接在最外層的 MaterialApp 中設(shè)置,也可以給按鈕嵌套一個 Theme()進(jìn)行處理。如下代碼采用了第二個方案。

ButtonThemeData({
    this.textTheme = ButtonTextTheme.normal,
    this.minWidth = 88.0,
    this.height = 36.0,
    EdgeInsetsGeometry padding,
    ShapeBorder shape,
    this.layoutBehavior = ButtonBarLayoutBehavior.padded,
    this.alignedDropdown = false,
    Color buttonColor,
    Color disabledColor,
    Color focusColor,
    Color hoverColor,
    Color highlightColor,
    Color splashColor,
    this.colorScheme,
    MaterialTapTargetSize materialTapTargetSize,
  })
 Theme(
              child: RaisedButton(
                onPressed: () {},
                color: Colors.white,
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(10),
                    side: BorderSide(color: Colors.red, width: 4)),
                child: Text("去掉默認(rèn)寬高"),
              ),
              data: ThemeData().copyWith(
                  buttonTheme: ButtonThemeData(minWidth: 10, height: 20)),
            ),

帶圖片/圖標(biāo)的按鈕
有時候需要實現(xiàn)一些帶有圖標(biāo)的按鈕,那么可以用 RaisedButton ,通過 child 嵌套實現(xiàn),也可以直接使用 IconButton

 RaisedButton(
              onPressed: () {},
              child: Row(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[Icon(Icons.add), Text("帶圖標(biāo)")],
              ),
            ),
            SizedBox(width: 10),
            FlatButton(
              onPressed: () {},
              child: Icon(
                Icons.add,
                color: Colors.red,
              ),
            ),
            SizedBox(width: 10),
            IconButton(
              onPressed: () {},
              icon: Icon(
                Icons.add,
                color: Colors.red,
              ),
            ),

OK,今日份 按鈕相關(guān)內(nèi)容搞定,后續(xù)有遇到其他的樣式,再更新進(jìn)來。。。

源碼鏈接:https://github.com/yanftch/book/blob/master/lib/demo/widgets/w_button.dart

收拾收拾,放假啦~~
預(yù)祝小伙伴們假期愉快??????

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容