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

Flutter?Flow實(shí)現(xiàn)滑動(dòng)顯隱層示例詳解

 更新時(shí)間:2023年03月03日 09:35:30   作者:張風(fēng)捷特烈  
這篇文章主要為大家介紹了Flutter?Flow實(shí)現(xiàn)滑動(dòng)顯隱層示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

1. 前言

最近要實(shí)現(xiàn)一個(gè)小需求,涵蓋了很多知識(shí)點(diǎn),比如手勢(shì)、動(dòng)畫、布局等。挺有意思的,寫出來和大家分享一下。如下所示,分為上下兩層;當(dāng)左右滑時(shí),上層會(huì)隨偏移量而平移,從而讓上層產(chǎn)生滑動(dòng)手勢(shì)顯隱的效果:

標(biāo)題

這里上層通過不透明度 0.2 的藍(lán)色示意,實(shí)際使用時(shí)可以改為透明色。很多直播間的浮層就是這種交互邏輯,通過右滑來隱藏浮層。

直播右滑中

2. 實(shí)現(xiàn)思路

思路其實(shí)非常簡(jiǎn)單,監(jiān)聽橫向滑動(dòng)的手勢(shì)事件,根據(jù)偏移量讓上層組件進(jìn)行偏移。當(dāng)放手時(shí),根據(jù)偏移量是否達(dá)到寬度的一半,使用動(dòng)畫進(jìn)行移出或者關(guān)閉。

偏移的實(shí)現(xiàn)方式有很多,但需要自由地進(jìn)行布局和矩陣變換、透明度,并且需要支持動(dòng)畫的變化,F(xiàn)low 組件是一個(gè)非常不錯(cuò)的選擇。 Flow 組件可以通過代理類對(duì)子組件進(jìn)行自定義布局,靈活性極強(qiáng);如果是 CustomPaint繪制之王 可以繪制萬物,那么 Flow 就是 布局之王,可以擺放萬物。三年前寫過一篇介紹 Flow 使用的文章: 《【Flutter高級(jí)玩法- Flow 】我的位置我做主》 。 本文就不對(duì) Flow 的基礎(chǔ)使用進(jìn)行介紹了。

另外,在滑動(dòng)過程中需要注意限制偏移量,使偏移量在 0~size.width 之內(nèi);當(dāng)放手時(shí),通過動(dòng)畫控制器來驅(qū)動(dòng)動(dòng)畫,使用補(bǔ)間讓偏移量運(yùn)動(dòng)到 0 (打開) 或 size.width(關(guān)閉) 。當(dāng)關(guān)閉時(shí),在右下角展示一個(gè)按鈕用于點(diǎn)擊展開:

3. 布局的代碼實(shí)現(xiàn)

Flow 組件布局最重要的是實(shí)現(xiàn) FlowDelegate,在其中的 paintChildren 方法中實(shí)現(xiàn)布局的邏輯。和 CustomPainter 類似,FlowDelegate 的實(shí)現(xiàn)類也可以通過 super 構(gòu)造為 repaint 入?yún)⒃O(shè)置可監(jiān)聽對(duì)象??杀O(jiān)聽對(duì)象的變化會(huì)觸發(fā) paintChildren 重新繪制:

SwipeFlowDelegate 實(shí)現(xiàn)類再構(gòu)造時(shí)傳入可監(jiān)聽對(duì)象 offsetX,在繪制索引為 1 的孩子時(shí),通過 Matrix4 進(jìn)行偏移。這樣只要在手勢(shì)水平滑動(dòng)中,更新 offsetX 值即可。另外,可以根據(jù) offsetX.value 是否達(dá)到 size.width 知道是否是關(guān)閉狀態(tài),如果已經(jīng)關(guān)閉,繪制按鈕。

class SwipeFlowDelegate extends FlowDelegate {
  final ValueListenable<double> offsetX;
  SwipeFlowDelegate(this.offsetX) : super(repaint: offsetX);
  @override
  void paintChildren(FlowPaintingContext context) {
    Size size = context.size;
    context.paintChild(0);
    Matrix4 offsetM4 = Matrix4.translationValues(offsetX.value, 0, 0);
    context.paintChild(1, transform: offsetM4);
    // 偏移量對(duì)于父級(jí)尺寸
    if (offsetX.value == size.width) {
      Matrix4 m1 = Matrix4.translationValues(size.width / 2 - 30, size.height / 2 - 30, 0);
      context.paintChild(2, transform: m1);
      Matrix4 m2 = Matrix4.translationValues(size.width / 2 - 30, -(size.height / 2 - 50), 0);
      context.paintChild(3, transform: m2);
    }
  }
  @override
  bool shouldRepaint(covariant SwipeFlowDelegate oldDelegate) {
    return oldDelegate.offsetX.value != offsetX.value;
  }
}

