admin管理员组文章数量:1318564
I am trying to achieve same movement as the mac doc
here is the link
But here is my project, using ReorderableListView in flutter, i am not able to move the items vertically, i am only able to move items horizontally freely
i want if i select the items, i could drags and hover the item anywhere in the screen like macos doc, not just horizontal here is the link - what i am able to achieve -(here
here is my build function
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Column(
children: [
SizedBox(
height: MediaQuery.sizeOf(context).height * .12,
),
const Center(
child: Text(
'Mac Dock',
style: TextStyle(color: Colors.white, fontSize: 30),
),
),
SizedBox(
height: MediaQuery.sizeOf(context).height * .20,
),
Center(
child: Container(
height: 70,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10)),
gradient: LinearGradient(colors: [
Colors.blueAccent,
Colors.greenAccent,
]),
),
padding: EdgeInsets.all(controller.verticlItemsPadding),
// 1.
child: ReorderableListView(
onReorderStart: (index) {
setState(() {
controller.hoveredIndex = null;
});
},
onReorderEnd: (index) {
setState(() {
controller.hoveredIndex = null;
});
},
proxyDecorator: proxyDecorator,
shrinkWrap: true,
onReorder: _update,
buildDefaultDragHandles: false,
scrollDirection: Axis.horizontal,
children: List.generate(
iconslist.length,
(index) {
// 2.
return ReorderableDragStartListener(
index: index,
key: ValueKey(iconslist[index]),
child: MouseRegion(
cursor: SystemMouseCursors.click,
onEnter: ((event) {
setState(() {
controller.hoveredIndex = index.toDouble();
});
}),
onExit: (event) {
setState(() {
controller.hoveredIndex = null;
});
},
// 3.
child: AnimatedContainer(
color: Colors.red,
duration: const Duration(
milliseconds: 150,
),
transform: Matrix4.identity()
..translate(
0.0,
controller.getTranslationY(index),
0.0,
),
height:
controller.getScaledSize(index), //baseItemHeight,
width: controller
.getScaledSize(index), // baseItemHeight,
alignment: AlignmentDirectional.center,
margin: const EdgeInsets.symmetric(
// horizontal: 2,
),
// 4.
child: iconslist[index],
),
),
);
},
).toList(),
),
),
),
],
),
);
}
i tried to use reorderable listview for the problem, and it restrict my view to horizontal movement
I am trying to achieve same movement as the mac doc
here is the link
But here is my project, using ReorderableListView in flutter, i am not able to move the items vertically, i am only able to move items horizontally freely
i want if i select the items, i could drags and hover the item anywhere in the screen like macos doc, not just horizontal here is the link - what i am able to achieve -(here
here is my build function
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Column(
children: [
SizedBox(
height: MediaQuery.sizeOf(context).height * .12,
),
const Center(
child: Text(
'Mac Dock',
style: TextStyle(color: Colors.white, fontSize: 30),
),
),
SizedBox(
height: MediaQuery.sizeOf(context).height * .20,
),
Center(
child: Container(
height: 70,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10)),
gradient: LinearGradient(colors: [
Colors.blueAccent,
Colors.greenAccent,
]),
),
padding: EdgeInsets.all(controller.verticlItemsPadding),
// 1.
child: ReorderableListView(
onReorderStart: (index) {
setState(() {
controller.hoveredIndex = null;
});
},
onReorderEnd: (index) {
setState(() {
controller.hoveredIndex = null;
});
},
proxyDecorator: proxyDecorator,
shrinkWrap: true,
onReorder: _update,
buildDefaultDragHandles: false,
scrollDirection: Axis.horizontal,
children: List.generate(
iconslist.length,
(index) {
// 2.
return ReorderableDragStartListener(
index: index,
key: ValueKey(iconslist[index]),
child: MouseRegion(
cursor: SystemMouseCursors.click,
onEnter: ((event) {
setState(() {
controller.hoveredIndex = index.toDouble();
});
}),
onExit: (event) {
setState(() {
controller.hoveredIndex = null;
});
},
// 3.
child: AnimatedContainer(
color: Colors.red,
duration: const Duration(
milliseconds: 150,
),
transform: Matrix4.identity()
..translate(
0.0,
controller.getTranslationY(index),
0.0,
),
height:
controller.getScaledSize(index), //baseItemHeight,
width: controller
.getScaledSize(index), // baseItemHeight,
alignment: AlignmentDirectional.center,
margin: const EdgeInsets.symmetric(
// horizontal: 2,
),
// 4.
child: iconslist[index],
),
),
);
},
).toList(),
),
),
),
],
),
);
}
i tried to use reorderable listview for the problem, and it restrict my view to horizontal movement
Share Improve this question edited Jan 21 at 10:39 DarkBee 15.6k8 gold badges72 silver badges117 bronze badges asked Jan 21 at 10:34 Varun GoelVarun Goel 111 bronze badge 4- What's your controller? – Ravindra S. Patil Commented Jan 21 at 11:00
- Please refer to this answer: ReorderableListview Implementation – aolsan Commented Jan 21 at 12:16
- I want to freely able to drag the selected icon anywhere in the screen, but reorderable listview constrains me on one axis only (here horizonal axis). – Varun Goel Commented Jan 21 at 14:38
- the controller is a getx controller, used to handle the animation stuff, like magnifying the icon on hover of the mouse – Varun Goel Commented Jan 21 at 14:39
1 Answer
Reset to default 0Track your desired vertical drag offset as a state variable, which is initially zero:
double _verticalDragOffset = 0;
Wrap each of your reorderable Widgets in a Listener
that detects drags and updates your vertical drag offset accordingly:
Listener(
// Make sure this doesn't block hit testing on the child.
behavior: HitTestBehavior.translucent,
onPointerMove: (event) {
setState(() => _verticalDragOffset += event.delta.dy);
},
child: /* your child here */,
)
Use the proxyDecorator
callback of ReorderableListView
to reposition dragged items to the correct vertical offset using Transform.translate
. The vertical offset needs to be interpolated using the proxy animation so that the dragged item animates to its final position when released.
Widget _proxyDecorator(child, index, Animation<double> animation) {
return AnimatedBuilder(
animation: animation,
builder: (_, __) {
// ReorderableListView uses Curves.easeOut internally, so you must use
// Curves.easeOut here to ensure the vertical and horizontal positions
// animate at the same rate.
final double animValue = Curves.easeOut.transform(animation.value);
final verticalOffset = animation.isForwardOrCompleted
? _verticalDragOffset
: lerpDouble(0, _verticalDragOffset, animValue)!;
return Transform.translate(
offset: Offset(0, verticalOffset),
child: child,
);
},
);
}
Finally, the vertical drag offset needs to be reset whenever a new drag is started. You can do this in the onReorderStart
callback of ReorderableListView
. Also, pass our proxyDecorator
implementation.
ReorderableListView(
onReorderStart: (_) => setState(() => _verticalDragOffset = 0),
proxyDecorator: _proxyDecorator,
...
)
Here's a complete example that puts this all together and uses the design in your post.
Result
Implementation
import 'dart:ui';
import 'package:flutter/material.dart';
void main() => runApp(const ReorderableApp());
class ReorderableApp extends StatelessWidget {
const ReorderableApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
home: Scaffold(
appBar: AppBar(title: const Text('ReorderableListView Sample')),
body: const ReorderableExample(),
),
);
}
}
class ReorderableExample extends StatefulWidget {
const ReorderableExample({super.key});
@override
State<ReorderableExample> createState() => _ReorderableExampleState();
}
class _ReorderableExampleState extends State<ReorderableExample> {
final _items = [
(Icons.person, Colors.amber),
(Icons.camera, Colors.orange),
(Icons.phone, Colors.blue),
(Icons.message, Colors.green),
];
double _verticalDragOffset = 0;
Widget _proxyDecorator(child, index, Animation<double> animation) {
return AnimatedBuilder(
animation: animation,
builder: (_, __) {
// ReorderableListView uses Curves.easeOut internally, so you must use
// Curves.easeOut here to ensure the vertical and horizontal positions
// animate at the same rate.
final double animValue = Curves.easeOut.transform(animation.value);
final verticalOffset = animation.isForwardOrCompleted
? _verticalDragOffset
: lerpDouble(0, _verticalDragOffset, animValue)!;
return Transform.translate(
offset: Offset(0, verticalOffset),
child: child,
);
},
);
}
@override
Widget build(BuildContext context) {
return Center(
child: Container(
height: 75,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(15)),
gradient: LinearGradient(colors: [
Colors.blueAccent,
Colors.greenAccent,
]),
),
padding: const EdgeInsets.all(15),
child: ReorderableListView(
shrinkWrap: true,
buildDefaultDragHandles: false,
scrollDirection: Axis.horizontal,
onReorderStart: (_) => setState(() => _verticalDragOffset = 0),
proxyDecorator: _proxyDecorator,
onReorder: (oldIndex, newIndex) => setState(() {
if (oldIndex < newIndex) {
newIndex -= 1;
}
final item = _items.removeAt(oldIndex);
_items.insert(newIndex, item);
}),
children: [
for (int index = 0; index < _items.length; index++)
ReorderableDragStartListener(
key: ObjectKey(_items[index].$1),
index: index,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: Listener(
behavior: HitTestBehavior.translucent,
onPointerMove: (event) {
setState(() => _verticalDragOffset += event.delta.dy);
},
child: AspectRatio(
aspectRatio: 1,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(7),
color: _items[index].$2,
),
child: Icon(_items[index].$1, color: Colors.white),
),
),
),
),
),
],
),
),
);
}
}
本文标签: flutterHow to move items freely in ReorderableListViewStack Overflow
版权声明:本文标题:flutter - How to move items freely in ReorderableListView? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742049399a2417983.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论