Skip to content

Instantly share code, notes, and snippets.

@ltvu93
Last active February 26, 2024 10:03
Show Gist options
  • Save ltvu93/ab80ce3eb6ea385304136ec1e068c3ca to your computer and use it in GitHub Desktop.
Save ltvu93/ab80ce3eb6ea385304136ec1e068c3ca to your computer and use it in GitHub Desktop.
import 'dart:math' as math;
import 'dart:ui';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SplitView(
childOne: Container(
color: Colors.red,
),
childTwo: Container(
color: Colors.blue,
),
),
),
);
}
}
// https://medium.com/@leonar.d/how-to-create-a-flutter-split-view-7e2ac700ea12
class SplitView extends StatefulWidget {
final Widget childOne;
final Widget childTwo;
SplitView({
required this.childOne,
required this.childTwo,
});
@override
_SplitViewState createState() => _SplitViewState();
}
class _SplitViewState extends State<SplitView> with TickerProviderStateMixin {
final minChildOneHeight = 200.0;
final maxChildOneHeight = 400.0;
late AnimationController _animationController;
@override
void initState() {
super.initState();
_animationController = AnimationController(
duration: Duration(milliseconds: 300),
vsync: this,
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
AnimatedBuilder(
animation: _animationController,
builder: (_, child) {
return SizedBox(
height: lerpDouble(
minChildOneHeight,
maxChildOneHeight,
_animationController.value,
),
child: child,
);
},
child: widget.childOne,
),
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: _toggle,
onVerticalDragUpdate: _handleDragUpdate,
onVerticalDragEnd: _handleDragEnd,
child: SizedBox(
width: double.infinity,
height: 32.0,
child: Icon(Icons.drag_handle),
),
),
Expanded(
child: widget.childTwo,
),
],
);
}
// https://github.com/MarcinusX/buy_ticket_design/blob/master/lib/exhibition_bottom_sheet.dart#L136
void _toggle() {
final isOpen = _animationController.isCompleted;
_animationController.fling(velocity: isOpen ? -2 : 2);
}
void _handleDragUpdate(DragUpdateDetails details) {
_animationController.value +=
(details.primaryDelta ?? 0) / (maxChildOneHeight - minChildOneHeight);
}
void _handleDragEnd(DragEndDetails details) {
if (_animationController.isAnimating || _animationController.isCompleted)
return;
final flingVelocity = details.velocity.pixelsPerSecond.dy /
(maxChildOneHeight - minChildOneHeight);
if (flingVelocity < 0.0) {
_animationController.fling(velocity: math.min(-2.0, flingVelocity));
} else if (flingVelocity > 0.0) {
_animationController.fling(velocity: math.max(2.0, flingVelocity));
} else {
_animationController.fling(
velocity: _animationController.value < 0.5 ? -2.0 : 2.0);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment