最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Android?Flutter如何自定義動(dòng)畫路由

 更新時(shí)間:2023年04月19日 16:40:28   作者:程序那些事  
flutter中有默認(rèn)的Route組件,叫做MaterialPageRoute,但是MaterialPageRoute太普通了,如果我們想要做點(diǎn)不同的跳轉(zhuǎn)特效應(yīng)該如何處理呢?一起來看看吧

簡(jiǎn)介

flutter中有默認(rèn)的Route組件,叫做MaterialPageRoute,一般情況下我們?cè)趂lutter中進(jìn)行跳轉(zhuǎn)的話,只需要向Navigator中傳入一個(gè)MaterialPageRoute就可以了。

但是MaterialPageRoute太普通了,如果我們想要做點(diǎn)不同的跳轉(zhuǎn)特效應(yīng)該如何處理呢?

一起來看看吧。

自定義跳轉(zhuǎn)使用

正常情況下,我們進(jìn)行路由跳轉(zhuǎn)需要用到Navigator和MaterialPageRoute,如下所示:

 Navigator.push(context, MaterialPageRoute(builder: (context) {
            return const NextPage();

如果要實(shí)現(xiàn)特定的路由動(dòng)畫,那么需要進(jìn)行路由的自定義。

在flutter中也就是要使用PageRouteBuilder來自定義一個(gè)Route。

先來看下PageRouteBuilder的定義:

class PageRouteBuilder<T> extends PageRoute<T> {

  PageRouteBuilder({
    super.settings,
    required this.pageBuilder,
    this.transitionsBuilder = _defaultTransitionsBuilder,
    this.transitionDuration = const Duration(milliseconds: 300),
    this.reverseTransitionDuration = const Duration(milliseconds: 300),
    this.opaque = true,
    this.barrierDismissible = false,
    this.barrierColor,
    this.barrierLabel,
    this.maintainState = true,
    super.fullscreenDialog,
  })

PageRouteBuilder也是PageRoute的一種,在構(gòu)建PageRouteBuilder的時(shí)候,通過控制不同的屬性值,我們可以自由控制pageBuilder,transitionsBuilder,transitionDuration,reverseTransitionDuration等特性。

可以看到自由程度還是非常高的。

其中pageBuilder是路由將會(huì)跳轉(zhuǎn)的頁面,這個(gè)是必須要指定的,要不然路由也就沒有意義了。

另外路由轉(zhuǎn)換的效果可以經(jīng)由transitionsBuilder來設(shè)置。

這里的RouteTransitionsBuilder是一個(gè)Function,返回一個(gè)Widget:

typedef RouteTransitionsBuilder = Widget Function(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child);

所以理論上,我們可以返回任何widget,但是一般來說,我們會(huì)返回一個(gè)AnimatedWidget,表示一個(gè)動(dòng)畫效果。

flutter動(dòng)畫基礎(chǔ)

flutter中有個(gè)專門的動(dòng)畫包叫做flutter/animation.dart, flutter中所有動(dòng)畫的核心叫做Animation。

Animation中定義了很多l(xiāng)istener用來監(jiān)控動(dòng)畫的變動(dòng)情況,并且還提供了一個(gè)AnimationStatus來存儲(chǔ)當(dāng)前的動(dòng)畫狀態(tài):

abstract class Animation<T> extends Listenable implements ValueListenable<T> {
  const Animation();

  AnimationWithParentMixin<T>

  @override
  void addListener(VoidCallback listener);

  @override
  void removeListener(VoidCallback listener);

  void addStatusListener(AnimationStatusListener listener);

  void removeStatusListener(AnimationStatusListener listener);

  AnimationStatus get status;

AnimationStatus是一個(gè)枚舉類,它包含了現(xiàn)在動(dòng)畫的各種狀態(tài):

enum AnimationStatus {
  dismissed,

  forward,

  reverse,

  completed,
}

dismissed表示動(dòng)畫暫停在開頭。

forward表示動(dòng)畫在從頭到尾播放。

reverse表示動(dòng)畫在從尾到頭播放。

completed表示動(dòng)畫播放完畢,停在了結(jié)尾。

有了動(dòng)畫的表示之后,如何對(duì)動(dòng)畫進(jìn)行控制呢?這里就需要用到AnimationController了。

AnimationController可以控制動(dòng)畫的duration,動(dòng)畫的最低值lowerBound默認(rèn)是0.0,動(dòng)畫的最高值upperBound默認(rèn)是1.0等等。

默認(rèn)情況AnimationController中從最低值到最高值是線性變化的,如果你想設(shè)置不同的Bound值,那么可以嘗試自定義 Animatable, 如果你想動(dòng)畫的變動(dòng)是非線性的,那么可以嘗試?yán)^承Animation來實(shí)現(xiàn)自己的變動(dòng)曲線。

實(shí)現(xiàn)一個(gè)自定義的route

這里我們使用flutter中的SlideTransition,SlideTransition是一個(gè)AnimatedWidget,它表示的是一個(gè)組件的位置變化的動(dòng)畫。

class SlideTransition extends AnimatedWidget {
  const SlideTransition({
    super.key,
    required Animation<Offset> position,
    this.transformHitTests = true,
    this.textDirection,
    this.child,
  }) : assert(position != null),
       super(listenable: position);

看下它的構(gòu)造函數(shù),可以看到SlideTransition需要一個(gè)position的屬性,這個(gè)position是一個(gè)Animation對(duì)象,里面包含的是Offset。

同時(shí)這個(gè)position是一個(gè)listenable對(duì)象,通過監(jiān)聽里面Offset的變化,從而重新build對(duì)應(yīng)的widget從而實(shí)現(xiàn)動(dòng)畫的效果。

Offset是一個(gè)表示位置的類,(0,0) 表示這個(gè)widget的左頂點(diǎn)在屏幕的左上角,同樣的(1,1)表示這個(gè)widget的左頂點(diǎn)在屏幕的右下角。

因?yàn)閞oute過后是一個(gè)新的頁面,我們希望出現(xiàn)一個(gè)頁面從右下角移動(dòng)到左上角的動(dòng)畫,那么我們可以這樣做:

Route customRoute() {
  return PageRouteBuilder(
    pageBuilder: (context, animation, secondaryAnimation) => const SecondPage(),
    transitionsBuilder: (context, animation, secondaryAnimation, child) {
      const begin = Offset(1.0, 1.0);
      const end = Offset.zero;
      const curve = Curves.easeOut;

      var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));

      return SlideTransition(
        position: animation.drive(tween),
        child: child,
      );
    },
  );
}

這里的begin和end表示widget從屏幕的右下角移動(dòng)到了屏幕的左上角。

Tween表示的是開始值和結(jié)束值之間的線性插值,是一個(gè)動(dòng)態(tài)過程,另外我們還可以這個(gè)插值變動(dòng)的曲線,這里使用了CurveTween,選中了Curves.easeOut這種曲線類型。

最后調(diào)用animation.drive方法把Tween和Animation關(guān)聯(lián)起來,這樣一個(gè)路由動(dòng)畫就完成了。

總結(jié)

最后程序運(yùn)行的結(jié)果如下:

其實(shí)flutter中的動(dòng)畫很簡(jiǎn)單,大家記住就是widget位置沿不同的曲線變化即可。

本文的例子:github.com/ddean2009/learn-flutter

以上就是詳解Android Flutter如何自定義動(dòng)畫路由的詳細(xì)內(nèi)容,更多關(guān)于Android Flutter自定義動(dòng)畫路由的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

东城区| 松滋市| 连平县| 洪湖市| 石城县| 龙门县| 濮阳县| 昌图县| 大埔区| 吴堡县| 汝南县| 平凉市| 昌图县| 黄梅县| 富蕴县| 灌云县| 水城县| 横山县| 磐安县| 宜川县| 枣庄市| 盐池县| 南京市| 当涂县| 天等县| 云南省| 达日县| 新竹市| 清涧县| 墨脱县| 乌鲁木齐县| 呼图壁县| 乌海市| 七台河市| 抚顺县| 白山市| 东丽区| 乌兰县| 灵川县| 莱西市| 界首市|