Skip to content

Instantly share code, notes, and snippets.

@mkiisoft
Created November 27, 2019 20:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mkiisoft/e963b18d3b58410b8428752129df2c16 to your computer and use it in GitHub Desktop.
Save mkiisoft/e963b18d3b58410b8428752129df2c16 to your computer and use it in GitHub Desktop.
Draggable Card
@override
Widget build(BuildContext context) {
final width = MediaQuery
.of(context)
.size
.width - 80;
return Material(
child: Scaffold(
body: Container(
child: Align(
alignment: Alignment.center,
child: Stack(
alignment: Alignment.center,
children: <Widget>[
AnimatedContainer(
duration: Duration(milliseconds: 250),
curve: Curves.decelerate,
padding: EdgeInsets.only(
left: isActive ? 64 : 96,
right: isActive ? 64 : 96,
top: isActive ? 48 : 64,
bottom: isActive ? 96 : 128),
child: Container(
width: width,
height: width / 1.6,
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: Color(0x509C27B0),
offset: Offset(0, 10),
blurRadius: 20,
)
]),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
color: Colors.purple,
),
),
),
AnimatedContainer(
duration: Duration(milliseconds: 250),
curve: Curves.decelerate,
padding: EdgeInsets.only(
left: isActive ? 32 : 64,
right: isActive ? 32 : 64,
top: isActive ? 16 : 32,
bottom: isActive ? 32 : 64),
child: Container(
width: width,
height: width / 1.6,
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: Color(0x50E040FB),
offset: Offset(0, 10),
blurRadius: 20,
)
]),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
color: Colors.purpleAccent,
),
),
),
DraggableCard(
callback: (started) {
setState(() {
isActive = started;
});
},
child: Center(
child: mainCard(width),
),
),
],
),
),
),
),
);
}
//// DRAGGABLE CARD
typedef CardCallback = void Function(bool);
class DraggableCard extends StatefulWidget {
final Widget child;
final CardCallback callback;
const DraggableCard({Key key, @required this.child, @required this.callback}) : super(key: key);
@override
_DraggableCardState createState() => _DraggableCardState();
}
class _DraggableCardState extends State<DraggableCard> with TickerProviderStateMixin {
AnimationController _controller;
Animation<Offset> _spring;
final _position = ValueNotifier<Offset>(Offset.zero);
Offset _return;
Offset _start;
@override
void initState() {
super.initState();
_controller = AnimationController.unbounded(vsync: this);
_controller.addListener(() {
_position.value = _spring.value;
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onPanStart: _onPanStart,
onPanDown: _onPanDown,
onPanUpdate: _onPanUpdate,
onPanEnd: _onPanEnd,
child: AnimatedBuilder(
animation: _position,
builder: (BuildContext context, Widget child) {
return Transform.translate(
offset: _position.value,
child: child,
);
},
child: widget.child,
),
);
}
void _onPanStart(details) {
widget.callback(true);
}
void _onPanDown(details) {
_controller.stop();
_start = details.globalPosition;
_return = _position.value;
}
void _onPanUpdate(details) {
_position.value = _return + details.globalPosition - _start;
}
void _onPanEnd(details) {
widget.callback(false);
final v = details.velocity.pixelsPerSecond;
_spring = Tween<Offset>(
begin: _position.value,
end: Offset.zero,
).animate(_controller);
_controller.animateWith(SpringSimulation(
SpringDescription.withDampingRatio(
mass: 1.5,
stiffness: 90,
ratio: 1.0,
),
0.0,
1.0,
math.min(math.max(v.dx, v.dy), 50),
));
}
}
Widget mainCard(double width) {
return Container(
width: width,
height: width / 1.6,
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: Color(0x50000000),
offset: Offset(0, 10),
blurRadius: 20,
)
]),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
color: Colors.black,
child: Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(25),
child: IntrinsicHeight(
child: Row(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Flutter Design",
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w500,
),
),
Padding(
padding: const EdgeInsets.only(top: 5),
child: Text(
"certificate",
style: TextStyle(
color: Colors.blue,
fontSize: 18,
fontWeight: FontWeight.w500,
),
),
),
],
),
Expanded(
child: Align(
alignment: Alignment.topRight,
child: Image.asset(
"images/flutter_highlight.png",
width: 40,
height: 40,
),
),
)
],
),
),
),
Positioned(
bottom: -80,
right: -30,
width: 250,
child: Opacity(
opacity: 0.8,
child: Image.asset(
"images/outline.png",
color: Colors.white,
),
),
),
],
),
),
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment