Flutter中漸變色的使用案例分享
前言
在日常的開發(fā)中,UI為了讓界面更加吸引人往往會在界面上用到大量的漸變色。那么在本文中,我們將通過幾個案例更好的去了解Flutter中漸變色的使用。讓我們開始探索Flutter世界中絢麗多彩的漸變色效果吧!
案例一:漸變色邊框
很多時候,一個簡單的邊框并不能滿足我們對于界面的美感要求。我們希望給邊框增添一些特殊的效果,讓它更加引人注目和獨(dú)特。而正是在這種情況下,漸變色邊框成為了一個合適的選擇。在Flutter中,實(shí)現(xiàn)漸變色邊框的方式有很多,有簡單的,有復(fù)雜的。最簡單的實(shí)現(xiàn)方式呢就是通過兩個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
漸變色,然后加上一個padding
,這個padding
就是邊框的粗細(xì),然后將內(nèi)部的Container
背景設(shè)置為白色即可。這種方式非常簡單。
但是這種方式呢不夠靈活,有局限性,而且可定制性受限,無法對每個邊框的漸變進(jìn)行獨(dú)立設(shè)置。所以對于邊框的漸變,更推薦使用CustomPainter
來進(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)來 final radius = 10.0; //定義矩形的位置和尺寸 Rect rect = Offset( size.width / 2 - rectWidth / 2, size.height / 2 - rectHeight / 2) & Size(rectWidth, rectHeight); //RRect.fromRectAndRadius一個具有圓角的矩形 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; } }
使用起來也很簡單
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
在開發(fā)中是一種常用的組件,用于切換不同的內(nèi)容或功能模塊。而為了增強(qiáng)標(biāo)簽欄的可視效果,讓用戶在界面切換時獲得更加流暢和引人注目的體驗(yàn),市面上的各大app基本上都對TabBar
的指示器indicator
做了特殊化。而Flutter自帶的對indicator
樣式修改就那么幾種,根本不夠用?。ㄟB改個長度都要自己自定義)。那么在這個案例中,我們就來研究下,如何自定義繪制一個漸變色的indicator
。
indicator
需要一個Decoration
對象,所以我們首先需要繼承于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) 方法計算出指示器的位置和尺寸, //并使用 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); } }
使用起來也很簡單:
TabBar( controller: controller, indicator: const CustomTabIndicator(), ... ),
以下是一些有趣的例子
案例三:漸變色爆炸粒子
一個會隨即生成30個爆炸效果的漸變色粒子。
實(shí)現(xiàn)起來也很簡單,以下是核心的生成邏輯:
//通過定時器調(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), ], ), ), ), ), ),
案例四:漸變色加載指示器
通過Animation
和AnimationController
來控制旋轉(zhuǎn)和顏色的變化。
核心邏輯
//將動畫控制器與顏色過渡動畫進(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é)
在本篇文章中,我們探討了幾個Flutter中漸變色的相關(guān)案例。Flutter提供了豐富的漸變色支持和靈活的定制選項(xiàng),使我們能夠輕松實(shí)現(xiàn)各種各樣的漸變色效果。無論是用于背景、文本、圖標(biāo)還是邊框,漸變色都能為應(yīng)用程序帶來生動、多樣和吸引人的視覺效果。希望本篇文章對你理解和運(yùn)用Flutter中的漸變色相關(guān)內(nèi)容有所幫助,激發(fā)你的創(chuàng)造力~
以上就是Flutter中漸變色的使用案例分享的詳細(xì)內(nèi)容,更多關(guān)于Flutter漸變色的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android中可以作為Log開關(guān)的一些操作及安全性詳解
Android的調(diào)試好伙伴Log在調(diào)試時非常有用,基本可以看Log而無需單點(diǎn)調(diào)試,尤其對實(shí)時大數(shù)據(jù)量的設(shè)備調(diào)試尤其有效,下面這篇文章就來給大家詳細(xì)介紹關(guān)于Android中可以作為Log開關(guān)的一些操作及安全性的相關(guān)資料,需要的朋友可以參考下。2017-12-1221天學(xué)習(xí)android開發(fā)教程之XML解析與生成
21天學(xué)習(xí)android開發(fā)教程之XML解析與生成,使用SAX來解析XML,在Android里面可以使用SAX和DOM,DOM需要把整個XML文件讀入內(nèi)存再解析,比較消耗內(nèi)存,而SAX基于事件驅(qū)動的處理方式,可以在各節(jié)點(diǎn)觸發(fā)回調(diào)函數(shù),需要的朋友可以參考下2016-02-02android基礎(chǔ)教程之a(chǎn)ndroid的listview與edittext沖突解決方法
這篇文章主要介紹了android的listview與edittext沖突解決方法,需要的朋友可以參考下2014-02-02Android 7.0調(diào)用相機(jī)崩潰詳解及解決辦法
這篇文章主要介紹了 Android 7.0調(diào)用相機(jī)崩潰詳解及解決辦法的相關(guān)資料,需要的朋友可以參考下2016-12-12Android實(shí)現(xiàn)底部導(dǎo)航欄的主界面
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)底部導(dǎo)航欄的主界面 ,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-09-09Android Studio實(shí)現(xiàn)幀動畫
這篇文章主要為大家詳細(xì)介紹了Android Studio實(shí)現(xiàn)幀動畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11Android適配安卓6.0藍(lán)牙通訊實(shí)現(xiàn)過程
這篇文章主要為大家詳細(xì)介紹了Android適配安卓6.0藍(lán)牙通訊實(shí)現(xiàn)過程,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-09-09