真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

使用Flutter怎么實(shí)現(xiàn)動(dòng)畫(huà)效果

本篇文章為大家展示了使用Flutter怎么實(shí)現(xiàn)動(dòng)畫(huà)效果,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

在靈石等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì) 網(wǎng)站設(shè)計(jì)制作按需策劃,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站建設(shè),全網(wǎng)營(yíng)銷(xiāo)推廣,成都外貿(mào)網(wǎng)站制作,靈石網(wǎng)站建設(shè)費(fèi)用合理。

首先,我們需要?jiǎng)?chuàng)建一個(gè)新項(xiàng)目myapp,然后把main.dart的內(nèi)容替換成下面的代碼

import 'package:flutter/material.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 {
 // Random([int seed ]):創(chuàng)建一個(gè)隨機(jī)數(shù)生成器
 final random = new Random();
 int dataSet;

 void changeData() {
 setState(() {
 dataSet = random.nextInt(100);
 });
 }

 @override
 Widget build(BuildContext context) {
 return new Scaffold(
 body: new Center(
 child: new Text('數(shù)據(jù)集:$dataSet'),
 ),
 floatingActionButton: new FloatingActionButton(
 onPressed: changeData,
 child: new Icon(Icons.refresh),
 ),
 );
 }
}

啟動(dòng)項(xiàng)目后,應(yīng)用程序會(huì)顯示一個(gè)居中的文本標(biāo)簽,顯示“數(shù)據(jù)集:null”和浮動(dòng)按鈕來(lái)刷新數(shù)據(jù)。

我們的應(yīng)用程序生成的樹(shù)結(jié)構(gòu)如下圖所示,您可以看到,雖然控件概念相當(dāng)廣泛,但每個(gè)具體的控件類型通常具有非常重要的責(zé)任。

使用Flutter怎么實(shí)現(xiàn)動(dòng)畫(huà)效果

通過(guò)定義用戶界面的不可變的控件樹(shù),修改用戶界面的唯一方法是重建樹(shù),當(dāng)下一幀到期時(shí)告訴Flutter一個(gè)子樹(shù)所依賴的一些狀態(tài)已經(jīng)改變了。這種狀態(tài)依賴的子樹(shù)的根必須是StatefulWidget,一個(gè)StatefulWidget不是可變的,但是它的子樹(shù)是由State對(duì)象構(gòu)建的。Flutter在構(gòu)建期間通過(guò)樹(shù)重建保留State對(duì)象并將其附加到新樹(shù)中的各自的控件,然后,它們確定該控件的子樹(shù)是如何構(gòu)建的。在我們的應(yīng)用程序中,MyHomePage是以_MyHomePageState為其狀態(tài)的StatefulWidget,每當(dāng)用戶按下按鈕時(shí),我們執(zhí)行一些代碼來(lái)更改_MyHomePageState。我們已經(jīng)用setState劃分了這個(gè)變化,以便Flutter可以進(jìn)行內(nèi)部管理,并調(diào)度控件樹(shù)進(jìn)行重建。當(dāng)發(fā)生這種情況時(shí),_MyHomePageState將構(gòu)建一個(gè)稍微不同的子樹(shù),這個(gè)子樹(shù)以新的MyHomePage實(shí)例為根。

不可變的控件和狀態(tài)依賴的子樹(shù)是Flutter提供的主要工具,用于處理響應(yīng)異步事件(比如按鈕、定時(shí)器刻度或輸入數(shù)據(jù))的復(fù)雜用戶界面中的狀態(tài)管理的復(fù)雜性。

我們的應(yīng)用程序?qū)⒈3趾?jiǎn)單的控件結(jié)構(gòu),但我們會(huì)做一些動(dòng)畫(huà)定制圖形,第一步是用一個(gè)非常簡(jiǎn)單的圖表替換每個(gè)數(shù)據(jù)集的文本顯示。由于數(shù)據(jù)集當(dāng)前僅有一個(gè)在0~100之間數(shù)字,所以圖表將是一個(gè)帶有單個(gè)條形的條形圖,其高度由該數(shù)字確定,我們將使用初始值50來(lái)避免高度為null。

