Flutter中漸變色的使用案例分享
前言
在日常的開(kāi)發(fā)中,UI為了讓界面更加吸引人往往會(huì)在界面上用到大量的漸變色。那么在本文中,我們將通過(guò)幾個(gè)案例更好的去了解Flutter中漸變色的使用。讓我們開(kāi)始探索Flutter世界中絢麗多彩的漸變色效果吧!
案例一:漸變色邊框
很多時(shí)候,一個(gè)簡(jiǎn)單的邊框并不能滿足我們對(duì)于界面的美感要求。我們希望給邊框增添一些特殊的效果,讓它更加引人注目和獨(dú)特。而正是在這種情況下,漸變色邊框成為了一個(gè)合適的選擇。在Flutter中,實(shí)現(xiàn)漸變色邊框的方式有很多,有簡(jiǎn)單的,有復(fù)雜的。最簡(jiǎn)單的實(shí)現(xiàn)方式呢就是通過(guò)兩個(gè)Container的疊加,例如:
Container(
height: 48,
width: 280,
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
gradient: const LinearGradient(
colors: [Colors.blue, Colors.red],
)),
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.white,
),
child: const Text(
'漸變色 — Taxze',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
),
),
只需要給外層Container加上LinearGradient漸變色,然后加上一個(gè)padding,這個(gè)padding就是邊框的粗細(xì),然后將內(nèi)部的Container背景設(shè)置為白色即可。這種方式非常簡(jiǎn)單。
但是這種方式呢不夠靈活,有局限性,而且可定制性受限,無(wú)法對(duì)每個(gè)邊框的漸變進(jìn)行獨(dú)立設(shè)置。所以對(duì)于邊框的漸變,更推薦使用CustomPainter來(lái)進(jìn)行繪制。
class GradientBoundPainter extends CustomPainter {
final List<Color> colors;
final double width;
final double height;
final double strokeWidth;
const GradientBoundPainter({
Key? key,
required this.colors,
required this.width,
required this.height,
this.strokeWidth = 2.0,
});
@override
void paint(Canvas canvas, Size size) {
//定義矩形的寬高
final rectWidth = width, rectHeight = height;
//圓角。必要的話可以將其作為變量傳進(jìn)來(lái)
final radius = 10.0;
//定義矩形的位置和尺寸
Rect rect = Offset(
size.width / 2 - rectWidth / 2, size.height / 2 - rectHeight / 2) &
Size(rectWidth, rectHeight);
//RRect.fromRectAndRadius一個(gè)具有圓角的矩形
RRect rRect = RRect.fromRectAndRadius(rect, Radius.circular(radius));
//繪制
final paint = Paint()
//創(chuàng)建線性漸變著色器
..shader = LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: colors,
).createShader(rect)
..strokeWidth = strokeWidth
//只繪制邊框而不填充
..style = PaintingStyle.stroke;
canvas.drawRRect(rRect, paint);
}
@override
bool shouldRepaint(covariant GradientBoundPainter oldDelegate) {
return oldDelegate.colors != colors;
}
}使用起來(lái)也很簡(jiǎn)單
Container(
width: 200,
height: 48,
child: LayoutBuilder(
builder: (BuildContext _, BoxConstraints bc) {
return CustomPaint(
painter: GradientBoundPainter(colors: [
const Color(0xFFFA709A),
const Color(0xFFFF8D1A),
], width: bc.maxWidth, height: bc.maxHeight),
// child: SizedBox(),
);
},
),
);
案例二:TabBar漸變色指示器
TabBar在開(kāi)發(fā)中是一種常用的組件,用于切換不同的內(nèi)容或功能模塊。而為了增強(qiáng)標(biāo)簽欄的可視效果,讓用戶在界面切換時(shí)獲得更加流暢和引人注目的體驗(yàn),市面上的各大app基本上都對(duì)TabBar的指示器indicator做了特殊化。而Flutter自帶的對(duì)indicator樣式修改就那么幾種,根本不夠用?。ㄟB改個(gè)長(zhǎng)度都要自己自定義)。那么在這個(gè)案例中,我們就來(lái)研究下,如何自定義繪制一個(gè)漸變色的indicator。
indicator需要一個(gè)Decoration對(duì)象,所以我們首先需要繼承于Decoration
class CustomTabIndicator extends Decoration {
}核心繪制邏輯如下
@override
BoxPainter createBoxPainter([VoidCallback? onChanged]) {
return _UnderlinePainter(this, onChanged);
}
///決定控制器寬度的方法
Rect _indicatorRectFor(Rect rect, TextDirection textDirection) {
assert(rect != null);
assert(textDirection != null);
final Rect indicator = insets.resolve(textDirection).deflateRect(rect);
// 希望的寬度
double wantWidth = this.width;
// 取中間坐標(biāo)
double cw = (indicator.left + indicator.right) / 2;
//這里是核心代碼
//下劃線靠左
// return Rect.fromLTWH(indicator.left,
// indicator.bottom - borderSide.width, wantWidth, borderSide.width);
//下劃線居中
return Rect.fromLTWH(cw - wantWidth / 2,
indicator.bottom - borderSide.width, wantWidth, borderSide.width);
}
@override
Path getClipPath(Rect rect, TextDirection textDirection) {
return Path()..addRect(_indicatorRectFor(rect, textDirection));
}
class _UnderlinePainter extends BoxPainter {
_UnderlinePainter(this.decoration, VoidCallback? onChanged)
: assert(decoration != null),
super(onChanged);
final CustomTabIndicator decoration;
///決定控制器邊角形狀的方法
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
assert(configuration != null);
assert(configuration.size != null);
final Rect rect = offset & configuration.size!;
final TextDirection textDirection = configuration.textDirection!;
//調(diào)用 decoration._indicatorRectFor(rect, textDirection) 方法計(jì)算出指示器的位置和尺寸,
//并使用 deflate 方法縮小矩形的大小,以便將邊框的一半包含在矩形內(nèi)。
final Rect indicator = decoration
._indicatorRectFor(rect, textDirection)
.deflate(decoration.borderSide.width / 2.0);
final gradient = LinearGradient(
colors: [Color(0xFFFA709A), Color(0xFFFF8C1A)],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
);
final Paint paint = decoration.borderSide.toPaint()
..shader = gradient.createShader(indicator)
..strokeCap = decoration.strokeCap; //這塊更改為想要的形狀
canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint);
}
}使用起來(lái)也很簡(jiǎn)單:
TabBar( controller: controller, indicator: const CustomTabIndicator(), ... ),

