Flutter侧滑删除控件

在android实现类似微信的侧滑删除比较复杂,需要使用到ViewDragHelper,各种手势判断。而在flutter中实现却很简单,几种控件组合起来就可以实现,先看一下效果图。
在这里插入图片描述

使用方法:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("SlideButton"),
      ),
      body: ListView(
        children: getSlides(),
      ),
    );
  }

  List<SlideButton> list;

  List<SlideButton> getSlides() {
    list = List<SlideButton>();
    for (var i = 0; i < 10; i++) {
      var key = GlobalKey<SlideButtonState>();
      var slide = SlideButton(
        key: key,
        singleButtonWidth: 80,
        onSlideStarted: (){
          list.forEach((slide){
            if(slide.key!=key){
              slide.key.currentState?.close();
            }
          });
        },
        child: Container(
          color: Colors.white,
          child: ListTile(
            title: Text("测试测试测试测试测试测试测试测试"),
          ),
        ),
        //滑动开显示的button
        buttons: <Widget>[
          buildAction(key, "置顶", Colors.grey[400], () {
            Fluttertoast.showToast(msg: "置顶");
            key.currentState.close();
          }),
          buildAction(key, "标为未读", Colors.amber, () {
            Fluttertoast.showToast(msg: "标为未读");
            key.currentState.close();
          }),
          buildAction(key, "删除", Colors.red, () {
            Fluttertoast.showToast(msg: "删除");
            key.currentState.close();
          }),
        ],
      );
      list.add(slide);
    }
    return list;
  }

	//构建button
  InkWell buildAction(GlobalKey<SlideButtonState> key, String text, Color color,
      GestureTapCallback tap) {

    return InkWell(
      onTap: tap,
      child: Container(
        alignment: Alignment.center,
        width: 80,
        color: color,
        child: Text(text,
            style: TextStyle(
              color: Colors.white,
            )),
      ),
    );
  }

整体布局

Stack(
      children: <Widget>[
        Positioned.fill(
            child: Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: widget.buttons,//actionButtons
        )),
        RawGestureDetector(
          gestures: gestures,
          //Transform,顾名思义就是偏移,设置偏移量就可以使控件发生偏移
          child: Transform.translate(
            offset: Offset(translateX, 0),
            child: Row(
              children: <Widget>[
                Expanded(
                  flex: 1,
                  //item布局
                  child: widget.child,
                )
              ],
            ),
          ),
        )
      ],
    )

动画及手势

动画及手势请参考解析Flutter中的手势控制Gestures

@override
  void initState() {
    super.initState();
    //最大偏移量,单个button宽度*button个数
    maxDragDistance = widget.singleButtonWidth * widget.buttons.length;
    gestures[HorizontalDragGestureRecognizer] =
        GestureRecognizerFactoryWithHandlers<HorizontalDragGestureRecognizer>(
      () => HorizontalDragGestureRecognizer(debugOwner: this),
      (HorizontalDragGestureRecognizer instance) {
        instance
          ..onDown = onHorizontalDragDown
          ..onUpdate = onHorizontalDragUpdate
          ..onEnd = onHorizontalDragEnd;
      },
    );
    //动画控制器
    animationController = AnimationController(
        lowerBound: -maxDragDistance,
        upperBound: 0,
        vsync: this,
        duration: Duration(milliseconds: 300))
      ..addListener(() {
        translateX = animationController.value;
        setState(() {});
      });
  }
//当手指按下时
void onHorizontalDragDown(DragDownDetails details) {
    if (widget.onSlideStarted != null) widget.onSlideStarted.call();
  }

//当手指滑动时
  void onHorizontalDragUpdate(DragUpdateDetails details) {
    //手势更新,更新偏移量
    translateX = (translateX + details.delta.dx).clamp(-maxDragDistance, 0.0);
    setState(() {});
  }

//当手指离开屏幕时
  void onHorizontalDragEnd(DragEndDetails details) {
    animationController.value = translateX;
    //用户拖动到一半时自动完成、取消操作
    //当手指离开屏幕是判断x轴方向的速度,速度大于200,关闭
    if (details.velocity.pixelsPerSecond.dx > 200) {
      close();
      //速度小于-200,打开
    } else if (details.velocity.pixelsPerSecond.dx < -200) {
      open();
    } else {
      //当偏移量大于最大偏移量的一半时打开,否则关闭
      if (translateX.abs() > maxDragDistance / 2) {
        open();
      } else {
        close();
      }
    }
  }

  void open() {
    if (translateX != -maxDragDistance)
      animationController.animateTo(-maxDragDistance).then((_) {
      	//滑动完成回调
        if (widget.onSlideCompleted != null) widget.onSlideCompleted.call();
      });
  }

  void close() {
    if (translateX != 0)
      animationController.animateTo(0).then((_) {
      	//滑动取消回调
        if (widget.onSlideCanceled != null) widget.onSlideCanceled.call();
      });
  }

flutter中实现滑动删除真是简单,仅仅用了100多行代码就实现了我们需要的效果。在android中很复杂的效果在flutter中都能很简单的实现。完整代码请到github中查看

猜你喜欢

转载自blog.csdn.net/ZYJWR/article/details/93411016