import 'package:flutter/material.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 {
 // Random([int seed ]):創(chuàng)建一個(gè)隨機(jī)數(shù)生成器
 final random = new Random();
 int dataSet = 50;

 void changeData() {
 setState(() {
 dataSet = random.nextInt(100);
 });
 }

 @override
 Widget build(BuildContext context) {
 return new Scaffold(
 body: new Center(
 child: new CustomPaint(
 size: new Size(200.0, 100.0),
 painter: new BarChartPainter(dataSet.toDouble())
 )
 ),
 floatingActionButton: new FloatingActionButton(
 onPressed: changeData,
 child: new Icon(Icons.refresh),
 ),
 );
 }
}

// CustomPaint:是將繪畫(huà)委托給CustomPainter策略的控件
class BarChartPainter extends CustomPainter {
 static const barWidth = 10.0;

 BarChartPainter(this.barHeight);
 final double barHeight;

 /*
 void paint(
 Canvas canvas,
 Size size
 )
 當(dāng)對(duì)象需要繪制時(shí)調(diào)用,它給出Canvas的坐標(biāo)空間,使得原點(diǎn)位于框的左上角,
 框的面積是size參數(shù)的大小
 */
 @override
 void paint(Canvas canvas, Size size) {
 final paint = new Paint()
 ..color = Colors.blue[400]
 ..style = PaintingStyle.fill;
 // drawRect:使用給定的Paint繪制一個(gè)矩形,是否填充或描邊(或兩者)是由Paint.style控制
 canvas.drawRect(
 // Rect.fromLTWH(double left, double top, double width, double height):
 // 從左上角和上邊緣構(gòu)造一個(gè)矩形,并設(shè)置其寬度和高度
 new Rect.fromLTWH(
 size.width-barWidth/2.0,
 size.height-barHeight,
 barWidth,
 barHeight
 ),
 paint
 );
 }

 /*
 bool shouldRepaint(
 CustomPainter,
 oldDelegate
 )
 當(dāng)定制繪畫(huà)委托類的新實(shí)例被提供給RenderCustomPaint對(duì)象時(shí),
 或任何時(shí)候使用自定義繪畫(huà)委托類的新實(shí)例創(chuàng)建新的CustomPaint對(duì)象
 (這相當(dāng)于同一件事,因?yàn)楹笳呤且郧罢邔?shí)施)
 */
 @override
 bool shouldRepaint(BarChartPainter old) => barHeight != old.barHeight;
}

下一步是添加動(dòng)畫(huà),每當(dāng)數(shù)據(jù)集發(fā)生變化時(shí),我們希望該欄可以平滑而不是突然地改變高度。Flutter有一個(gè)AnimationController的概念,用于編排動(dòng)畫(huà),通過(guò)注冊(cè)一個(gè)監(jiān)聽(tīng)器,我們被告知當(dāng)動(dòng)畫(huà)值(0.0~1.0)改變時(shí)。每當(dāng)發(fā)生這種情況,我們可以像以前一樣調(diào)用setState并更新_MyHomePageState。

import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';
import 'dart:math';
import 'dart:ui' show lerpDouble;

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 with TickerProviderStateMixin {
 // Random([int seed ]):創(chuàng)建一個(gè)隨機(jī)數(shù)生成器
 final random = new Random();
 int dataSet = 50;
 AnimationController animation;
 double startHeight;
 double currentHeight;
 double endHeight;

 /*
 @protected
 @mustCallSuper
 void initState()
 將此對(duì)象插入樹(shù)中時(shí)調(diào)用
 該框架將為其創(chuàng)建的每個(gè)State對(duì)象精確地調(diào)用此方法一次
 */
 @override
 void initState() {
 super.initState();
 /*
 AnimationController({
 double value,
 Duration duration,
 String debugLabel,
 double lowerBound: 0.0,
 double upperBound: 1.0,
 TickerProvider vsync
 })
 創(chuàng)建動(dòng)畫(huà)控制器
 */
 animation = new AnimationController(
 // 這個(gè)動(dòng)畫(huà)應(yīng)該持續(xù)的時(shí)間長(zhǎng)短
 duration: const Duration(milliseconds: 300),
 vsync: this
 )
 /*
 void addListener(
 VoidCallback listener
 )
 每次動(dòng)畫(huà)值更改時(shí)調(diào)用監(jiān)聽(tīng)器
 可以使用removeListener刪除監(jiān)聽(tīng)器
 */
 ..addListener((){
 setState((){
 /*
 double lerpDouble(
 num a,
 num b,
 double t
 )
 在兩個(gè)數(shù)字之間進(jìn)行線性內(nèi)插
 return a + (b - a) * t;
 */
 currentHeight = lerpDouble(
 startHeight,
 endHeight,
 animation.value
 );
 });
 });
 startHeight = 0.0;
 currentHeight = 0.0;
 endHeight = dataSet.toDouble();
 // 開(kāi)始向前運(yùn)行這個(gè)動(dòng)畫(huà)(朝向最后)
 animation.forward();
 }

 /*
 @override
 void dispose()
 當(dāng)該對(duì)象永久從樹(shù)中刪除時(shí)調(diào)用
 當(dāng)該State對(duì)象永遠(yuǎn)不會(huì)再次構(gòu)建時(shí),該框架調(diào)用此方法
 框架調(diào)用dispose后,該State對(duì)象被視為已卸載,并且mounted屬性為false,此時(shí)調(diào)用setState是一個(gè)錯(cuò)誤
 生命周期的這個(gè)階段是終點(diǎn):沒(méi)有辦法重新安裝dispose的State對(duì)象
 */
 @override
 void dispose() {
 animation.dispose();
 super.dispose();
 }

 void changeData() {
 setState(() {
 startHeight = currentHeight;
 dataSet = random.nextInt(100);
 endHeight = 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),
 painter: new BarChartPainter(currentHeight)
 )
 ),
 floatingActionButton: new FloatingActionButton(
 onPressed: changeData,
 child: new Icon(Icons.refresh),
 ),
 );
 }
}

