Flutter進階之實現(xiàn)動畫效果(四)
在上一篇文章:Flutter進階—實現(xiàn)動畫效果(三)中,實現(xiàn)了一個隨機高度、顏色的條形。這一篇文章我們會實現(xiàn)多個條形,同樣是隨機高度、顏色。
首先在bar.dart中創(chuàng)建BarChart類,并使用固定長度的Bar實例列表。我們將使用5個條形,表示一周的5個工作日。然后,我們需要將創(chuàng)建空白和隨機實例的責(zé)任從Bar轉(zhuǎn)移到BarChart。
import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';
import 'dart:ui' show lerpDouble;
import 'dart:math';
import 'color_palette.dart';
class BarChart {
static const int barCount = 5;
final List<Bar> bars;
BarChart(this.bars) {
assert(bars.length == barCount);
}
factory BarChart.empty() {
return new BarChart(
/*
List.filled(
int length,
E fill, {
bool growable: false
}
)
創(chuàng)建給定長度的固定長度列表,并用fill在每個位置初始化值
length必須是非負(fù)整數(shù)
*/
new List.filled(
barCount,
new Bar(0.0, Colors.transparent)
)
);
}
factory BarChart.random(Random random) {
final Color color = ColorPalette.primary.random(random);
return new BarChart(
/*
List.generate(
int length,
E generator(
int index
), {
bool growable: true
}
)
創(chuàng)建給定長度的固定長度列表,并用generator創(chuàng)建的值在每個位置初始化值
創(chuàng)建的列表是固定長度,除非growable為true
*/
new List.generate(
barCount,
(i) => new Bar(
random.nextDouble()*100.0,
color
)
)
);
}
static BarChart lerp(BarChart begin, BarChart end, double t) {
return new BarChart(
new List.generate(
barCount,
(i) => Bar.lerp(begin.bars[i], end.bars[i], t)
)
);
}
}
class BarChartTween extends Tween<BarChart> {
BarChartTween(BarChart begin, BarChart end) : super(begin: begin, end: end);
@override
BarChart lerp(double t) => BarChart.lerp(begin, end, t);
}
class Bar {
Bar(this.height, this.color);
final double height;
final Color color;
static Bar lerp(Bar begin, Bar end, double t) {
return new Bar(
lerpDouble(begin.height, end.height, t),
Color.lerp(begin.color, end.color, t)
);
}
}
class BarTween extends Tween<Bar> {
BarTween(Bar begin, Bar end) : super(begin: begin, end: end);
@override
Bar lerp(double t) => Bar.lerp(begin, end, t);
}
class BarChartPainter extends CustomPainter {
static const barWidthFraction = 0.75;
BarChartPainter(Animation<BarChart> animation)
: animation = animation,
super(repaint: animation);
final Animation<BarChart> animation;
@override
void paint(Canvas canvas, Size size) {
void drawBar(Bar bar, double x, double width, Paint paint) {
paint.color = bar.color;
canvas.drawRect(
new Rect.fromLTWH(
x,
size.height-bar.height,
width,
bar.height
),
paint
);
}
/*
Paint:Canvas繪制時使用的樣式說明
style:是否繪制內(nèi)部的形狀、形狀的邊緣或兩者都有,默認(rèn)為PaintingStyle.fill
*/
final paint = new Paint()..style = PaintingStyle.fill;
final chart = animation.value;
// 每個條形占用的空間寬度
final barDistance = size.width/(1+chart.bars.length);
// 每個條形占用空間75%的寬度
final barWidth = barDistance*barWidthFraction;
// 用于計算每個條形的x坐標(biāo)點
var x = barDistance-barWidth/2;
for (final bar in chart.bars) {
drawBar(bar, x, barWidth, paint);
x += barDistance;
}
}
@override
bool shouldRepaint(BarChartPainter old) => false;
}
BarChartPainter在條形之間均勻分配可用寬度,并使每個條形占用可用寬度的75%。接下來我們要更新main.dart,用BarChart、BarChartTween替換Bar、BarTween。
// ...
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
final random = new Random();
AnimationController animation;
BarChartTween tween;
@override
void initState() {
super.initState();
animation = new AnimationController(
duration: const Duration(milliseconds: 300),
vsync: this
);
tween = new BarChartTween(new BarChart.empty(), new BarChart.random(random));
animation.forward();
}
@override
void dispose() {
animation.dispose();
super.dispose();
}
void changeData() {
setState(() {
tween = new BarChartTween(
tween.evaluate(animation),
new BarChart.random(random),
);
animation.forward(from: 0.0);
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new CustomPaint(
size: new Size(200.0, 100.0),
painter: new BarChartPainter(tween.animate(animation))
)
),
floatingActionButton: new FloatingActionButton(
onPressed: changeData,
child: new Icon(Icons.refresh),
),
);
}
}
現(xiàn)在應(yīng)用程序的效果如下圖:

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
RecyclerView實現(xiàn)仿支付寶應(yīng)用管理
這篇文章主要為大家詳細(xì)介紹了RecyclerView實現(xiàn)仿支付寶應(yīng)用管理的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-04-04
Android應(yīng)用中使用DOM方式解析XML格式數(shù)據(jù)的基本方法
這篇文章主要介紹了Android應(yīng)用中使用DOM方式解析XML格式數(shù)據(jù)的基本方法,值得注意的是DOM方式解析的效率并不高,在數(shù)據(jù)量大的時候并不推薦使用,需要的朋友可以參考下2016-04-04
Android 自定義SeekBar動態(tài)改變硬件音量大小實現(xiàn)和音量鍵的同步(推薦)
這篇文章主要介紹了 Android 自定義SeekBar動態(tài)改變硬件音量大小實現(xiàn)和音量鍵的同步效果,整段代碼簡單易懂,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-01-01