以下是一些有趣的例子
案例三:漸變色爆炸粒子

一個(gè)會(huì)隨即生成30個(gè)爆炸效果的漸變色粒子。
實(shí)現(xiàn)起來(lái)也很簡(jiǎn)單,以下是核心的生成邏輯:
//通過(guò)定時(shí)器調(diào)用生成粒子的函數(shù)
_timer = Timer.periodic(Duration(milliseconds: 500), (_) {
_explode();
});
//隨機(jī)生成粒子
void _explode() {
final random = Random();
_particles.clear();
for (int i = 0; i < 30; i++) {
final particle = Particle(
//顏色
color: _colors[random.nextInt(_colors.length)],
//角度
angle: random.nextDouble() * 2 * pi,
//距離
distance: random.nextDouble() * 120,
//大小
size: random.nextDouble() * 8 + 2,
//旋轉(zhuǎn)角度
rotation: random.nextDouble() * 2 * pi,
);
_particles.add(particle);
}
setState(() {});
}
//渲染
for (final particle in _particles)
Positioned(
//確定粒子在屏幕上的具體位置
left: particle.distance * cos(particle.angle) +
MediaQuery.of(context).size.width / 4,
top: particle.distance * sin(particle.angle) +
MediaQuery.of(context).size.height / 5,
//控制粒子的旋轉(zhuǎn)
child: Transform.rotate(
angle: particle.rotation,
child: Container(
width: particle.size,
height: particle.size,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: RadialGradient(
colors: [
particle.color.withOpacity(1.0),
particle.color.withOpacity(0.0),
],
),
),
),
),
),案例四:漸變色加載指示器

