app-starlock/lib/tools/left_slide_actions.dart
2024-05-18 09:37:50 +08:00

125 lines
3.0 KiB
Dart
Executable File

import 'package:flutter/material.dart';
typedef _BaseFunction<T> = void Function(T o);
/// 来源: https://blog.csdn.net/zhuowalun8427/article/details/121285947 。
class LeftSlideActions extends StatefulWidget {
final double actionsWidth;
final List<Widget> actions;
final Widget child;
final Decoration? decoration;
final VoidCallback? actionsWillShow;
final _BaseFunction<VoidCallback>? exportHideActions;
const LeftSlideActions({
Key? key,
required this.actionsWidth,
required this.actions,
required this.child,
this.decoration,
this.actionsWillShow,
this.exportHideActions,
}) : super(key: key);
@override
_LeftSlideActionsState createState() => _LeftSlideActionsState();
}
class _LeftSlideActionsState extends State<LeftSlideActions>
with TickerProviderStateMixin {
double _translateX = 0;
late AnimationController _controller;
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
void initState() {
super.initState();
_controller = AnimationController(
lowerBound: -widget.actionsWidth,
upperBound: 0,
vsync: this,
duration: const Duration(milliseconds: 300),
)..addListener(() {
_translateX = _controller.value;
setState(() {});
});
if (widget.exportHideActions != null) {
widget.exportHideActions!(_hide);
}
}
@override
Widget build(BuildContext context) {
return Container(
decoration: widget.decoration,
clipBehavior: Clip.hardEdge,
child: Stack(
children: [
Positioned.fill(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: widget.actions,
),
),
GestureDetector(
onHorizontalDragUpdate: (v) {
_onHorizontalDragUpdate(v);
},
onHorizontalDragEnd: (v) {
_onHorizontalDragEnd(v);
},
child: Transform.translate(
offset: Offset(_translateX, 0),
child: Row(
children: [
Expanded(flex: 1, child: widget.child),
],
),
),
),
],
),
);
}
void _onHorizontalDragUpdate(DragUpdateDetails details) {
_translateX = (_translateX + details.delta.dx).clamp(-widget.actionsWidth, 0.0);
setState(() {});
}
void _onHorizontalDragEnd(DragEndDetails details) {
_controller.value = _translateX;
if (details.velocity.pixelsPerSecond.dx > 200) {
_hide();
} else if (details.velocity.pixelsPerSecond.dx < -200) {
_show();
} else {
if (_translateX.abs() > widget.actionsWidth / 2) {
_show();
} else {
_hide();
}
}
}
void _show() {
if (widget.actionsWillShow != null) {
widget.actionsWillShow!();
}
if (_translateX != -widget.actionsWidth) {
_controller.animateTo(-widget.actionsWidth);
}
}
void _hide() {
if (_translateX != 0) {
_controller.animateTo(0);
}
}
}