在此处提供的完整代码中,来自
drag-and-drop
的 left to right
工作完美,允许我显示底层小部件。现在,我要介绍的更改是如何将 drag-and-drop
中的 right to left
添加到其中,这样我就可以将顶部小部件移动到左侧。
我的意思是,如何给它添加从右到左的反向拖放操作?
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
brightness: Brightness.dark,
),
home: const MyHome(),
);
}
}
class MyHome extends StatefulWidget {
const MyHome();
@override
State<StatefulWidget> createState() => _MyHome();
}
class _MyHome extends State<MyHome> with SingleTickerProviderStateMixin {
late AnimationController _animationController;
final double maxSlide = 225.0;
final double minDragStartEdge = 150.0;
final double maxDragStartEdge = 250.0;
bool _canBeDragged = true;
@override
void initState() {
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 250),
);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onHorizontalDragStart: _onDragStart,
onHorizontalDragUpdate: _onDragUpdate,
onHorizontalDragEnd: _onDragEnd,
child: AnimatedBuilder(
animation: _animationController,
builder: (BuildContext context, _) {
final slide = maxSlide * _animationController.value;
final scale = 1 - (_animationController.value / 0.20);
return Stack(
children: [
const Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'TEST',
style: TextStyle(color: Colors.white, fontSize: 32.0),
),
],
),
Transform(
transform: Matrix4.identity()
..translate(slide)
..scale(scale),
alignment: Alignment.centerLeft,
child: SizedBox.expand(
child: Container(
color:Colors.white,
margin: const EdgeInsets.only(top:50),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
children: [
IconButton(
onPressed: () {
},
icon: const Icon(Icons.menu)),
const Text('Appbar'),
],
),
const Text(
'TEXT',
style: TextStyle(color: Colors.black, fontSize: 32.0),
),
],
),
),
),
),
],
);
},
),
),
);
}
void _onDragStart(DragStartDetails details) {
final isDragOpenFromLeft = _animationController.isDismissed &&
details.globalPosition.dx < minDragStartEdge;
final isDragCloseFromRight = _animationController.isCompleted &&
details.globalPosition.dx > maxDragStartEdge;
_canBeDragged = isDragOpenFromLeft || isDragCloseFromRight;
}
void _onDragUpdate(DragUpdateDetails details) {
if (_canBeDragged) {
final delta = details.primaryDelta! / maxSlide;
_animationController.value += delta;
}
}
void _onDragEnd(DragEndDetails details) {
if (_animationController.isDismissed || _animationController.isCompleted) {
return;
}
if (details.velocity.pixelsPerSecond.dx.abs() >= 165.0) {
final visualVelocity = details.velocity.pixelsPerSecond.dx /
MediaQuery.of(context).size.width;
_animationController.fling(velocity: visualVelocity);
} else if (_animationController.value < 0.5) {
closeDrawer();
} else {
openDrawer();
}
}
void openDrawer() {
_animationController.forward();
}
void closeDrawer() {
_animationController.reverse();
}
}
我认为编辑这部分代码就足够了。
void _onDragStart(DragStartDetails details) {
final isDragOpenFromLeft = _animationController.isDismissed &&
details.globalPosition.dx < minDragStartEdge;
final isDragCloseFromRight = _animationController.isCompleted &&
details.globalPosition.dx > maxDragStartEdge;
_canBeDragged = isDragOpenFromLeft || isDragCloseFromRight;
}
这将处理从右到左的过渡。 _canBeDragged 名称在这里有点令人困惑,但无论如何:
void _onDragUpdate(DragUpdateDetails details) {
final delta = details.primaryDelta! / maxSlide;
if (_canBeDragged) {
_animationController.value += delta;
} else {
_animationController.value -= delta;
}
}
对动画有意义的其他更改:
void _onDragEnd(DragEndDetails details) {
if (_animationController.isDismissed || _animationController.isCompleted) {
return;
}
if (_animationController.value < 0.3) {
closeDrawer();
} else {
openDrawer();
}
}
此外,我会将
Scaffold
与 GestureDetector
交换,这样当抽屉打开时,整个屏幕都会监听拖动。
您提供的代码允许从左到右拖动以显示底层小部件。要还启用从右向左拖动以将顶部小部件移动到左侧,您需要进行一些调整。
这是修改后的代码:
void _onDragStart(DragStartDetails details) {
final isDragOpenFromLeft = _animationController.isDismissed &&
details.globalPosition.dx < minDragStartEdge;
final isDragCloseFromRight = _animationController.isCompleted &&
details.globalPosition.dx > maxDragStartEdge;
final isDragOpenFromRight = _animationController.isDismissed &&
details.globalPosition.dx > maxDragStartEdge;
final isDragCloseFromLeft = _animationController.isCompleted &&
details.globalPosition.dx < minDragStartEdge;
_canBeDragged = isDragOpenFromLeft || isDragCloseFromRight || isDragOpenFromRight || isDragCloseFromLeft;
}
void _onDragUpdate(DragUpdateDetails details) {
if (_canBeDragged) {
final delta = details.primaryDelta! / maxSlide;
_animationController.value += delta;
}
}
void _onDragEnd(DragEndDetails details) {
if (_animationController.isDismissed || _animationController.isCompleted) {
return;
}
final moveRight = details.velocity.pixelsPerSecond.dx > 0;
if (moveRight) {
if (details.velocity.pixelsPerSecond.dx.abs() >= 165.0) {
final visualVelocity = details.velocity.pixelsPerSecond.dx /
MediaQuery.of(context).size.width;
_animationController.fling(velocity: visualVelocity);
} else if (_animationController.value < 0.5) {
closeDrawer();
} else {
openDrawer();
}
} else {
if (details.velocity.pixelsPerSecond.dx.abs() >= 165.0) {
final visualVelocity = details.velocity.pixelsPerSecond.dx /
MediaQuery.of(context).size.width;
_animationController.fling(velocity: visualVelocity);
} else if (_animationController.value > 0.5) {
openDrawer();
} else {
closeDrawer();
}
}
}