// CustomPaint:是將繪畫(huà)委托給CustomPainter策略的控件
class BarChartPainter extends CustomPainter {
 static const barWidth = 10.0;

 BarChartPainter(this.barHeight);
 final double barHeight;

 /*
 void paint(
 Canvas canvas,
 Size size
 )
 當(dāng)對(duì)象需要繪制時(shí)調(diào)用,它給出Canvas的坐標(biāo)空間,使得原點(diǎn)位于框的左上角,
 框的面積是size參數(shù)的大小
 */
 @override
 void paint(Canvas canvas, Size size) {
 final paint = new Paint()
 ..color = Colors.blue[400]
 ..style = PaintingStyle.fill;
 // drawRect:使用給定的Paint繪制一個(gè)矩形,是否填充或描邊(或兩者)是由Paint.style控制
 canvas.drawRect(
 // Rect.fromLTWH(double left, double top, double width, double height):
 // 從左上角和上邊緣構(gòu)造一個(gè)矩形,并設(shè)置其寬度和高度
 new Rect.fromLTWH(
 size.width-barWidth/2.0,
 size.height-barHeight,
 barWidth,
 barHeight
 ),
 paint
 );
 }

 /*
 bool shouldRepaint(
 CustomPainter,
 oldDelegate
 )
 當(dāng)定制繪畫(huà)委托類的新實(shí)例被提供給RenderCustomPaint對(duì)象時(shí),
 或任何時(shí)候使用自定義繪畫(huà)委托類的新實(shí)例創(chuàng)建新的CustomPaint對(duì)象
 (這相當(dāng)于同一件事,因?yàn)楹笳呤且郧罢邔?shí)施)
 */
 @override
 bool shouldRepaint(BarChartPainter old) => barHeight != old.barHeight;
}

上面代碼中的lerpDouble函數(shù)比較難理解,代入?yún)?shù)之后計(jì)算結(jié)果如下圖。

使用Flutter怎么實(shí)現(xiàn)動(dòng)畫(huà)效果

數(shù)據(jù)從一開(kāi)始的0.0到達(dá)50.0時(shí),花費(fèi)了10個(gè)時(shí)間點(diǎn)。再到達(dá)52時(shí),則花費(fèi)了16個(gè)時(shí)間點(diǎn)。因此大約得出的結(jié)論時(shí),在我們的應(yīng)用程序中,數(shù)據(jù)變化越小,花費(fèi)的時(shí)間點(diǎn)越多。

使用Flutter怎么實(shí)現(xiàn)動(dòng)畫(huà)效果

上述內(nèi)容就是使用Flutter怎么實(shí)現(xiàn)動(dòng)畫(huà)效果,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


網(wǎng)頁(yè)題目:使用Flutter怎么實(shí)現(xiàn)動(dòng)畫(huà)效果
本文來(lái)源:http://weahome.cn/article/jjppgi.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部