效果图


关键控件
Transform.translate - 平移变换组件
基本语法
Dart
Transform.translate(
offset: Offset(dx, dy), // 必需参数
child: Widget, // 要平移的子组件
transformHitTests: true, // 可选
)
核心参数: offset - 平移偏移量
Dart
dx: 水平方向偏移量(正数向右,负数向左)
dy: 垂直方向偏移量(正数向下,负数向上)
滑动中监听
Dart
onHorizontalDragStart: // 滑动开始时触发
onHorizontalDragUpdate: // 滑动过程中连续触发
onHorizontalDragEnd: // 滑动结束时触发
onHorizontalDragCancel: // 滑动被取消时触发
关键知识点
1.为什么向右滑动details.delta.dx为正数,向左滑动details.delta.dx为负数,
Dart
坐标系理解:
在Flutter的滑动事件中:
屏幕坐标系:原点(0,0)在屏幕左上角
X轴:从左到右是正方向
Y轴:从上到下是正方向
delta.dx 的含义:
delta.dx 表示水平方向的位移变化量
正值 = 向右滑动(手指从左边移动到右边)
负值 = 向左滑动(手指从右边移动到左边)
(0,0) 左上角
┌─────────────┐
│ │
│ +------│----> X轴 (正方向向右)
│ | │
│ ↓ │
│ Y轴 │
│ (正方向向下) │
└─────────────┘
实现步骤
1.定义变量
Dart
double _slideOffset = 0.0; //当前滑动偏移量
final double _maxSlideDistance = 60.0; // 最大滑动距离,删除按钮的宽度也设置了这个值
bool _showDeleteButton = false;//是否显示删除按钮提示
2.圆角矩形叠在删除按钮上面,所以要用stack组件,先构建删除按钮
Dart
// 删除按钮(在内容下面)
Positioned.fill(
child: Align(
alignment: Alignment.centerRight,
child: GestureDetector(
onTap: (){
//删除按钮的点击时间
print("点击删除按钮");
},
child: Container(
width: 60,
height: 40,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(20),
),
child: Center(
child: Icon(
Icons.delete,
color: Colors.white,
size: 20,
),
),
),
)
),
),
3.定义可滑动的内容
Dart
// 可滑动的内容
GestureDetector(
//处理滑动更新
onHorizontalDragUpdate: (details) {
setState(() {
//a -= b;表达式表示:a = a - b
//details.delta.dx表示用户手指在X轴移动的距离,向右滑动details.delta.dx为正数,向左滑动details.delta.dx为负数,(补充说明)
//从 _slideOffset 中减去 details.delta.dx 的值。
_slideOffset -= details.delta.dx;
//限制滑动范围
if (_slideOffset < 0) _slideOffset = 0; //不能向右移
if (_slideOffset > _maxSlideDistance) _slideOffset = _maxSlideDistance; //移动距离不能超过设置的最大滑动距离
//显示/隐藏删除按钮的逻辑
if (_slideOffset > 20 && !_showDeleteButton) {//左移大于20且删除按钮没有显示的时候
_showDeleteButton = true; //显示
} else if (_slideOffset < 20 && _showDeleteButton) {
_showDeleteButton = false;
}
});
},
//处理滑动结束
onHorizontalDragEnd: (details) {
if (_slideOffset > 30) { //用户左滑的距离大于30,则显示删除按钮
_slideOffset = _maxSlideDistance;
} else { //否则就不显示删除按钮
_slideOffset = 0;
_showDeleteButton = false;
}
setState(() {});
},
child: Transform.translate( //平移变换组件
//offset(dx,dy) //dx表示X轴偏移,dy表示Y轴偏移
//Offset(正数, 0) → 向右移动 ; Offset(负数, 0) → 向左移动
//Offset(10, 0)表示向右移动10像素 ; Offset(-10, 0)表示向左移动10像素 ;Offset(0, 0)表示不移动
offset: Offset(-_slideOffset, 0),//注意这里这里有个负号,所以这个小于零变成右移,大于零变成左移
child: Container(
width: 320,
height: 40,
decoration: BoxDecoration(
color: Color(0xFF1E2134),
borderRadius: BorderRadius.circular(20),
),
child: Center(
child: Text( //通过是否显示删除按钮,来更新文本
_showDeleteButton ? "松手删除" : "向右滑动显示删除",
style: TextStyle(
color: Colors.white,
fontSize: 16,
),
),
),
),
),
),
代码实例
Dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<StatefulWidget> createState() => _MeditationPageState();
}
class _MeditationPageState extends State<HomePage> with SingleTickerProviderStateMixin {
double _slideOffset = 0.0; //当前滑动偏移量
final double _maxSlideDistance = 60.0; // 最大滑动距离,删除按钮的宽度也设置了这个值
bool _showDeleteButton = false;//是否显示删除按钮提示
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
body: Container(
width: double.infinity,
height: double.infinity,
child: Center(
child: Container(
width: 320,
margin: EdgeInsets.symmetric(horizontal: 20),
child: Stack(
children: [
// 删除按钮(在内容下面)
Positioned.fill(
child: Align(
alignment: Alignment.centerRight,
child: GestureDetector(
onTap: (){
//删除按钮的点击时间
print("点击删除按钮");
},
child: Container(
width: 60,
height: 40,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(20),
),
child: Center(
child: Icon(
Icons.delete,
color: Colors.white,
size: 20,
),
),
),
)
),
),
// 可滑动的内容
GestureDetector(
//处理滑动更新
onHorizontalDragUpdate: (details) {
setState(() {
//a -= b;表达式表示:a = a - b
//details.delta.dx表示用户手指在X轴移动的距离,向右滑动details.delta.dx为正数,向左滑动details.delta.dx为负数,(补充说明)
//从 _slideOffset 中减去 details.delta.dx 的值。
_slideOffset -= details.delta.dx;
//限制滑动范围
if (_slideOffset < 0) _slideOffset = 0; //不能向右移
if (_slideOffset > _maxSlideDistance) _slideOffset = _maxSlideDistance; //移动距离不能超过设置的最大滑动距离
//显示/隐藏删除按钮的逻辑
if (_slideOffset > 20 && !_showDeleteButton) {//左移大于20且删除按钮没有显示的时候
_showDeleteButton = true; //显示
} else if (_slideOffset < 20 && _showDeleteButton) {
_showDeleteButton = false;
}
});
},
//处理滑动结束
onHorizontalDragEnd: (details) {
if (_slideOffset > 30) { //用户左滑的距离大于30,则显示删除按钮
_slideOffset = _maxSlideDistance;
} else { //否则就不显示删除按钮
_slideOffset = 0;
_showDeleteButton = false;
}
setState(() {});
},
child: Transform.translate( //平移变换组件
//offset(dx,dy) //dx表示X轴偏移,dy表示Y轴偏移
//Offset(正数, 0) → 向右移动 ; Offset(负数, 0) → 向左移动
//Offset(10, 0)表示向右移动10像素 ; Offset(-10, 0)表示向左移动10像素 ;Offset(0, 0)表示不移动
offset: Offset(-_slideOffset, 0),//注意这里这里有个负号,所以这个小于零变成右移,大于零变成左移
child: Container(
width: 320,
height: 40,
decoration: BoxDecoration(
color: Color(0xFF1E2134),
borderRadius: BorderRadius.circular(20),
),
child: Center(
child: Text( //通过是否显示删除按钮,来更新文本
_showDeleteButton ? "松手删除" : "向右滑动显示删除",
style: TextStyle(
color: Colors.white,
fontSize: 16,
),
),
),
),
),
),
],
),
),
),
),
);
}
}