Skip to content

Instantly share code, notes, and snippets.

@fabiancrx
Last active January 29, 2024 11:52
Show Gist options
  • Save fabiancrx/1be96fd05e3e23c095060f70fa6dedb7 to your computer and use it in GitHub Desktop.
Save fabiancrx/1be96fd05e3e23c095060f70fa6dedb7 to your computer and use it in GitHub Desktop.
Draggable resizable sheet
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(home: MyHomePage()));
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: FilledButton(
onPressed: () {
showDraggableResizableSheet(
keyboardDismissedSize: .54,
context: context,
builder: (_, controller) {
return ListView.separated(
controller: controller,
itemCount: 8,
itemBuilder: (context, index) => const TextField(),
separatorBuilder: (context, index) => const SizedBox.square(dimension: 16),
);
});
},
child: const Text('show modal'))),
);
}
}
/// Shows a [DraggableScrollableSheet] with [builder] as content.
/// The scrollController passed to the builder MUST be assigned to the scrollable eg: listview.
/// It automatically expands and contracts when the keyboard is shown/dismissed.
Future<void> showDraggableResizableSheet<T>(
{required BuildContext context,
required ScrollableWidgetBuilder builder,
double initialChildSize = .5,
double minChildSize = .3,
double maxChildSize = 1,
bool shrinkOnKeyboardDismissal = true,
double keyboardDismissedSize = .8}) async {
final sheetController = DraggableScrollableController();
var lastFrameKeyboardShown = false;
return showModalBottomSheet<T>(
showDragHandle: true,
isScrollControlled: true,
context: context,
builder: (_) => DraggableScrollableSheet(
initialChildSize: initialChildSize,
minChildSize: minChildSize,
maxChildSize: maxChildSize,
expand: false,
controller: sheetController,
builder: (BuildContext context, ScrollController scrollController) {
if (context.isKeyboardVisible) {
sheetController.animateTo(1, duration: const Duration(milliseconds: 150), curve: Curves.easeInOut);
lastFrameKeyboardShown = true;
} else if (shrinkOnKeyboardDismissal && !context.isKeyboardVisible && lastFrameKeyboardShown) {
sheetController.animateTo(keyboardDismissedSize,
duration: const Duration(milliseconds: 450), curve: Curves.easeInOut);
lastFrameKeyboardShown = false;
}
return Scaffold(
backgroundColor: Colors.transparent,
resizeToAvoidBottomInset: true,
body: builder(context, scrollController),
);
}),
).then((value) {
sheetController.dispose();
});
}
extension ScreenSizeX on BuildContext {
/// True If the keyboard is visible in the screen
bool get isKeyboardVisible => MediaQuery.of(this).viewInsets.bottom > 100;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment