您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“Android Flutter怎么實現(xiàn)彈簧動畫交互”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Android Flutter怎么實現(xiàn)彈簧動畫交互”吧!
首頁創(chuàng)建一個測試使用的Demo頁面
void main() { runApp(const MaterialApp(home: PhysicsCardDragDemo())); } class PhysicsCardDragDemo extends StatelessWidget { const PhysicsCardDragDemo({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: const DraggableCard( child: FlutterLogo( size: 128, ), ), ); } }
DraggableCard 是自定義的一個 StatefulWidget,代碼如下:
class _DraggableCardState extends State<DraggableCard> { @override void initState() { super.initState(); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return Align( child: Card( child: widget.child, ), ); } }
然后在 _DraggableCardState 中創(chuàng)建一個動畫控制器,并在頁面銷毀的時候釋放動畫控制器,代碼如下:
class _DraggableCardState extends State<DraggableCard> with SingleTickerProviderStateMixin { late AnimationController _controller; @override void initState() { super.initState(); _controller = AnimationController(vsync: this, duration: const Duration(seconds: 1)); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Align( child: Card( child: widget.child, ), ); } }
SingleTickerProviderStateMixin是用來在StatefulWidget中管理單個AnimationController的Mixin;它提供了一個TickerProvider,用于將AnimationController與TickerProviderStateMixin一起使用。
TickerProviderStateMixin提供了一個Ticker,它可以在每個frame中調(diào)用AnimationController的方法,這使得AnimationController可以在每個frame中更新動畫。
在 _DraggableCardState 中,結(jié)合使用 Alignment 與 GestureDetector,代碼如下:
class _DraggableCardState extends State<DraggableCard> with SingleTickerProviderStateMixin { late AnimationController _controller; Alignment _dragAlignment = const Alignment(0, 0); @override Widget build(BuildContext context) { var size = MediaQuery.of(context).size; return GestureDetector( onPanDown: (details) {}, onPanUpdate: (details) { _dragAlignment += Alignment( details.delta.dx / (size.width / 2), details.delta.dy / (size.height / 2), ); setState(() { }); }, onPanEnd: (details) {}, child: Align( alignment: _dragAlignment, child: Card( child: widget.child, ), ), ); }
GestureDetector用來檢測手勢,例如輕觸、滑動、拖動等,可以用來實現(xiàn)各種交互效果。
Alignment用于控制子widget在父widget中的位置??梢酝ㄟ^Alignment的構(gòu)造函數(shù)來指定子widget相對于父widget的位置,如Alignment.topLeft表示子widget位于父widget的左上角。也可以通過FractionalOffset來指定子widget相對于父widget的位置,如FractionalOffset(0.5, 0.5)表示子widget位于父widget的中心。Alignment還可以與Stack一起使用,實現(xiàn)多個子widget的定位。
我們需要實現(xiàn),當(dāng)手指抬起時,被移動的 Widget 動畫的方式彈回去。
在這里需要一個 Animation ,再定義一個 runAnimation 方法,同時為 第一步創(chuàng)建的動畫控制器添加一個更新監(jiān)聽。
class _DraggableCardState extends State<DraggableCard> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<Alignment> _animation; @override void initState() { super.initState(); _controller = AnimationController(vsync: this, duration: const Duration(seconds: 1)); _controller.addListener(() { setState(() { _dragAlignment = _animation.value; }); }); } void _runAnimation() { _animation = _controller.drive( AlignmentTween( begin: _dragAlignment, end: Alignment.center, ), ); _controller.reset(); _controller.forward(); } }
然后在手指抬起的時候,執(zhí)行動畫,將被移動的 Widget (如這里的圖片)以動畫的方式移動回原位:
@override Widget build(BuildContext context) { var size = MediaQuery.of(context).size; return GestureDetector( onPanDown: (details) { _controller.stop(); }, onPanUpdate: (details) { _dragAlignment += Alignment( details.delta.dx / (size.width / 2), details.delta.dy / (size.height / 2), ); setState(() { }); }, onPanEnd: (details) { _runAnimation(); }, child: Align( alignment: _dragAlignment, child: Card( child: widget.child, ), ), ); }
最后一步是做一些數(shù)學(xué)運算,計算小部件完成拖動后的速度。這是為了使小部件在被拍回之前能夠以這種速度逼真地繼續(xù)。(_runAnimation方法已經(jīng)通過設(shè)置動畫的開始和結(jié)束對齊來設(shè)置方向。)
導(dǎo)入包如下:
import 'package:flutter/physics.dart';
onPanEnd回調(diào)提供了一個DragEndDetails對象。此對象提供指針停止接觸屏幕時的速度。速度以像素每秒為單位,但Align小部件不使用像素。它使用介于[-1.0,-1.0]和[1.0,1.0]之間的坐標(biāo)值,其中[0.0,0.0]表示中心。步驟2中計算的大小用于將像素轉(zhuǎn)換為該范圍內(nèi)的坐標(biāo)值。
然后修改 runAnimation 執(zhí)行動畫函數(shù)如下:
void _runAnimation(Offset pixelsPerSecond, Size size) { _animation = _controller.drive( AlignmentTween( begin: _dragAlignment, end: Alignment.center, ), ); final unitsPerSecondX = pixelsPerSecond.dx / size.width; final unitsPerSecondY = pixelsPerSecond.dy / size.height; final unitsPerSecond = Offset(unitsPerSecondX, unitsPerSecondY); final unitVelocity = unitsPerSecond.distance; //它可以用于模擬彈簧的阻尼、質(zhì)量和剛度等屬性,從而實現(xiàn)更加真實的動畫效果。 const spring = SpringDescription( mass: 30, stiffness: 1, damping: 1, ); //SpringSimulation用來模擬一個彈簧的運動,可以用于創(chuàng)建具有彈性的動畫效果。 final simulation = SpringSimulation(spring, 0, 1, -unitVelocity); _controller.animateWith(simulation); }
然后在手指抬起的時候調(diào)用
onPanEnd: (details) { _runAnimation(details.velocity.pixelsPerSecond, size); },
到此,相信大家對“Android Flutter怎么實現(xiàn)彈簧動畫交互”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。