在android实现类似微信的侧滑删除比较复杂,需要使用到ViewDragHelper,各种手势判断。而在flutter中实现却很简单,几种控件组合起来就可以实现,先看一下效果图。
使用方法:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("SlideButton"),
),
body: ListView(
children: getSlides(),
),
);
}
List list;
List getSlides() {
list = List();
for (var i = 0; i < 10; i++) {
var key = GlobalKey();
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: [
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 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: [
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: [
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(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中查看