Created
January 14, 2021 17:11
-
-
Save nhancv/7e3254ac67754b115657e4f0880f8277 to your computer and use it in GitHub Desktop.
Flutter draggable widget
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Draggable widget | |
class _WDraggable extends StatefulWidget { | |
const _WDraggable({Key key, this.child, this.valueChanged}) : super(key: key); | |
final Widget child; | |
final ValueChanged<Offset> valueChanged; | |
@override | |
_WDraggableState createState() => _WDraggableState(); | |
} | |
class _WDraggableState extends State<_WDraggable> { | |
ValueNotifier<Offset> valueListener = ValueNotifier<Offset>(const Offset(1, 1)); | |
@override | |
void initState() { | |
valueListener.addListener(_notifyParent); | |
super.initState(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Builder( | |
builder: (BuildContext context) { | |
final GestureDetector handle = GestureDetector( | |
onPanUpdate: (DragUpdateDetails details) { | |
final double dx = (valueListener.value.dx + | |
(details.delta.dx / context.size.width)) | |
.clamp(0.0, 1.0) | |
.toDouble(); | |
final double dy = (valueListener.value.dy - | |
(details.delta.dy / context.size.height)) | |
.clamp(0.0, 1.0) | |
.toDouble(); | |
valueListener.value = Offset(dx, dy); | |
}, | |
child: widget.child, | |
); | |
return AnimatedBuilder( | |
animation: valueListener, | |
builder: (_, Widget child) { | |
return Align( | |
alignment: Alignment(valueListener.value.dx * 2 - 1, | |
1 - valueListener.value.dy * 2), | |
child: child, | |
); | |
}, | |
child: handle, | |
); | |
}, | |
); | |
} | |
// Notify change to parent | |
void _notifyParent() { | |
if (widget.valueChanged != null) { | |
widget.valueChanged(valueListener.value); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
/// Draggable widget Horizontal only, constraining with parent size | |
class WDraggableH extends StatefulWidget { | |
const WDraggableH(this.child, {Key key, this.valueChanged}) : super(key: key); | |
final Widget child; | |
final ValueChanged<double> valueChanged; | |
@override | |
_WDraggableHState createState() => _WDraggableHState(); | |
} | |
class _WDraggableHState extends State<WDraggableH> { | |
ValueNotifier<double> valueListener = ValueNotifier<double>(0); | |
@override | |
void initState() { | |
valueListener.addListener(_notifyParent); | |
super.initState(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Builder( | |
builder: (BuildContext context) { | |
final GestureDetector handle = GestureDetector( | |
onHorizontalDragUpdate: (DragUpdateDetails details) { | |
valueListener.value = | |
(valueListener.value + (details.delta.dx / context.size.width)) | |
.clamp(0.0, 1.0) | |
.toDouble(); | |
}, | |
child: widget.child, | |
); | |
return AnimatedBuilder( | |
animation: valueListener, | |
builder: (_, Widget child) { | |
return Align( | |
alignment: Alignment(valueListener.value * 2 - 1, 0), | |
child: child, | |
); | |
}, | |
child: handle, | |
); | |
}, | |
); | |
} | |
// Notify change to parent | |
void _notifyParent() { | |
if (widget.valueChanged != null) { | |
widget.valueChanged(valueListener.value); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
/// Draggable widget Vertical only, constraining with parent size | |
class WDraggableV extends StatefulWidget { | |
const WDraggableV({Key key, this.child, this.valueChanged}) : super(key: key); | |
final Widget child; | |
final ValueChanged<double> valueChanged; | |
@override | |
_WDraggableVState createState() => _WDraggableVState(); | |
} | |
class _WDraggableVState extends State<WDraggableV> { | |
ValueNotifier<double> valueListener = ValueNotifier<double>(0); | |
@override | |
void initState() { | |
valueListener.addListener(_notifyParent); | |
super.initState(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Builder( | |
builder: (BuildContext context) { | |
final GestureDetector handle = GestureDetector( | |
onVerticalDragUpdate: (DragUpdateDetails details) { | |
valueListener.value = | |
(valueListener.value - (details.delta.dy / context.size.height)) | |
.clamp(0.0, 1.0) | |
.toDouble(); | |
}, | |
child: widget.child, | |
); | |
return AnimatedBuilder( | |
animation: valueListener, | |
builder: (_, Widget child) { | |
return Align( | |
alignment: Alignment(0, 1 - valueListener.value * 2), | |
child: child, | |
); | |
}, | |
child: handle, | |
); | |
}, | |
); | |
} | |
// Notify change to parent | |
void _notifyParent() { | |
if (widget.valueChanged != null) { | |
widget.valueChanged(valueListener.value); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment