Flutter Flow实现滑动显隐层示例详解

 更新时间:2023年03月03日 09:35:30   作者:张风捷特烈  
这篇文章主要为大家介绍了Flutter Flow实现滑动显隐层示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

1. 前言

最近要实现一个小需求,涵盖了很多知识点,比如手势、动画、布局等。挺有意思的,写出来和大家分享一下。如下所示,分为上下两层;当左右滑时,上层会随偏移量而平移,从而让上层产生滑动手势显隐的效果:

标题

这里上层通过不透明度 0.2 的蓝色示意,实际使用时可以改为透明色。很多直播间的浮层就是这种交互逻辑,通过右滑来隐藏浮层。

直播右滑中

2. 实现思路

思路其实非常简单,监听横向滑动的手势事件,根据偏移量让上层组件进行偏移。当放手时,根据偏移量是否达到宽度的一半,使用动画进行移出或者关闭。

偏移的实现方式有很多,但需要自由地进行布局和矩阵变换、透明度,并且需要支持动画的变化,Flow 组件是一个非常不错的选择。 Flow 组件可以通过代理类对子组件进行自定义布局,灵活性极强;如果是 CustomPaint绘制之王 可以绘制万物,那么 Flow 就是 布局之王,可以摆放万物。三年前写过一篇介绍 Flow 使用的文章: 《【Flutter高级玩法- Flow 】我的位置我做主》 。 本文就不对 Flow 的基础使用进行介绍了。

另外,在滑动过程中需要注意限制偏移量,使偏移量在 0~size.width 之内;当放手时,通过动画控制器来驱动动画,使用补间让偏移量运动到 0 (打开) 或 size.width(关闭) 。当关闭时,在右下角展示一个按钮用于点击展开:

3. 布局的代码实现

Flow 组件布局最重要的是实现 FlowDelegate,在其中的 paintChildren 方法中实现布局的逻辑。和 CustomPainter 类似,FlowDelegate 的实现类也可以通过 super 构造为 repaint 入参设置可监听对象。可监听对象的变化会触发 paintChildren 重新绘制:

SwipeFlowDelegate 实现类再构造时传入可监听对象 offsetX,在绘制索引为 1 的孩子时,通过 Matrix4 进行偏移。这样只要在手势水平滑动中,更新 offsetX 值即可。另外,可以根据 offsetX.value 是否达到 size.width 知道是否是关闭状态,如果已经关闭,绘制按钮。

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);
    // 偏移量对于父级尺寸
    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 的最大优势是可以自定义孩子的绘制与否,还可以在绘制时通过 Matrix4 对孩子进行矩阵变换,还有可选参数可以控制透明度。接下来使用 Flow 组件时,提供 SwipeFlowDelegate ,并在 children 列表中依次放入子组件。其中前两个组件由外界传入,分别是底组件和上层组件,这样组件的布局就完成了,接下来监听事件,更新 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. 手势的监听

这里手势的处理是非常简单的,通过 GestureDetector 监听水平拖拽事件。在 onHorizontalDragUpdate 中根据拖拽的偏移量更新 factor 的值,其中通过 .clamp(0, widget.width) 可以限制偏移量的取值区间。

@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 回调中,根据当前偏移量是否大于一般宽度,决定关闭还是打开。期间过程使用动画进行偏移量的过渡变化。

5. 动画的使用

动画的使用,主要是通过 AnimationController 动画控制器来驱动数值的变化;在放手时 Tween 创建补间动画器,监听动画器数值的变化更新偏移量。这样偏移量就可以在指定时间内,在两个值之间渐变,从而产生动画效果。比如抬手时,open 方法是让偏移量从当前位置变化到 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) {
    // 略同...
  }
  // 动画关闭
  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);
  }
  // 动画打开
  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);
  }
}

如果想让动画的变化非匀速,可以使用 Curve 来控制动画曲线。这样,基于 Flow 实现的自定义布局,就可以根据手势和动画,完成特定的交互功能。从这里可以看出 Flow 自定义布局的灵活性非常强,很多疑难杂症,都可以使用它来完成。

比如企业微信中:侧滑展示左栏,而且上层不会全部消失,通过 Flow 来自定义布局就很容易实现。大家可以基于本文,自己实现一下作为练习。那本文就到这里,谢谢观看 ~

标题关闭

以上就是Flutter Flow实现滑动显隐层示例详解的详细内容,更多关于Flutter Flow滑动显隐层的资料请关注脚本之家其它相关文章!

相关文章

  • Android开发中实现应用的前后台切换效果

    Android开发中实现应用的前后台切换效果

    这篇文章主要介绍了Android开发中实现应用的前后台切换效果的方法,文章最后还附带了监听程序是否进入后台的判断方法,需要的朋友可以参考下
    2016-02-02
  • Android中的ViewPager视图滑动切换类的入门实例教程

    Android中的ViewPager视图滑动切换类的入门实例教程

    Android中ViewPager通常与Fragments组件共同使用来实现视图切换功能,本文就带大家一起来学习Android中的ViewPager视图滑动切换类的入门实例教程:
    2016-06-06
  • Android实现LED发光字效果

    Android实现LED发光字效果

    这篇文章主要为大家详细介绍了Android实现LED发光字效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • 安卓图片反复压缩后为什么普遍会变绿而不是其它颜色?

    安卓图片反复压缩后为什么普遍会变绿而不是其它颜色?

    今天小编就为大家分享一篇关于安卓图片反复压缩后为什么普遍会变绿而不是其它颜色?,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • Android如何绘制发光效果详解

    Android如何绘制发光效果详解

    这篇文章主要给大家介绍了关于Android如何绘制发光效果的相关资料,文中通过示例代码介绍的非常详细,对各位Android开发者们具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-07-07
  • 解决Android Studio一直停留在MyApplication:syncing的问题

    解决Android Studio一直停留在MyApplication:syncing的问题

    这篇文章主要介绍了Android Studio一直停留在MyApplication:syncing的完美解决方案,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • 利用Android实现比较炫酷的自定义View

    利用Android实现比较炫酷的自定义View

    自定义View、多线程、网络,被认为是Android开发者必须牢固掌握的最基础的三大基本功,这篇文章主要给大家介绍了关于如何利用Android实现比较炫酷的自定义View的相关资料,需要的朋友可以参考下
    2021-07-07
  • Android控件SeekBar仿淘宝滑动验证效果

    Android控件SeekBar仿淘宝滑动验证效果

    这篇文章主要为大家详细介绍了Android控件SeekBar仿淘宝滑动验证效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • 详解Android ContentProvider的基本原理和使用

    详解Android ContentProvider的基本原理和使用

    ContentProvider(内容提供者)是 Android 的四大组件之一,管理 Android 以结构化方式存放的数据,以相对安全的方式封装数据(表)并且提供简易的处理机制和统一的访问接口供其他程序调用
    2021-06-06
  • Android基础总结篇之三:Activity的task相关介绍

    Android基础总结篇之三:Activity的task相关介绍

    这篇文章主要介绍了Android基础总结篇之三:Activity的task相关介绍,具有一定的参考价值,有需要的可以了解一下。
    2016-11-11

最新评论