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

利用Flutter制作一個(gè)會(huì)飛的菜單

 更新時(shí)間:2023年06月06日 14:03:36   作者:程序那些事  
flutter中自帶了drawer組件,可以實(shí)現(xiàn)通用的菜單功能,所以本文將嘗試一下通過自定義動(dòng)畫來實(shí)現(xiàn)一個(gè)會(huì)飛的菜單,感興趣的可以了解一下

簡介

flutter中自帶了drawer組件,可以實(shí)現(xiàn)通用的菜單功能,那么有沒有一種可能,我們可以通過自定義動(dòng)畫來實(shí)現(xiàn)一個(gè)別樣的菜單呢?

答案是肯定的,一起來看看吧。

定義一個(gè)菜單項(xiàng)目

因?yàn)檫@里的主要目的是實(shí)現(xiàn)菜單的動(dòng)畫,所以這里的菜單比較簡單,我們的menu是一個(gè)StatefulWidget,里面就是一個(gè)Column組件,column中有四行詩:

  static const _menuTitles = [
    '遲日江山麗',
    '春風(fēng)花草香',
    '泥融飛燕子',
    '沙暖睡鴛鴦',
  ];
    Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child:_buildContent()
    );
  }
  Widget _buildContent() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const SizedBox(height: 16),
        ..._buildListItems()
      ],
    );
  }
  List<Widget> _buildListItems() {
    final listItems = <Widget>[];
    for (var i = 0; i < _menuTitles.length; ++i) {
      listItems.add(
         Padding(
            padding: const EdgeInsets.symmetric(horizontal: 36.0, vertical: 16),
            child: Text(
              _menuTitles[i],
              textAlign: TextAlign.center,
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.w500,
              ),
            ),
      )
      );
    }
    return listItems;
  }

讓menu動(dòng)起來

怎么讓menu動(dòng)起來呢?我們需要給最外層的AnimateMenuApp添加一個(gè)AnimationController,所以需要在_AnimateMenuAppState添加SingleTickerProviderStateMixin的mixin,如下所示:

class _AnimateMenuAppState extends State<AnimateMenuApp>
    with SingleTickerProviderStateMixin {
  late AnimationController _drawerSlideController;

然后在initState中對(duì)_drawerSlideController進(jìn)行初始化:

  void initState() {
    super.initState();
    _drawerSlideController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 150),
    );
  }

在讓menu動(dòng)起來之前,我們需要設(shè)計(jì)一下動(dòng)畫的樣式。假如我們的動(dòng)畫是讓menu從右向左飛出。那么我們可以使用FractionalTranslation來進(jìn)行offset進(jìn)行位置變換。

并且當(dāng)菜單沒有開啟的時(shí)候,我們需要顯示一個(gè)空的組件,這里用SizedBox來替代。

當(dāng)菜單開啟的時(shí)候,就執(zhí)行這個(gè)FractionalTranslation的動(dòng)畫,所以我們的build方法需要這樣寫:

  Widget _buildDrawer() {
    return AnimatedBuilder(
      animation: _drawerSlideController,
      builder: (context, child) {
        return FractionalTranslation(
          translation: Offset(1.0 - _drawerSlideController.value, 0.0),
          child: _isDrawerClosed() ? const SizedBox() : const Menu(),
        );
      },
    );
  }

FractionalTranslation中的Offset是根據(jù)_drawerSlideController的value來進(jìn)行變化的。

那么_drawerSlideController的value怎么變化呢?

我們定義一個(gè)_toggleDrawer方法,在點(diǎn)擊菜單按鈕的時(shí)候來觸發(fā)這個(gè)方法,從而實(shí)現(xiàn)_drawerSlideController的value變化:

  void _toggleDrawer() {
    if (_isDrawerOpen() || _isDrawerOpening()) {
      _drawerSlideController.reverse();
    } else {
      _drawerSlideController.forward();
    }
  }

同時(shí),我們定義下面幾個(gè)判斷菜單狀態(tài)的方法:

  bool _isDrawerOpen() {
    return _drawerSlideController.value == 1.0;
  }
  bool _isDrawerOpening() {
    return _drawerSlideController.status == AnimationStatus.forward;
  }
  bool _isDrawerClosed() {
    return _drawerSlideController.value == 0.0;
  }

