flutter
/

GetX BottomSheet: Persistent & Modal Sheets Without Context

Last Sync: Today

On this page

13
0%
5 min read
Remaining
5 minleft

Click any section to jump — progress syncs automatically

flutter

GetX BottomSheet: Persistent & Modal Sheets Without Context

What is GetX BottomSheet?

GetX provides a context‑free way to show bottom sheets – modal or persistent – anywhere in your app. Unlike Flutter's native showModalBottomSheet, you don't need a BuildContext. This makes it ideal for showing actions, forms, or additional content from controllers, services, or any Dart class. You can also await the result and control whether the user can dismiss it by tapping outside.

Basic Usage: Get.bottomSheet

DARTRead-only
1
Get.bottomSheet(
  Container(
    height: 200,
    color: Colors.white,
    child: Center(
      child: Text('This is a bottom sheet'),
    ),
  ),
);

Key Parameters

  • backgroundColor – Background color of the sheet (default is white).
  • barrierColor – Color of the overlay behind the sheet.
  • isScrollControlled – Whether the sheet can expand to full screen (default false). When true, the sheet can take any height, even beyond the safe area.
  • enableDrag – Whether the user can drag to dismiss (default true).
  • isDismissible – Whether tapping outside dismisses the sheet (default true).
  • elevation – Elevation of the sheet (default 4.0).
  • shape – Custom shape (e.g., RoundedRectangleBorder).
  • clipBehavior – How to clip the sheet (default Clip.none).
  • settings – Route settings.
  • enterBottomSheetDuration – Animation duration for entering (default 250ms).
  • exitBottomSheetDuration – Animation duration for exiting (default 250ms).
  • ignoreSafeArea – Whether to ignore safe area (default false).
  • useRootNavigator – Whether to use the root navigator (default false).

Custom Height & Scrollable Content

By default, the bottom sheet has a fixed height. To make it scrollable or full screen, use isScrollControlled: true.

DARTRead-only
1
Get.bottomSheet(
  Container(
    height: 400,
    child: SingleChildScrollView(
      child: Column(
        children: List.generate(20, (index) => ListTile(title: Text('Item $index'))),
      ),
    ),
  ),
  isScrollControlled: true,
);

Full‑Screen Bottom Sheet

Combine isScrollControlled: true with height: double.infinity to fill the screen.

DARTRead-only
1
Get.bottomSheet(
  Container(
    height: double.infinity,
    color: Colors.white,
    child: Center(child: Text('Full screen sheet')),
  ),
  isScrollControlled: true,
);

Returning Values

You can await the bottom sheet and return a value using Get.back(result: value).

DARTRead-only
1
Future<void> showSelection() async {
  final selected = await Get.bottomSheet(
    Container(
      height: 250,
      child: Column(
        children: [
          ListTile(
            title: Text('Option 1'),
            onTap: () => Get.back(result: 'Option 1'),
          ),
          ListTile(
            title: Text('Option 2'),
            onTap: () => Get.back(result: 'Option 2'),
          ),
        ],
      ),
    ),
  );

  if (selected != null) {
    Get.snackbar('Selected', selected);
  }
}

Persistent Bottom Sheets

By default, bottom sheets are modal (they block interaction with the underlying content). You can create a persistent bottom sheet that stays open while allowing interaction with the background by using isDismissible: false and enableDrag: false.

DARTRead-only
1
Get.bottomSheet(
  Container(
    height: 200,
    child: Center(child: Text('Persistent sheet')),
  ),
  isDismissible: false,
  enableDrag: false,
);

Customizing Shape & Animation

DARTRead-only
1
Get.bottomSheet(
  Container(
    height: 300,
    decoration: BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
    ),
    child: ...
  ),
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
  ),
  enterBottomSheetDuration: Duration(milliseconds: 400),
  exitBottomSheetDuration: Duration(milliseconds: 400),
);

Using with Controllers

Since Get.bottomSheet doesn't need a context, you can call it directly from a controller or service.

DARTRead-only
1
class HomeController extends GetxController {
  void showFilterSheet() {
    Get.bottomSheet(FilterSheet());
  }
}

Comparison: GetX vs Native BottomSheet

AspectGetX BottomSheetNative showModalBottomSheet
Requires BuildContextNoYes
Can be called from controllerYesNo (needs context)
Return value supportYes (Future)Yes (Future)
Persistent sheetYes (isDismissible: false)No (always modal)
Custom shapeYesYes
Animation controlYesYes