從這里可以看出,FlowDelegate 的最大優(yōu)勢(shì)是可以自定義孩子的繪制與否,還可以在繪制時(shí)通過 Matrix4 對(duì)孩子進(jìn)行矩陣變換,還有可選參數(shù)可以控制透明度。接下來使用 Flow 組件時(shí),提供 SwipeFlowDelegate ,并在 children 列表中依次放入子組件。其中前兩個(gè)組件由外界傳入,分別是底組件和上層組件,這樣組件的布局就完成了,接下來監(jiān)聽事件,更新 factor 即可:

final ValueNotifier<double> factor = ValueNotifier(0);
Flow(
  delegate: SwipeFlowDelegate(factor),
  children: [
    widget.content,
    widget.overflow,
    GestureDetector(
        onTap: open,
        child: const Icon(Icons.menu_open_outlined, color: Colors.white)),
    GestureDetector(
        onTap: () {
          Navigator.of(context).pop();
        },
        child: const Icon(Icons.close, color: Colors.white))
  ],
)

4. 手勢(shì)的監(jiān)聽

這里手勢(shì)的處理是非常簡(jiǎn)單的,通過 GestureDetector 監(jiān)聽水平拖拽事件。在 onHorizontalDragUpdate 中根據(jù)拖拽的偏移量更新 factor 的值,其中通過 .clamp(0, widget.width) 可以限制偏移量的取值區(qū)間。