因?yàn)椴藛螆D標(biāo)需要根據(jù)菜單狀態(tài)來發(fā)生改變,菜單的狀態(tài)又是依賴于_drawerSlideController,所以,我們把IconButton放到一個(gè)AnimatedBuilder里面,從而實(shí)現(xiàn)動(dòng)態(tài)變化的效果:

  PreferredSizeWidget _buildAppBar() {
    return AppBar(
      title: const Text(
        '動(dòng)畫菜單',
        style: TextStyle(
          color: Colors.black,
        ),
      ),
      backgroundColor: Colors.transparent,
      elevation: 0.0,
      automaticallyImplyLeading: false,
      actions: [
        AnimatedBuilder(
          animation: _drawerSlideController,
          builder: (context, child) {
            return IconButton(
              onPressed: _toggleDrawer,
              icon: _isDrawerOpen() || _isDrawerOpening()
                  ? const Icon(
                Icons.clear,
                color: Colors.black,
              )
                  : const Icon(
                Icons.menu,
                color: Colors.black,
              ),
            );
          },
        ),
      ],
    );
  }

最后實(shí)現(xiàn)的效果如下:

添加菜單內(nèi)部的動(dòng)畫

上面的例子中整個(gè)菜單是作為一個(gè)整體來動(dòng)畫的,有沒有可能菜單里面的每一個(gè)item也有自己的動(dòng)畫呢?

答案當(dāng)然是肯定的。

我們只需要在上面的基礎(chǔ)上將menu組件添加動(dòng)畫支持即可:

class _MenuState extends State<Menu> with SingleTickerProviderStateMixin

動(dòng)畫中的位移我們選擇使用Transform.translate,同時(shí)還添加了淡入淡出的效果,也就是把上面例子中的Padding用AnimatedBuilder包裹起來,如下所示:

  List<Widget> _buildListItems() {
    final listItems = <Widget>[];
    for (var i = 0; i < _menuTitles.length; ++i) {
      listItems.add(
        AnimatedBuilder(
          animation: _itemController,
          builder: (context, child) {
            final animationPercent = Curves.easeOut.transform(
              _itemSlideIntervals[i].transform(_itemController.value),
            );
            final opacity = animationPercent;
            final slideDistance = (1.0 - animationPercent) * 150;
            return Opacity(
              opacity: opacity,
              child: Transform.translate(
                offset: Offset(slideDistance, 0),
                child: child,
              ),
            );
          },
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 36.0, vertical: 16),
            child: Text(
              _menuTitles[i],
              textAlign: TextAlign.center,
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.w500,
              ),
            ),
          ),
        ),
      );
    }
    return listItems;
  }

AnimatedBuilder中的builder返回的是一個(gè)Opacity對(duì)象,里面包含了opacity和child兩個(gè)屬性。其中最終要的一個(gè)變化值是animationPercent,這個(gè)值是根據(jù)_itemController的value和初始設(shè)置的各個(gè)item的變化時(shí)間來決定的。

每個(gè)item的值是不一樣的:

  void _createAnimationIntervals() {
    for (var i = 0; i < _menuTitles.length; ++i) {
      final startTime = _initialDelayTime + (_staggerTime * i);
      final endTime = startTime + _itemSlideTime;
      _itemSlideIntervals.add(
        Interval(
          startTime.inMilliseconds / _animationDuration.inMilliseconds,
          endTime.inMilliseconds / _animationDuration.inMilliseconds,
        ),
      );
    }
  }

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

總結(jié)

在flutter中一切皆可動(dòng)畫,我們只需要掌握動(dòng)畫創(chuàng)作的訣竅即可。

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