Best Practices

  • Use isScrollControlled for scrollable content – Avoid overflow issues.
  • Provide a clear close action – Include a close button or gesture, especially when isDismissible is false.
  • Return values when applicable – Let callers know what was selected.
  • Keep the sheet height appropriate – Not too tall, not too short, unless full screen is intended.
  • Test on small screens – Ensure content fits and is scrollable if needed.

Common Mistakes

  • ❌ Forgetting to handle return values – The future may be ignored; but if you need the result, await it.
  • ❌ Setting isScrollControlled without adjusting height – The sheet may not be visible if height is too small.
  • ❌ Using Get.bottomSheet without GetMaterialApp – Won't work.
  • ❌ Making the sheet non‑dismissible without a close button – Users may get stuck. ✅ Always provide a way to close.

Conclusion

GetX bottom sheets provide a simple, context‑free API for showing modal and persistent sheets. With extensive customization options and the ability to return values, they are perfect for actions, filters, forms, and more in your Flutter app.

Try it yourself

import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      home: BottomSheetDemo(),
    );
  }
}

class BottomSheetDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('GetX BottomSheet')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () {
                Get.bottomSheet(
                  Container(
                    height: 200,
                    color: Colors.white,
                    child: Center(
                      child: Text('Simple sheet'),
                    ),
                  ),
                );
              },
              child: Text('Simple BottomSheet'),
            ),
            ElevatedButton(
              onPressed: () async {
                final result = await Get.bottomSheet(
                  Container(
                    height: 250,
                    color: Colors.white,
                    child: Column(
                      children: [
                        ListTile(
                          title: Text('Option A'),
                          onTap: () => Get.back(result: 'A'),
                        ),
                        ListTile(
                          title: Text('Option B'),
                          onTap: () => Get.back(result: 'B'),
                        ),
                      ],
                    ),
                  ),
                );
                if (result != null) {
                  Get.snackbar('Selected', result);
                }
              },
              child: Text('With Return Value'),
            ),
            ElevatedButton(
              onPressed: () {
                Get.bottomSheet(
                  Container(
                    height: 400,
                    child: SingleChildScrollView(
                      child: Column(
                        children: List.generate(20, (index) => ListTile(title: Text('Item $index'))),
                      ),
                    ),
                  ),
                  isScrollControlled: true,
                );
              },
              child: Text('Scrollable Sheet'),
            ),
            ElevatedButton(
              onPressed: () {
                Get.bottomSheet(
                  Container(
                    height: 300,
                    decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
                    ),
                    child: Center(
                      child: Text('Custom shape'),
                    ),
                  ),
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
                  ),
                );
              },
              child: Text('Custom Shape'),
            ),
          ],
        ),
      ),
    );
  }
}

Test Your Knowledge

Q1
of 4

Which method is used to show a bottom sheet in GetX?

A
Get.showBottomSheet
B
Get.modalBottomSheet
C
Get.bottomSheet
D
Get.sheet
Q2
of 4

How do you make a bottom sheet full screen?

A
Set `fullscreen: true`
B
Set `isScrollControlled: true` and height to `double.infinity`
C
Set `expand: true`
D
Use `Get.fullScreenSheet()`
Q3
of 4

How do you prevent the user from dismissing a bottom sheet by tapping outside?

A
set `isDismissible: false`
B
set `dismissOnTap: false`
C
set `barrierDismissible: false`
D
set `enableDrag: false`
Q4
of 4

What is a key advantage of GetX bottom sheet over native Flutter bottom sheet?

A
Better animations
B
No BuildContext required
C
Supports more platforms
D
Automatically dismisses after timeout

Frequently Asked Questions

Can I show a bottom sheet without a `BuildContext`?

Yes! That's the primary advantage of GetX bottom sheets. You can call Get.bottomSheet from anywhere – controllers, services, or even plain Dart classes.

How do I make the sheet expand to full screen?

Set isScrollControlled: true and give the sheet height: double.infinity.

Can I have multiple bottom sheets stacked?

You can, but the new one will overlay the previous. Dismiss them in reverse order by calling Get.back() for each.

How to prevent the user from dragging to dismiss?

Set enableDrag: false.

How to make the sheet appear from the left/right?

Bottom sheets are always from the bottom. For side sheets, use Get.dialog with a custom widget that slides in from the side.

Can I show a bottom sheet from a `GetxService`?

Yes, anywhere.

How do I close a bottom sheet programmatically?

Call Get.back() from anywhere inside the sheet's widget tree.

Previous

getx dialog

Next

getx middleware

Related Content

Need help?

Explore our comprehensive docs or start a chat with our tech experts.