Flutter進(jìn)階之實(shí)現(xiàn)動畫效果(二)
在上一篇文章:Flutter進(jìn)階—實(shí)現(xiàn)動畫效果(一)的最后,我們說到需要一個處理程序混亂的概念。在這一篇文章中,我們會引入補(bǔ)間,它是構(gòu)建動畫代碼的一個非常簡單的概念,主要作用是用面向?qū)ο蟮姆椒ㄌ娲懊嫦蜻^程的方法。tween是一個值,它描述了其他值的空間中的兩個點(diǎn)之間的路徑,比如條形圖的動畫值從0運(yùn)行到1。
補(bǔ)間在Dart中表示類型為Tween的對象
abstract class Tween<T> {
final T begin;
final T end;
Tween(this.begin, this.end);
T lerp(double t);
}
術(shù)語lerp來自計(jì)算機(jī)圖形學(xué)領(lǐng)域,是線性插值(作為名詞)和線性內(nèi)插(作為動詞)的縮寫。參數(shù)t是動畫值,補(bǔ)間應(yīng)該從begin(當(dāng)t為0時)到end(當(dāng)t為1時)。
FlutterSDK的Tween類與Dart非常相似,但是一個支持變化begin和end的具體類。我們可以使用單個Tween來整理代碼,用于處理?xiàng)l形圖高度。
import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';
import 'dart:math';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
final random = new Random();
int dataSet = 50;
AnimationController animation;
Tween<double> tween;
@override
void initState() {
super.initState();
animation = new AnimationController(
duration: const Duration(milliseconds: 300),
vsync: this
);
// Tween({T begin, T end }):創(chuàng)建tween(補(bǔ)間)
tween = new Tween<double>(begin: 0.0, end: dataSet.toDouble());
animation.forward();
}
@override
void dispose() {
animation.dispose();
super.dispose();
}
void changeData() {
setState(() {
dataSet = random.nextInt(100);
tween = new Tween<double>(
/*
@override
T evaluate(
Animation<double> animation
)
返回給定動畫的當(dāng)前值的內(nèi)插值
當(dāng)動畫值分別為0.0或1.0時,此方法返回begin和end
*/
begin: tween.evaluate(animation),
end: dataSet.toDouble()
);
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),
/*
Animation<T> animate(
Animation<double> parent
)
返回一個由給定動畫驅(qū)動的新動畫,但它承擔(dān)由該對象確定的值
*/
painter: new BarChartPainter(tween.animate(animation))
)
),
floatingActionButton: new FloatingActionButton(
onPressed: changeData,
child: new Icon(Icons.refresh),
),
);
}
}
class BarChartPainter extends CustomPainter {
static const barWidth = 10.0;
BarChartPainter(Animation<double> animation)
: animation = animation,
super(repaint: animation);
final Animation<double> animation;
@override
void paint(Canvas canvas, Size size) {
final barHeight = animation.value;
final paint = new Paint()
..color = Colors.blue[400]
..style = PaintingStyle.fill;
canvas.drawRect(
new Rect.fromLTWH(
size.width-barWidth/2.0,
size.height-barHeight,
barWidth,
barHeight
),
paint
);
}
@override
bool shouldRepaint(BarChartPainter old) => false;
}
我們使用Tween將條形高度動畫終點(diǎn)包裝在一個值中,它完全與AnimationController和CustomPainter進(jìn)行接口,因?yàn)镕lutter框架現(xiàn)在會在每個動畫時間點(diǎn)上標(biāo)記CustomPaint進(jìn)行重繪,而不是將整個MyHomePage子樹標(biāo)記為重構(gòu)、重新布局和重繪。這些都是顯示的改進(jìn),但是,補(bǔ)間的概念不止如此,它提供了組織我們的想法和代碼的結(jié)構(gòu)。
回到我們的代碼,我們需要一個Bar類型和一個BarTween來動畫化它。我們將與bar相關(guān)的類提取到bar.dart文件中,放到main.dart同級目錄下。
import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';
import 'dart:ui' show lerpDouble;
class Bar {
Bar(this.height);
final double height;
static Bar lerp(Bar begin, Bar end, double t) {
return new Bar(lerpDouble(begin.height, end.height, 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 barWidth = 10.0;
BarChartPainter(Animation<Bar> animation)
: animation = animation,
super(repaint: animation);
final Animation<Bar> animation;
@override
void paint(Canvas canvas, Size size) {
final bar = animation.value;
final paint = new Paint()
..color = Colors.blue[400]
..style = PaintingStyle.fill;
canvas.drawRect(
new Rect.fromLTWH(
size.width-barWidth/2.0,
size.height-bar.height,
barWidth,
bar.height
),
paint
);
}
@override
bool shouldRepaint(BarChartPainter old) => false;
}
我們遵循FlutterSDK的慣例來定義Bar類的靜態(tài)方法BarTween.lerp。DartSDK中沒有double.lerp,所以我們使用dart:ui包中的lerpDouble函數(shù)來達(dá)到同樣的效果。
現(xiàn)在我們的應(yīng)用程序可以用條形圖重新顯示。
import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';
import 'dart:math';
import 'bar.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
final random = new Random();
AnimationController animation;
BarTween tween;
@override
void initState() {
super.initState();
animation = new AnimationController(
duration: const Duration(milliseconds: 300),
vsync: this
);
tween = new BarTween(new Bar(0.0), new Bar(50.0));
animation.forward();
}
@override
void dispose() {
animation.dispose();
super.dispose();
}
void changeData() {
setState(() {
tween = new BarTween(
tween.evaluate(animation),
new Bar(100.0 * random.nextDouble()),
);
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),
),
);
}
}
未完待續(xù)。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Flutter進(jìn)階之實(shí)現(xiàn)動畫效果(一)
- Flutter進(jìn)階之實(shí)現(xiàn)動畫效果(十)
- Flutter進(jìn)階之實(shí)現(xiàn)動畫效果(三)
- Flutter進(jìn)階之實(shí)現(xiàn)動畫效果(五)
- Flutter進(jìn)階之實(shí)現(xiàn)動畫效果(九)
- Flutter進(jìn)階之實(shí)現(xiàn)動畫效果(四)
- Flutter進(jìn)階之實(shí)現(xiàn)動畫效果(八)
- Flutter進(jìn)階之實(shí)現(xiàn)動畫效果(七)
- Flutter進(jìn)階之實(shí)現(xiàn)動畫效果(六)
- Flutter實(shí)戰(zhàn)教程之酷炫的開關(guān)動畫效果
相關(guān)文章
Android使用URLConnection提交請求的實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了Android使用URLConnection提交請求的實(shí)現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10
基于Android-Skin-Loader實(shí)現(xiàn)換膚效果
這篇文章主要為大家詳細(xì)介紹了基于Android-Skin-Loader實(shí)現(xiàn)換膚效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-03-03
基于Flutter實(shí)現(xiàn)按位置大小比例布局的控件
做視頻監(jiān)控項(xiàng)目時需要需要展示多分屏,比如2x2、3x3、414等等,所以本文為大家介紹了如何基于Flutter實(shí)現(xiàn)按位置大小比例布局的控件,需要的可以參考一下2023-08-08
解決android studio 打開java文件 內(nèi)容全變了的問題
這篇文章主要介紹了解決android studio 打開java文件 內(nèi)容全變了的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
Android之IphoneTreeView帶組指示器的ExpandableListView效果
在正在顯示的最上面的組的標(biāo)簽位置添加一個和組視圖完全一樣的視圖,作為組標(biāo)簽。這個標(biāo)簽的位置要隨著列表的滑動不斷變化,以保持總是顯示在最上方,并且該消失的時候就消失2013-06-06
Android組件之DrawerLayout實(shí)現(xiàn)抽屜菜單
DrawerLayout組件同樣是V4包中的組件,也是直接繼承于ViewGroup類,所以這個類也是一個容器類。接下來通過本文給大家介紹Android組件之DrawerLayout實(shí)現(xiàn)抽屜菜單,感興趣的朋友一起學(xué)習(xí)吧2016-02-02

