Flutter佈局錦囊---塗鴉風格按鈕
阿新 • • 發佈:2019-01-05
設計給的效果如下:
拿到設計後,先把整體拆分成幾個部分:
- “可點選框”,使用堆疊(
Stack
)元件佈局的可點選區域。 - “底部矩形”,用來襯托“主要矩形”,以形成立體效果的矩形。
- “主要矩形”,按鈕主體部分,通過調整上下位置來模擬按壓效果。
然後就可以開始進行編碼了。
第1步:繪製元件樹
第2步:實現“可點選框”
通過手勢探測器(GestureDetector
)元件,你可以通過檢測多種手勢並設定對應的處理函式。通過大小框(SizedBox
)元件為“按鈕”設定一個活動區域,並將堆疊(Stack
)元件作為子元件置於其中。同時,通過activation
onTapCallback
兩個變數來傳遞狀態和回撥函式。
import 'package:flutter/material.dart';
/// 自定義的塗鴉按鈕元件。
class DoodleButton extends StatefulWidget {
// TODO: 第3步:實現“底部矩形”,成員變數。
// TODO: 第4步:實現“主要矩形”,成員變數。
/// 按鈕的啟用狀態,預設為`false`。
final bool activation;
/// 發生點選時的回撥函式。
final Function onTapCallback;
DoodleButton({
// TODO: 第3步:實現“底部矩形”,預設構造。
// TODO: 第4步:實現“主要矩形”,預設構造。
this.activation: false,
this.onTapCallback,
});
@override
_DoodleButtonState createState() => _DoodleButtonState();
}
/// 與自定義的塗鴉按鈕元件關聯的狀態子類。
class _DoodleButtonState extends State<DoodleButton> {
// TODO: 第4步:實現“主要矩形”,控制按壓。
@override
Widget build (BuildContext context) {
// 手勢探測器(`GestureDetector`)元件,檢測手勢的元件。
// 嘗試識別與其非空回撥相對應的手勢。如果此元件具有子項,
// 則它會根據其大小調整行為推遲該子項。
// 如果它沒有子元件,它會變得適合父元件。
return GestureDetector(
// 在點選(`onTap`)屬性,發生了點選。
onTap: widget.activation ? () {
setState(() {
// TODO: 第4步:實現“主要矩形”,“按下”按鈕。
widget.onTapCallback();
// TODO: 第4步:實現“主要矩形”,“鬆開”按鈕。
});
} : null,
child: SizedBox(
height: 48.0,
// 堆疊(`Stack`)元件,用於將其子級相對於其框的邊緣定位。
child: Stack(
children: <Widget>[
// TODO: 第3步:實現“底部矩形”,實現容器。
// TODO: 第4步:實現“主要矩形”,實現容器。
]
),
),
);
}
}
第3步:實現“底部矩形”
通過backgroundColor
、silentBackgroundColor
變數來傳遞“按鈕”可用、不可用時,“底部矩形”的顏色。
// TODO: 第3步:實現“底部矩形”,成員變數。
/// 按鈕的底部顏色,預設為`#D95636`。
final Color backgroundColor;
/// 不可用按鈕的底部顏色,預設為`#8A8A8A`。
final Color silentBackgroundColor;
// TODO: 第3步:實現“底部矩形”,預設構造。
this.backgroundColor: const Color(0xFFD95636),
this.silentBackgroundColor: const Color(0xFF8A8A8A),
使用對齊(Align
)元件,並通過Alignment.bottomCenter
將其設定為靠近下方對齊。再用邊界半徑(BorderRadius
)類,將矩形的4個邊角設定為圓角。
// TODO: 第3步:實現“底部矩形”,實現容器。
// 對齊(`Align`)元件,用於將其子項與其自身對齊,並根據子級的大小自行調整大小。
Align(
// 對準屬性,如何調整子元件。
alignment: Alignment.bottomCenter,
child: Container(
decoration: BoxDecoration(
color: widget.activation ? widget.backgroundColor : widget.silentBackgroundColor,
// 框裝飾(`BoxDecoration`)類的邊界(`border`)屬性,在背景顏色、漸變或影象上方繪製的邊框。
// 邊界(`Border`)類,框的邊框,由四個邊組成:頂部、右側、底部、左側。
border: Border.all(
// 寬度引數,邊框的寬度。
width: 2.0,
// 顏色引數,邊框的顏色。
color: const Color(0xFF282828),
),
// 邊界半徑(`borderRadius`)屬性,如果為非空值,則此屬性將對此框的角進行舍入。
// 邊界半徑(`BorderRadius`)類,矩形每個角的一組不可變半徑。
// 邊界半徑.所有(`BorderRadius.all`)建構函式,建立一個邊界半徑,設定所有的半徑。
borderRadius: BorderRadius.all(
// 半徑(`Radius`)類,圓形或橢圓形的半徑。
// 半徑.圓(`Radius.circular`)建構函式,構造一個圓形半徑,x和y將具有相同的半徑值。
Radius.circular(2.0),
),
),
height: 42.0,
),
),
第4步:實現“主要矩形”
通過mainColor
、silentMainColor
變數來傳遞“按鈕”可用、不可用時,“底部矩形”的顏色,promptText
變數傳遞“按鈕”的操作提示文字。
// TODO: 第4步:實現“主要矩形”,成員變數。
/// 按鈕的操作提示文字。
final String promptText;
/// 按鈕的主要顏色,預設為`#FF6B47`。
final Color mainColor;
/// 不可用按鈕的主要顏色,預設為`#B2B2B2`。
final Color silentMainColor;
// TODO: 第4步:實現“主要矩形”,預設構造。
this.promptText,
this.mainColor: const Color(0xFFFF6B47),
this.silentMainColor: const Color(0xFFB2B2B2),
通過對準(Alignment
)類來控制“主要矩形”的按壓效果:靠近上邊時是鬆開按鈕;靠近下邊時是按下按鈕。
// TODO: 第4步:實現“主要矩形”,控制按壓。
// 對準(`Alignment`)類,矩形內的一個點。
// [0.0,0.0]表示矩形的中心,[-1.0到+1.0]的距離是從矩形的一邊到矩形的另一邊的距離。
// 因此,水平(或垂直)[2.0]單位等於矩形的寬度(或高度)。
/// 主要容器的對齊方式,控制按鈕的按壓狀態。
Alignment mainContainerAlignment = Alignment.topCenter;
// TODO: 第4步:實現“主要矩形”,“按下”按鈕。
mainContainerAlignment = Alignment.bottomCenter;
widget.onTapCallback();
// TODO: 第4步:實現“主要矩形”,“鬆開”按鈕。
mainContainerAlignment = Alignment.topCenter;
最後實現“主要矩形”的佈局程式碼。
// TODO: 第4步:實現“主要矩形”,實現容器。
Align(
alignment: mainContainerAlignment,
child: Container(
child: Center(
child: Text(
widget.promptText,
style: TextStyle(
color: const Color(0xFF282828),
fontSize: 18.0,
// 字型重量(`FontWeight`)類,用於繪製文字的字形的粗細。
fontWeight: FontWeight.bold,
),
),
),
decoration: BoxDecoration(
color: widget.activation ? widget.mainColor : widget.silentMainColor,
border: Border.all(
width: 2.0,
color: const Color(0xFF282828),
),
borderRadius: BorderRadius.all(
Radius.circular(2.0),
),
),
height: 42.0,
),
),