Skip to content

Instantly share code, notes, and snippets.

@slightfoot
Last active March 8, 2022 14:06
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save slightfoot/f935e22b313e9f87d744fc17f74c02c7 to your computer and use it in GitHub Desktop.
Save slightfoot/f935e22b313e9f87d744fc17f74c02c7 to your computer and use it in GitHub Desktop.
Split Bar in Flutter. Lets you touch between two horizontal sections to resize the split point.
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
void main() {
runApp(
MaterialApp(
theme: ThemeData(
primaryColor: Colors.indigo,
accentColor: Colors.pinkAccent,
),
home: ExampleScreen(),
),
);
}
class ExampleScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Split Bar'),
),
body: SplitBar(
onWeightChanged: (weight) => print('weight: $weight'),
left: Container(
color: Colors.red,
child: Placeholder(),
),
right: PageView(
children: <Widget>[
Container(
color: Colors.blue,
child: Placeholder(),
),
Container(
color: Colors.green,
child: Placeholder(),
),
Container(
color: Colors.yellow,
child: Placeholder(),
),
],
),
),
);
}
}
class SplitBar extends StatefulWidget {
const SplitBar({
Key key,
this.left,
this.right,
this.touchOverlap = 16.0,
this.initialWeight = 0.333,
this.onWeightChanged,
}) : super(key: key);
final Widget left;
final Widget right;
final double touchOverlap;
final double initialWeight;
final ValueChanged<double> onWeightChanged;
@override
_SplitBarState createState() => _SplitBarState();
}
class _SplitBarState extends State<SplitBar> {
double _weight;
@override
void initState() {
super.initState();
_weight = widget.initialWeight;
}
void _handleDragUpdate(DragUpdateDetails d) {
final RenderBox container = context.findRenderObject();
final pos = container.globalToLocal(d.globalPosition);
setState(() => _weight = pos.dx / container.size.width);
widget.onWeightChanged?.call(_weight);
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
final double left = constraints.maxWidth * _weight;
final double right = constraints.maxWidth * (1.0 - _weight);
return Stack(
children: <Widget>[
Positioned(
top: 0.0,
left: 0.0,
right: right,
bottom: 0.0,
child: Offstage(
offstage: left.round() == 0,
child: widget.left,
),
),
Positioned(
top: 0.0,
left: left,
right: 0.0,
bottom: 0.0,
child: Offstage(
offstage: right.round() == 0,
child: widget.right,
),
),
Positioned(
left: left - widget.touchOverlap,
right: right - widget.touchOverlap,
top: 0.0,
bottom: 0.0,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onHorizontalDragUpdate: _handleDragUpdate,
),
),
],
);
},
);
}
}
@lvscar
Copy link

lvscar commented Feb 17, 2020

Thx , the demo is really helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment