中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Flutter進階之實現動畫效果(二)

發布時間:2020-10-02 17:16:43 來源:腳本之家 閱讀:168 作者:何小有 欄目:移動開發

在上一篇文章:Flutter進階—實現動畫效果(一)的最后,我們說到需要一個處理程序混亂的概念。在這一篇文章中,我們會引入補間,它是構建動畫代碼的一個非常簡單的概念,主要作用是用面向對象的方法替代之前面向過程的方法。tween是一個值,它描述了其他值的空間中的兩個點之間的路徑,比如條形圖的動畫值從0運行到1。

補間在Dart中表示類型為Tween的對象

abstract class Tween<T> {
 final T begin;
 final T end;

 Tween(this.begin, this.end);

 T lerp(double t);
}

術語lerp來自計算機圖形學領域,是線性插值(作為名詞)和線性內插(作為動詞)的縮寫。參數t是動畫值,補間應該從begin(當t為0時)到end(當t為1時)。

FlutterSDK的Tween類與Dart非常相似,但是一個支持變化begin和end的具體類。我們可以使用單個Tween來整理代碼,用于處理條形圖高度。

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 }):創建tween(補間)
  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
    )
    返回給定動畫的當前值的內插值
    當動畫值分別為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
      )
      返回一個由給定動畫驅動的新動畫,但它承擔由該對象確定的值
       */
      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將條形高度動畫終點包裝在一個值中,它完全與AnimationController和CustomPainter進行接口,因為Flutter框架現在會在每個動畫時間點上標記CustomPaint進行重繪,而不是將整個MyHomePage子樹標記為重構、重新布局和重繪。這些都是顯示的改進,但是,補間的概念不止如此,它提供了組織我們的想法和代碼的結構。

回到我們的代碼,我們需要一個Bar類型和一個BarTween來動畫化它。我們將與bar相關的類提取到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類的靜態方法BarTween.lerp。DartSDK中沒有double.lerp,所以我們使用dart:ui包中的lerpDouble函數來達到同樣的效果。

現在我們的應用程序可以用條形圖重新顯示。

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),
    ),
  );
 }
}

未完待續。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

巴青县| 阿拉善右旗| 九寨沟县| 乐陵市| 遵义县| 民丰县| 桐城市| 安图县| 宁城县| 靖远县| 陵川县| 雅江县| 鱼台县| 石门县| 白沙| 饶平县| 景谷| 旌德县| 彭州市| 库伦旗| 兴业县| 凤翔县| 乐都县| 侯马市| 田林县| 永川市| 乌鲁木齐县| 葫芦岛市| 泗阳县| 扶沟县| 马鞍山市| 怀宁县| 荥阳市| 五莲县| 文成县| 四子王旗| 焉耆| 德清县| 黎城县| 华池县| 舞钢市|