Skip to content

Instantly share code, notes, and snippets.

@caseycrogers
Last active October 28, 2021 20:17
Show Gist options
  • Save caseycrogers/c972511cb8a9d0d29b594dc4bb3c1b35 to your computer and use it in GitHub Desktop.
Save caseycrogers/c972511cb8a9d0d29b594dc4bb3c1b35 to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
void main() => runApp(const MaterialApp(home: _DraggableSheetTest()));
class _DraggableSheetTest extends StatefulWidget {
const _DraggableSheetTest({Key? key}) : super(key: key);
@override
_DraggableSheetTestState createState() => _DraggableSheetTestState();
}
class _DraggableSheetTestState extends State<_DraggableSheetTest> {
final TextEditingController _minSizeController =
TextEditingController(text: '.25');
final TextEditingController _snapSizesController =
TextEditingController(text: '.5, .75');
final TextEditingController _maxSizeController =
TextEditingController(text: '1');
final TextEditingController _initialSizeController =
TextEditingController(text: '.6');
final TextEditingController _animationDurationController =
TextEditingController(text: '0');
final FocusNode _node = FocusNode();
final DraggableScrollableController _sheetController =
DraggableScrollableController();
bool _snapSizesIsValid = true;
bool _minIsValid = true;
bool _maxIsValid = true;
bool _initialIsValid = true;
bool _snap = true;
double _initialChildSize = .6;
List<double> _snapSizes = [.25, .5, .75, 1];
int _jumpToSpeed = 0;
bool _speedIsValid = true;
final List<double> _goToSizes = [.4, .5, .6, .9];
@override
void dispose() {
_node.dispose();
super.dispose();
}
Color _getColor(int index) {
if (index == _snapSizes.length - 1) {
return Colors.black;
}
return index % 2 == 0 ? Colors.lightBlue : Colors.white;
}
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Stack(
children: [
Column(
children: _snapSizes
.asMap()
.keys
.map((index) {
double nextSnapSize =
index == _snapSizes.length - 1 ? 1 : _snapSizes[index + 1];
return Container(
color: _getColor(index),
height: size.height * (nextSnapSize - _snapSizes[index]),
);
})
.toList()
.reversed
.toList(),
),
Positioned(
child: Container(color: Colors.red),
height: 1,
bottom: (size.height * _initialChildSize).ceil().toDouble(),
width: size.width,
),
DraggableScrollableSheet(
controller: _sheetController,
snap: _snap,
minChildSize: _snapSizes.first,
maxChildSize: _snapSizes.last,
initialChildSize: _initialChildSize,
snapSizes: _snapSizes,
builder: (context, controller) {
return Material(
color: Colors.grey.withOpacity(.9),
child: ListView(
controller: controller,
children: List.generate(100, (index) => Text(index.toString())),
),
);
},
),
Positioned(
bottom: MediaQuery.of(context).viewInsets.bottom,
width: MediaQuery.of(context).size.width,
child: Material(
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
const Text(' Go to:'),
..._goToSizes.map((size) {
return TextButton(
onPressed: () {
if (_jumpToSpeed == 0) {
_sheetController.jumpTo(size);
} else {
_sheetController.animateTo(
size,
duration: Duration(milliseconds: _jumpToSpeed),
curve: Curves.linear,
);
}
},
child: Text(size.toString()),
);
}),
const Text('ms: '),
Expanded(
child: TextField(
controller: _animationDurationController,
decoration: InputDecoration(
errorText: _speedIsValid ? null : '',
),
onChanged: (newString) {
final int? newSpeed = int.tryParse(newString);
if (newSpeed != null) {
_jumpToSpeed = newSpeed;
_speedIsValid = true;
return;
}
_speedIsValid = false;
},
),
),
],
),
Row(
children: [
const Text(' Snap:'),
Switch(
value: _snap,
onChanged: (_) => setState(() {
_snap = !_snap;
}),
),
const Text(' Snap Sizes:'),
Flexible(
flex: 3,
child: TextField(
controller: _snapSizesController,
decoration: InputDecoration(
errorText: _snapSizesIsValid ? null : '',
),
onChanged: (newString) {
if (newString
.replaceAll(' ', '')
.split(',')
.every((v) => double.tryParse(v) != null)) {
_snapSizes = [
_snapSizes.first,
...newString
.replaceAll(' ', '')
.split(',')
.map((v) => double.parse(v)),
_snapSizes.last,
];
_snapSizesIsValid = true;
return;
}
_snapSizesIsValid = false;
},
),
),
],
),
Row(
children: [
const Text(' minSize:'),
Flexible(
flex: 1,
child: TextField(
controller: _minSizeController,
decoration: InputDecoration(
errorText: _minIsValid ? null : '',
),
onChanged: (newString) {
if (double.tryParse(newString) != null) {
_snapSizes.first = double.parse(newString);
_minIsValid = true;
return;
}
_minIsValid = false;
},
),
),
const Text(' maxSize:'),
Flexible(
flex: 1,
child: TextField(
controller: _maxSizeController,
decoration: InputDecoration(
errorText: _maxIsValid ? null : '',
),
onChanged: (newString) {
if (double.tryParse(newString) != null) {
_snapSizes.last = double.parse(newString);
_maxIsValid = true;
return;
}
_maxIsValid = false;
},
),
),
const Text(' initialSize:'),
Flexible(
flex: 1,
child: TextField(
controller: _initialSizeController,
decoration: InputDecoration(
errorText: _initialIsValid ? null : '',
),
onChanged: (newString) {
if (double.tryParse(newString) != null) {
_initialChildSize = double.parse(newString);
_initialIsValid = true;
return;
}
_initialIsValid = false;
},
),
),
IconButton(
icon: const Icon(Icons.refresh),
onPressed: () {
FocusScope.of(context).requestFocus(_node);
_sheetController.reset();
},
),
IconButton(
icon: const Icon(Icons.check),
onPressed: () {
FocusScope.of(context).requestFocus(_node);
setState(() {});
},
),
],
),
],
),
),
),
],
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment