<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在上一篇普通的載入千篇一律,有趣的 loading 萬里挑一 中,我們介紹了使用Path
類的PathMetrics
屬性來控制繪製點在路徑上運動來實現比較有趣的loading
效果。有評論說因為是黑色背景,所以看著好看。黑色背景確實顯得高階一點,但是並不是其他配色也不行,本篇我們來封裝一個可以自定義設定前景色和背景色的Loading
元件。
loading
元件共定義4個入口引數:
得到的Loading
元件類如下所示:
class LoadingAnimations extends StatefulWidget { final Color bgColor; final Color foregroundColor; String? loadingText; final double size; LoadingAnimations( {required this.foregroundColor, required this.bgColor, this.loadingText, this.size = 100.0, Key? key}) : super(key: key); @override _LoadingAnimationsState createState() => _LoadingAnimationsState(); }
我們先來實現一個圓形的loading
,效果如下所示。
這裡繪製了兩組沿著一個大圓運動的軸對稱的實心圓,半徑依次減小,圓心間距隨著動畫時間逐步拉大。實際上實現的核心還是基於Path
的PathMetrics
。具體實現程式碼如下:
_drawCircleLoadingAnimaion( Canvas canvas, Size size, Offset center, Paint paint) { final radius = boxSize / 2; final ballCount = 6; final ballRadius = boxSize / 15; var circlePath = Path() ..addOval(Rect.fromCircle(center: center, radius: radius)); var circleMetrics = circlePath.computeMetrics(); for (var pathMetric in circleMetrics) { for (var i = 0; i < ballCount; ++i) { var lengthRatio = animationValue * (1 - i / ballCount); var tangent = pathMetric.getTangentForOffset(pathMetric.length * lengthRatio); var ballPosition = tangent!.position; canvas.drawCircle(ballPosition, ballRadius / (1 + i), paint); canvas.drawCircle( Offset(size.width - tangent.position.dx, size.height - tangent.position.dy), ballRadius / (1 + i), paint); } } }
其中路徑比例為lengthRatio
,通過animationValue
乘以一個係數使得實心圓的間距越來越大 ,同時通過Offset(size.width - tangent.position.dx, size.height - tangent.position.dy)
繪製了一組對對稱的實心圓,這樣整體就有一個圓形的效果了,動起來也會更有趣一點。
橢圓和圓形沒什麼區別,這裡我們搞個漸變的效果看看,利用之前介紹過的Paint
的shader
可以實現漸變色繪製效果。
實現程式碼如下所示。
final ballCount = 6; final ballRadius = boxSize / 15; var ovalPath = Path() ..addOval(Rect.fromCenter( center: center, width: boxSize, height: boxSize / 1.5)); paint.shader = LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [this.foregroundColor, this.bgColor], ).createShader(Offset.zero & size); var ovalMetrics = ovalPath.computeMetrics(); for (var pathMetric in ovalMetrics) { for (var i = 0; i < ballCount; ++i) { var lengthRatio = animationValue * (1 - i / ballCount); var tangent = pathMetric.getTangentForOffset(pathMetric.length * lengthRatio); var ballPosition = tangent!.position; canvas.drawCircle(ballPosition, ballRadius / (1 + i), paint); canvas.drawCircle( Offset(size.width - tangent.position.dx, size.height - tangent.position.dy), ballRadius / (1 + i), paint); } }
當然,如果漸變色的顏色更豐富一點會更有趣些。
通過貝塞爾曲線構建一條Path
,讓一組圓形沿著貝塞爾曲線運動的Loading
效果也很有趣。
原理和圓形的一樣,首先是構建貝塞爾曲線Path
,程式碼如下。
var bezierPath = Path() ..moveTo(size.width / 2 - boxSize / 2, center.dy) ..quadraticBezierTo(size.width / 2 - boxSize / 4, center.dy - boxSize / 4, size.width / 2, center.dy) ..quadraticBezierTo(size.width / 2 + boxSize / 4, center.dy + boxSize / 4, size.width / 2 + boxSize / 2, center.dy) ..quadraticBezierTo(size.width / 2 + boxSize / 4, center.dy - boxSize / 4, size.width / 2, center.dy) ..quadraticBezierTo(size.width / 2 - boxSize / 4, center.dy + boxSize / 4, size.width / 2 - boxSize / 2, center.dy);
這裡實際是構建了兩條貝塞爾曲線,先從左邊到右邊,然後再折回來。之後就是運動的實心圓了,這個只是數量上多了,ballCount
為30
,這樣效果看著就有一種拖影的效果。
var ovalMetrics = bezierPath.computeMetrics(); for (var pathMetric in ovalMetrics) { for (var i = 0; i < ballCount; ++i) { var lengthRatio = animationValue * (1 - i / ballCount); var tangent = pathMetric.getTangentForOffset(pathMetric.length * lengthRatio); var ballPosition = tangent!.position; canvas.drawCircle(ballPosition, ballRadius / (1 + i), paint); canvas.drawCircle( Offset(size.width - tangent.position.dx, size.height - tangent.position.dy), ballRadius / (1 + i), paint); } }
這裡還可以改變運動方向,實現一些其他的效果,例如下面的效果,第二組圓球的繪製位置實際上是第一組圓球的x、y座標的互換。
var lengthRatio = animationValue * (1 - i / ballCount); var tangent = pathMetric.getTangentForOffset(pathMetric.length * lengthRatio); var ballPosition = tangent!.position; canvas.drawCircle(ballPosition, ballRadius / (1 + i), paint); canvas.drawCircle(Offset(tangent.position.dy, tangent.position.dx), ballRadius / (1 + i), paint);
我們來看如何使用我們定義的這個元件,使用程式碼如下,我們用Future延遲模擬了一個載入效果,在載入過程中使用loading
指示載入過程,載入完成後顯示圖片。
class _LoadingDemoState extends State<LoadingDemo> { var loaded = false; @override void initState() { super.initState(); Future.delayed(Duration(seconds: 5), () { setState(() { loaded = true; }); }); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar( title: Text('Loading 使用'), ), body: Center( child: loaded ? Image.asset( 'images/beauty.jpeg', width: 100.0, ) : LoadingAnimations( foregroundColor: Colors.blue, bgColor: Colors.white, size: 100.0, ), ), ); }
最終執行的效果如下,原始碼已提交至:繪圖相關原始碼,檔名為loading_animations.dart
。
本篇介紹了Loading
元件的封裝方法,核心要點還是利用Path
和動畫控制繪製元素的運動軌跡來實現更有趣的效果。在實際應用過程中,也可以根據互動設計的需要,做一些其他有趣的載入動效,提高等待過程的趣味性。
到此這篇關於利用Android封裝一個有趣的Loading元件的文章就介紹到這了,更多相關Android封裝Loading元件內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45