天天看点

使用Flutter模仿SOUL可任意拖动的悬浮按钮

在Flutter中,我们可以两种方式实现小部件对拖动效果

  • GestureDetector()
  • Draggable()

GestureDetector

在开发过程中经常使用到GestureDetector的onTap的点击手势,在编辑器中点击GestureDetector进入它的定义可以看到很多手势,但在实现我们想要的拖动效果时,只需要用到以下两个事件:

GestureDetector(
	//更新child的位置
	onPanUpdate: (details) {},
	//拖动结束,处理child贴边悬浮
	onPanEnd: (details) {},
	//悬浮部件布局
	child: Container(...)
)

           

因为想要实现在屏幕内的任意拖动,所以我们在Stack()内,将悬浮Widget的拖动范围设置在Stack的Positioned()中,来实现在屏幕内的任意拖动:

//设定Widget的偏移量
Offset offset = Offset(20, kToolbarHeight + 100);

Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(children: <Widget>[
        ...
        Positioned(
      	  left: offset.dx,
          top: offset.dy,
          child: GestureDetector(
	        //更新child的位置
	        onPanUpdate: (details) {},
	        //拖动结束,处理child贴边悬浮
	        onPanEnd: (details) {},
	        //悬浮部件布局
	       child: Container(...)
         )
      ]),
    );
  }
           
使用Flutter模仿SOUL可任意拖动的悬浮按钮

Draggable

Draggable可以创建一个被拖动的Widget,但是对应参数child和feedback不能被设置null,为必填参数:

Draggable(
  //创建可以被拖动的Widget
  child: widgetItem('original'),
  //拖动过程中的Widget
  feedback: widgetItem('dragging'),
  //拖动过程中,在原来位置停留的Widget,设定这个可以保留原本位置的残影,如果不需要可以直接设置为Container()
  childWhenDragging: widgetItem('trace'),
  //拖动结束后的Widget
  onDraggableCanceled: (Velocity velocity, Offset offset) {
  	...//更新位置信息
  }
)
           

实现的代码和第一种方式类似

Demo源码>