到此這篇關(guān)于利用Flutter制作一個(gè)會(huì)飛的菜單的文章就介紹到這了,更多相關(guān)Flutter菜單內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android內(nèi)置的OkHttp用法介紹

    Android內(nèi)置的OkHttp用法介紹

    okhttp是一個(gè)第三方類庫,用于android中請(qǐng)求網(wǎng)絡(luò)。這是一個(gè)開源項(xiàng)目,是安卓端最火熱的輕量級(jí)框架,由移動(dòng)支付Square公司貢獻(xiàn)(該公司還貢獻(xiàn)了Picasso和LeakCanary) 。用于替代HttpUrlConnection和Apache HttpClient
    2022-08-08
  • 解析kotlin中什么是Lambda?閉包

    解析kotlin中什么是Lambda?閉包

    Kotlin通過Lambda閉包將代碼封裝為可傳遞的數(shù)據(jù)塊,替代Java的匿名內(nèi)部類,提升代碼靈活性與可讀性,其語法簡潔,能捕獲外部變量,實(shí)現(xiàn)高階函數(shù)功能,簡化回調(diào)邏輯,本文給大家介紹kotlin中什么是Lambda?閉包,感謝興趣的朋友跟隨小編一起看看吧
    2025-06-06
  • 深入淺析Android坐標(biāo)系統(tǒng)

    深入淺析Android坐標(biāo)系統(tǒng)

    這篇文章主要介紹了 深入淺析Android坐標(biāo)系統(tǒng)的相關(guān)資料,需要的朋友可以參考下
    2016-01-01
  • Android中 自定義數(shù)據(jù)綁定適配器BaseAdapter的方法

    Android中 自定義數(shù)據(jù)綁定適配器BaseAdapter的方法

    本篇文章小編為大家介紹,Android中 自定義數(shù)據(jù)綁定適配器BaseAdapter的方法。需要的朋友參考下
    2013-04-04
  • Android自定義View之組合控件實(shí)現(xiàn)類似電商app頂部欄

    Android自定義View之組合控件實(shí)現(xiàn)類似電商app頂部欄

    這篇文章主要為大家詳細(xì)介紹了Android自定義View之組合控件,實(shí)現(xiàn)類似電商app頂部欄的相關(guān)資料,具有參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-05-05
  • Android布局技巧之使用ViewStub

    Android布局技巧之使用ViewStub

    這篇文章主要為大家詳細(xì)介紹了Android布局技巧之使用ViewStub,具有一定的實(shí)用性,感興趣的小伙伴們可以參考一下
    2016-06-06
  • Android自定義LocationMarker的實(shí)現(xiàn)詳解

    Android自定義LocationMarker的實(shí)現(xiàn)詳解

    這篇文章主要為大家詳細(xì)介紹一個(gè)比較簡單的東西:自定義繪制Marker 其實(shí)就是自定義view, 跟軌跡沒太多關(guān)聯(lián),感興趣的小伙伴可以跟隨小編一起了解一下
    2023-02-02
  • Android APK反編譯圖文教程

    Android APK反編譯圖文教程

    學(xué)會(huì)反編譯比較關(guān)鍵,也是我們美化必須掌握技術(shù),學(xué)會(huì)反編譯也是實(shí)現(xiàn)制作ROM的起步,ROM高手必然是反編譯高手這里有必要說一下,教程只是給你一個(gè)動(dòng)手的那一個(gè)蹺板,教程不是萬能的,給了你基礎(chǔ)與啟發(fā),最重要的是我們能夠自主的進(jìn)行創(chuàng)新與思考
    2016-04-04
  • 使用ListView實(shí)現(xiàn)網(wǎng)上訂餐首頁

    使用ListView實(shí)現(xiàn)網(wǎng)上訂餐首頁

    這篇文章主要為大家詳細(xì)介紹了使用ListView實(shí)現(xiàn)網(wǎng)上訂餐首頁,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-01-01
  • Android TextView多文本折疊展開效果

    Android TextView多文本折疊展開效果

    這篇文章主要為大家詳細(xì)介紹了Android TextView多文本折疊展開效果的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10

最新評(píng)論

琼结县| 原平市| 广州市| 芷江| 图们市| 渭南市| 龙里县| 伽师县| 那坡县| 大同市| 通海县| 龙江县| 宾阳县| 凤翔县| 瑞金市| 汶上县| 新邵县| 卢氏县| 金堂县| 阿合奇县| 平安县| 阳西县| 华池县| 威宁| 肇东市| 松潘县| 醴陵市| 闸北区| 温宿县| 南溪县| 南丹县| 惠安县| 侯马市| 左贡县| 林口县| 盐边县| 隆化县| 丰顺县| 绥德县| 海城市| 安陆市|