通過(guò)Animation和AnimationController來(lái)控制旋轉(zhuǎn)和顏色的變化。
核心邏輯
//將動(dòng)畫(huà)控制器與顏色過(guò)渡動(dòng)畫(huà)進(jìn)行關(guān)聯(lián)
_animation = _animationController.drive(
ColorTween(
begin: Colors.red,
end: Colors.purple,
),
);
AnimatedBuilder(
animation: _animationController,
builder: (BuildContext context, Widget? child) {
return Transform.rotate(
//控制旋轉(zhuǎn)
angle: _animationController.value * 2 * pi,
child: Container(
...
decoration: BoxDecoration(
shape: BoxShape.circle,
//控制漸變
gradient: LinearGradient(
colors: [
_animation.value!,
_animation.value!.withOpacity(0.5),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: Icon(...),
),
);
},
),總結(jié)
在本篇文章中,我們探討了幾個(gè)Flutter中漸變色的相關(guān)案例。Flutter提供了豐富的漸變色支持和靈活的定制選項(xiàng),使我們能夠輕松實(shí)現(xiàn)各種各樣的漸變色效果。無(wú)論是用于背景、文本、圖標(biāo)還是邊框,漸變色都能為應(yīng)用程序帶來(lái)生動(dòng)、多樣和吸引人的視覺(jué)效果。希望本篇文章對(duì)你理解和運(yùn)用Flutter中的漸變色相關(guān)內(nèi)容有所幫助,激發(fā)你的創(chuàng)造力~
以上就是Flutter中漸變色的使用案例分享的詳細(xì)內(nèi)容,更多關(guān)于Flutter漸變色的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- flutter FadeTransition實(shí)現(xiàn)透明度漸變動(dòng)畫(huà)
- Flutter 滾動(dòng)監(jiān)聽(tīng)及實(shí)戰(zhàn)appBar滾動(dòng)漸變的實(shí)現(xiàn)
- flutter仿微信底部圖標(biāo)漸變功能的實(shí)現(xiàn)代碼
- 淺談Flutter 中漸變的高級(jí)用法(3種)
- Flutter實(shí)現(xiàn)漸變色加描邊字體效果
- Flutter繪制3.4邊形及多邊形漸變動(dòng)畫(huà)實(shí)現(xiàn)示例
- Flutter實(shí)現(xiàn)一個(gè)支持漸變背景的Button示例詳解
相關(guān)文章
Android中默認(rèn)系統(tǒng)的聲音/大小修改和配置詳解
這篇文章主要給大家介紹了關(guān)于Android中默認(rèn)系統(tǒng)的聲音/大小修改和配置的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)各位Android開(kāi)發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-11-11
android 獲取本機(jī)的IP地址和mac物理地址的實(shí)現(xiàn)方法
本文主要介紹android 獲取本機(jī)的IP地址和mac物理地址的實(shí)現(xiàn)方法,這里提供示例代碼,實(shí)現(xiàn)功能,有需要的小伙伴可以參考下2016-09-09
AndroidStudio構(gòu)建項(xiàng)目提示錯(cuò)誤信息“unable to find valid certification”的
這篇文章主要介紹了AndroidStudio構(gòu)建項(xiàng)目提示“unable to find valid certification”最新解決方案,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05
android隱式意圖激活瀏覽器的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇android隱式意圖激活瀏覽器的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06
頁(yè)面未隨軟鍵盤(pán)上升及android隱藏軟鍵盤(pán)總結(jié)
這篇文章主要介紹了頁(yè)面未隨軟鍵盤(pán)上升及android隱藏軟鍵盤(pán)總結(jié),需要的朋友可以參考下2015-12-12
Android打開(kāi)系統(tǒng)相機(jī)并拍照的2種顯示方法
這篇文章主要介紹了Android打開(kāi)系統(tǒng)相機(jī)并拍照的2種顯示方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05
Android開(kāi)發(fā)之sqlite3命令行簡(jiǎn)單使用方法
這篇文章主要介紹了Android開(kāi)發(fā)之sqlite3命令行簡(jiǎn)單使用方法,分析了Android增刪改查等常用sqlite3的數(shù)據(jù)庫(kù)操作命令使用方法,需要的朋友可以參考下2016-02-02
Android單一實(shí)例全局可調(diào)用網(wǎng)絡(luò)加載彈窗
這篇文章主要為大家詳細(xì)介紹了Android單一實(shí)例全局可調(diào)用網(wǎng)絡(luò)加載彈窗,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12
android輕量級(jí)無(wú)侵入式管理數(shù)據(jù)庫(kù)自動(dòng)升級(jí)組件
這篇文章主要為大家介紹了android輕量級(jí)無(wú)侵入式管理數(shù)據(jù)庫(kù)自動(dòng)升級(jí)組件詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
Android編程開(kāi)發(fā)之NotiFication用法詳解
這篇文章主要介紹了Android編程開(kāi)發(fā)之NotiFication用法,結(jié)合實(shí)例形式較為詳細(xì)的分析了NotiFication的功能、使用技巧與注意事項(xiàng),需要的朋友可以參考下2015-12-12