@override
Widget build(BuildContext context) {
  return GestureDetector(
      behavior: HitTestBehavior.opaque,
      onHorizontalDragUpdate: _onHorizontalDragUpdate,
      onHorizontalDragEnd: _onHorizontalDragEnd,
      child: SizedBox(
        height: MediaQuery.of(context).size.height,
        width: widget.width,
        child: Flow( delegate:// 同上,略...
      );
}
void _onHorizontalDragUpdate(DragUpdateDetails details) {
  double cur = factor.value + details.delta.dx;
  factor.value = cur.clamp(0, widget.width);
}
void _onHorizontalDragEnd(DragEndDetails details) {
  if (factor.value > widget.width / 2) {
    close();
  } else {
    open();
  }
}

最后在 _onHorizontalDragEnd 回調(diào)中,根據(jù)當(dāng)前偏移量是否大于一般寬度,決定關(guān)閉還是打開。期間過程使用動(dòng)畫進(jìn)行偏移量的過渡變化。

5. 動(dòng)畫的使用

動(dòng)畫的使用,主要是通過 AnimationController 動(dòng)畫控制器來驅(qū)動(dòng)數(shù)值的變化;在放手時(shí) Tween 創(chuàng)建補(bǔ)間動(dòng)畫器,監(jiān)聽動(dòng)畫器數(shù)值的變化更新偏移量。這樣偏移量就可以在指定時(shí)間內(nèi),在兩個(gè)值之間漸變,從而產(chǎn)生動(dòng)畫效果。比如抬手時(shí),open 方法是讓偏移量從當(dāng)前位置變化到 0 :

class _ScrollHideWrapperState extends State<ScrollHideWrapper> with SingleTickerProviderStateMixin {
  late AnimationController _ctrl;
  final ValueNotifier<double> factor = ValueNotifier(0);
  @override
  void initState() {
    super.initState();
    _ctrl = AnimationController(
      duration: const Duration(milliseconds: 200),
      vsync: this,
    );
  }
  @override
  Widget build(BuildContext context) {
    // 略同...
  }
  // 動(dòng)畫關(guān)閉
  Future<void> close() async {
    Animation<double> anim = Tween<double>(begin: factor.value, end: widget.width).animate(_ctrl);
    anim.addListener(() => factor.value = anim.value);
    await _ctrl.forward(from: 0);
  }
  // 動(dòng)畫打開
  Future<void> open() async {
    Animation<double> anim = Tween<double>(begin: factor.value, end: 0).animate(_ctrl);
    anim.addListener(() => factor.value = anim.value);
    await _ctrl.forward(from: 0);
  }
}

如果想讓動(dòng)畫的變化非勻速,可以使用 Curve 來控制動(dòng)畫曲線。這樣,基于 Flow 實(shí)現(xiàn)的自定義布局,就可以根據(jù)手勢(shì)和動(dòng)畫,完成特定的交互功能。從這里可以看出 Flow 自定義布局的靈活性非常強(qiáng),很多疑難雜癥,都可以使用它來完成。

比如企業(yè)微信中:側(cè)滑展示左欄,而且上層不會(huì)全部消失,通過 Flow 來自定義布局就很容易實(shí)現(xiàn)。大家可以基于本文,自己實(shí)現(xiàn)一下作為練習(xí)。那本文就到這里,謝謝觀看 ~

標(biāo)題關(guān)閉

以上就是Flutter Flow實(shí)現(xiàn)滑動(dòng)顯隱層示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Flutter Flow滑動(dòng)顯隱層的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • android中ViewPager結(jié)合Fragment進(jìn)行無限滑動(dòng)

    android中ViewPager結(jié)合Fragment進(jìn)行無限滑動(dòng)

    本篇文章中主要介紹了android中ViewPager結(jié)合Fragment進(jìn)行無限滑動(dòng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-03-03
  • Android實(shí)現(xiàn)便于批量操作可多選的圖片ListView實(shí)例

    Android實(shí)現(xiàn)便于批量操作可多選的圖片ListView實(shí)例

    這篇文章主要介紹了Android實(shí)現(xiàn)便于批量操作可多選的圖片ListView功能實(shí)現(xiàn)方法,涉及ListView針對(duì)多圖操作的相關(guān)技巧,需要的朋友可以參考下
    2016-08-08
  • Android實(shí)現(xiàn)搜索本地音樂的方法

    Android實(shí)現(xiàn)搜索本地音樂的方法

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)搜索本地音樂的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • Android中判斷網(wǎng)絡(luò)連接是否可用及監(jiān)控網(wǎng)絡(luò)狀態(tài)

    Android中判斷網(wǎng)絡(luò)連接是否可用及監(jiān)控網(wǎng)絡(luò)狀態(tài)

    獲取網(wǎng)絡(luò)信息需要在AndroidManifest.xml文件中加入相應(yīng)的權(quán)限,接下來詳細(xì)介紹Android中判斷網(wǎng)絡(luò)連接是否可用及監(jiān)控網(wǎng)絡(luò)狀態(tài),感興趣的朋友可以參考下
    2012-12-12
  • android監(jiān)聽安裝和卸載示例

    android監(jiān)聽安裝和卸載示例

    Android應(yīng)用程序的安裝和卸載事件,是由系統(tǒng)進(jìn)行監(jiān)聽并全局廣播的,支持1.5(android 3)以上,因此,如果想要監(jiān)聽獲取應(yīng)用的安裝和卸載事件,只需要自定義一個(gè)BroadcastReceiver,來對(duì)系統(tǒng)廣播進(jìn)行監(jiān)聽和處理
    2014-02-02
  • Flutter使用?input?chip?標(biāo)簽組件示例詳解

    Flutter使用?input?chip?標(biāo)簽組件示例詳解

    這篇文章主要為大家介紹了Flutter使用?input?chip?標(biāo)簽組件示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • Android手把手教大家制作APP首頁(下拉刷新、自動(dòng)加載)

    Android手把手教大家制作APP首頁(下拉刷新、自動(dòng)加載)

    這篇文章主要為大家詳細(xì)介紹了Android手把手教大家制作APP首頁,實(shí)現(xiàn)下拉刷新、自動(dòng)加載功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Android 如何本地加載pdf文件

    Android 如何本地加載pdf文件

    本篇文章主要介紹了Android本地加載pdf文件的相關(guān)知識(shí)。具有很好的參考價(jià)值。下面跟著小編一起來看下吧
    2017-04-04
  • 淺談Android 指紋解鎖技術(shù)

    淺談Android 指紋解鎖技術(shù)

    這篇文章主要介紹了淺談Android 指紋解鎖技術(shù),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-03-03
  • Kotlin與Java相互調(diào)用的完整實(shí)例

    Kotlin與Java相互調(diào)用的完整實(shí)例

    Kotlin的設(shè)計(jì)過程中就考慮到了與Java的互操作性,在Kotlin中可以直接調(diào)用既有的Java代碼,反過來在Java中也可以很流暢地使用Kotlin代碼,這篇文章主要給大家介紹了關(guān)于Kotlin與Java相互調(diào)用的相關(guān)資料,需要的朋友可以參考下
    2021-12-12

最新評(píng)論

永靖县| 疏附县| 乌鲁木齐县| 彝良县| 临猗县| 堆龙德庆县| 海门市| 宝丰县| 洛浦县| 江油市| 呼伦贝尔市| 深泽县| 名山县| 杭锦旗| 邓州市| 连城县| 盐池县| 临洮县| 陕西省| 宁津县| 德保县| 阿拉善右旗| 佛山市| 连江县| 张家港市| 肇州县| 马山县| 沙田区| 基隆市| 海南省| 崇信县| 精河县| 乾安县| 嘉祥县| 新宁县| 彰化市| 长岭县| 来安县| 罗城| 永春县| 旺苍县|