????小菜在嘗試做主題顏色切換時(shí),希望背景色有一個(gè)自然的過(guò)渡過(guò)程,于是了解到 ColorTween 顏色補(bǔ)間差值器,配合 AnimationController 實(shí)現(xiàn)兩種顏色間的自然過(guò)渡疟呐;小菜簡(jiǎn)單嘗試一下;
ColorTween
源碼分析
????ColorTween 的源碼很簡(jiǎn)單东且,繼承自 Tween 補(bǔ)間動(dòng)畫启具,與 Tween 相同,只是 begin 和 end 用 Color 替代珊泳;其中若需要透明狀態(tài)鲁冯,可以將 begin / end 設(shè)置為 null拷沸;Colors.transparent 再此代表黑色透明,會(huì)淡入淡出黑色薯演;
class ColorTween extends Tween<Color?> {
ColorTween({ Color? begin, Color? end }) : super(begin: begin, end: end);
@override
Color? lerp(double t) => Color.lerp(begin, end, t);
}
案例源碼
????小菜預(yù)先設(shè)置好需要主題顏色切換的 UI Widget撞芍,之后通過(guò)混入 TickerProviderStateMixin,在 initState() 初始化時(shí)設(shè)置好 AnimationController跨扮,將顏色傳遞給背景色序无;
AnimationController _controller;
Animation<Color> _colors;
Color _currentColor = Colors.black;
@override
void initState() {
super.initState();
_controller = AnimationController(duration: Duration(seconds: 3), vsync: this);
_colors = ColorTween(begin: _currentColor, end: Colors.amber).animate(_controller);
}
_bodyWid() => Material(
child: AnimatedBuilder(
animation: _colors,
builder: (BuildContext _, Widget childWidget) {
return Scaffold(backgroundColor: _colors.value, body: _itemListWid());
}));
????通過(guò) AnimationController 控制淡入淡出時(shí)機(jī);reset() 重置控制器衡创,forward() 為 begin 到 end 顏色切換帝嗡;reward() 為 end 到 begin 顏色切換周拐;repeat() 重復(fù)循環(huán)切換怕磨;
_changeColorWid() => Container(
color: Colors.white,
child: Column(children: [
ListTile(title: Text('切換 ThemeColor:')),
Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
_itemColorWid(Colors.deepOrange), _itemColorWid(Colors.teal),
_itemColorWid(Colors.blue), _itemColorWid(Colors.pink),
_itemColorWid(Colors.indigoAccent)
])
]));
_itemColorWid(color) => GestureDetector(
child: Container(width: 50.0, height: 50.0, color: color),
onTap: () {
_colors = ColorTween(begin: _currentColor, end: color).animate(_controller);
setState(() {
_controller.reset();
_controller.forward();
});
_currentColor = color;
});
ButtonBar
????小菜在很多場(chǎng)景中設(shè)置水平均分或右對(duì)齊黄痪,為此小菜了解到一個(gè)新的容器方式苍糠,ButtonBar 默認(rèn)水平方式放置子 Widget 當(dāng)水平寬度無(wú)法完全放置所有子 Widget 時(shí)會(huì)豎直方向放置沪悲,小菜簡(jiǎn)單學(xué)習(xí)一下卷中;
源碼分析
const ButtonBar({
Key key,
this.alignment, // 對(duì)齊方式
this.mainAxisSize, // 主軸上占據(jù)空間范圍
this.buttonTextTheme, // 按鈕文本主題
this.buttonMinWidth, // 子按鈕最小寬度
this.buttonHeight, // 子按鈕最高度
this.buttonPadding, // 子按鈕內(nèi)邊距
this.buttonAlignedDropdown, // 下拉菜單是否與子按鈕對(duì)齊
this.layoutBehavior,
this.overflowDirection, // 子按鈕排列順序
this.overflowButtonSpacing, // 子按鈕之間間距
this.children = const <Widget>[],
})
????簡(jiǎn)單分析源碼脖苏,ButtonBar 作為一個(gè)無(wú)狀態(tài)的 StatelessWidget 與 Row 類似方灾,作為一個(gè)存放子 Widget 的容器塘秦,其中包括了類似于對(duì)齊方式等屬性方便應(yīng)用讼渊;小菜簡(jiǎn)單理解為變形的 Row,實(shí)際是繼承自 Flex 的 _ButtonBarRow尊剔;
案例嘗試
構(gòu)造方法
????ButtonBar 作為一個(gè) Widget 容器爪幻,用于水平存放各 Widget,若子 Widget 占據(jù)空間范圍大于分配空間時(shí)须误,則豎直方向展示挨稿;
_buttonBarWid01() => ButtonBar(children: <Widget>[
RaisedButton(child: Text('Button 01'), onPressed: null),
RaisedButton(child: Text('Button 02'), onPressed: null) ]);
_buttonBarWid02() => ButtonBar(children: <Widget>[
RaisedButton(child: Text('Button 01'), onPressed: null),
RaisedButton(child: Text('Button 02'), onPressed: null),
RaisedButton(child: Text('Button 03'), onPressed: null),
RaisedButton(child: Text('Button 04'), onPressed: null) ]);
_buttonBarWid03() => ButtonBar(children: <Widget>[
RaisedButton(child: Text('Button 01'), onPressed: null),
RaisedButton(child: Text('Button 02'), onPressed: null),
RaisedButton(child: Text('Button 03'), onPressed: null),
RaisedButton(child: Text('Button 04'), onPressed: null),
RaisedButton(child: Text('Button 05'), onPressed: null) ]);
1. alignment
????alignment 為容器內(nèi)子 Widget 的對(duì)齊方式,不設(shè)置或?yàn)?null 時(shí)默認(rèn)為 end 方式對(duì)齊京痢,此時(shí)與 ltr / rtl 相關(guān)奶甘;
_buttonBarWid01(index) {
MainAxisAlignment alignment;
if (index == 0) {
alignment = MainAxisAlignment.start;
} else if (index == 1) {
alignment = MainAxisAlignment.center;
} else if (index == 2) {
alignment = MainAxisAlignment.spaceAround;
} else if (index == 3) {
alignment = MainAxisAlignment.spaceBetween;
} else if (index == 4) {
alignment = MainAxisAlignment.spaceEvenly;
} else {
alignment = MainAxisAlignment.end;
}
return ButtonBar(alignment: alignment, children: <Widget>[
RaisedButton(child: Text('Button'), onPressed: null),
RaisedButton(child: Text('${alignment.toString()}'), onPressed: null) ]);
}
2. mainAxisSize
????mainAxisSize 為主軸上占據(jù)空間范圍,與 Row / Column 一致祭椰,分為 min / max 最小范圍和最大填充范圍兩種臭家;
_buttonBarWid05(mainAxisSize) => Container(
color: Colors.blue.withOpacity(0.3),
child: ButtonBar(mainAxisSize: mainAxisSize, children: <Widget>[
RaisedButton(child: Text('Button 01'), onPressed: null),
RaisedButton(child: Text('Button 02'), onPressed: null),
RaisedButton(child: Text('Button 03'), onPressed: null)
]));
3. buttonTextTheme
????buttonTextTheme 為子 Widget 按鈕主題,主要包括 normal / accent / primary 三種主題樣式方淤,分別對(duì)應(yīng) ThemeData.brightness / accentColor / primaryColor钉赁;
_buttonBarWid04(theme) =>
ButtonBar(buttonTextTheme: theme, children: <Widget>[
RaisedButton(child: Text('Button 01'), onPressed: null),
RaisedButton(child: Text('Button 02', style: TextStyle(color: Colors.blue)), onPressed: null),
RaisedButton(child: Text('${theme.toString()}'), onPressed: null),
]);
4. buttonMinWidth & buttonHeight
????buttonMinWidth & buttonHeight 分別對(duì)應(yīng)子 Widget 默認(rèn)的最小按鈕寬度和按鈕高度;
_buttonBarWid06(width, height, alignment) =>
ButtonBar(buttonMinWidth: width, buttonHeight: height, children: <Widget>[
RaisedButton(child: Text('Button 01'), onPressed: null),
RaisedButton(child: Text('Button 02', style: TextStyle(color: Colors.blue)), onPressed: null),
RaisedButton(child: Text('${alignment.toString()}'), onPressed: null),
]);
5. overflowButtonSpacing & buttonPadding
????overflowButtonSpacing 對(duì)應(yīng)子按鈕外間距携茂,類似于 GridView 元素間間距你踩;buttonPadding 對(duì)應(yīng)子按鈕內(nèi)邊距;
_buttonBarWid07(padding, spacing) => ButtonBar(
overflowButtonSpacing: spacing,
buttonPadding: EdgeInsets.all(padding),
children: <Widget>[
RaisedButton(child: Text('Button 01'), onPressed: null),
RaisedButton(child: Text('Button 02', style: TextStyle(color: Colors.blue)), onPressed: null),
RaisedButton(child: Text('Button 03'), onPressed: null)
]);
6. overflowDirection
????overflowDirection 為若容器內(nèi)子 Widget 所占范圍超過(guò)最大限制范圍時(shí),垂直排列順序姓蜂,小菜理解為順序和倒序兩種按厘;
_buttonBarWid08(direction) =>
ButtonBar(overflowDirection: direction, children: <Widget>[
RaisedButton(child: Text('Button 01'), onPressed: null),
RaisedButton(child: Text('Button 02', style: TextStyle(color: Colors.blue)), onPressed: null),
RaisedButton(child: Text('Button 03'), onPressed: null),
RaisedButton(child: Text('${direction.toString()}'), onPressed: null),
]);
????ColorTween 案例源碼 & ButtonBar 案例源碼
????ColorTween 和 ButtonBar 的應(yīng)用非常簡(jiǎn)單,這次小菜在實(shí)際場(chǎng)景中進(jìn)行嘗試學(xué)習(xí)钱慢,如有錯(cuò)誤逮京,請(qǐng)多多指導(dǎo)!
來(lái)源: 阿策小和尚