How to set Bottom Sheet position to top
Asked Answered
S

3

16

I want to create a expandable container that have multiple controls like textentry and buttons.

So I have implemented a bottom sheet but I want to set this position on top.

Code:

Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: RaisedButton(
            child: Text('Show Buttom Sheet'),
            onPressed: () {
              showModalBottomSheet(context: context, builder: (context){
                return StreamBuilder(
                  stream: controller.stream,
                  builder:(context,snapshot) => GestureDetector(
                      onVerticalDragUpdate: (DragUpdateDetails details)
{
                        position = MediaQuery.of(context).size.height- 
                      details.globalPosition.dy;
                        print('position dy = ${position}');

                        position.isNegative?Navigator.pop(context)

                            :controller.add(position);

                      },
                      behavior: HitTestBehavior.translucent,
                      child:
                      Container(
                        color: Colors.red,
                        height: snapshot.hasData ? snapshot.data:200.0,
                        width: double.infinity,
                        child: Text('Child'),
                      )),
                );

              });

            }),
      ),
    );
  }
Staves answered 4/6, 2019 at 9:15 Comment(1)
A Simple Top Modal Sheet for Flutter: morioh.com/p/0f80b5c68d71Serin
V
23

Looking at the Material Design reference for Bottom Sheets it does suggest that the usage be ergonomic, meaning it should be at the bottom because it's easier to reach with your thumb (when using a phone). There don't seem to be other examples of "Top Sheets", implying there are better ways of handling a click of a button that's located at the top of the screen. For example in Gmail, clicking your avatar produces a Card that's positioned a little below the button.

Having said that, here is one way to create a "Top Sheet":

IconButton(
  icon: Icon(Icons.star),
  onPressed: () {
    return showGeneralDialog(
      context: context,
      barrierDismissible: true,
      transitionDuration: Duration(milliseconds: 500),
      barrierLabel: MaterialLocalizations.of(context).dialogLabel,
      barrierColor: Colors.black.withOpacity(0.5),
      pageBuilder: (context, _, __) {
        return Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Container(
              width: MediaQuery.of(context).size.width,
              color: Colors.white,
              child: Card(
                child: ListView(
                  shrinkWrap: true,
                  children: <Widget>[
                    ListTile(
                      title: Text('Item 1'),
                      onTap: () => Navigator.of(context).pop('item1'),
                    ),
                    ListTile(
                      title: Text('Item 2'),
                      onTap: () => Navigator.of(context).pop('item2'),
                    ),
                    ListTile(
                      title: Text('Item 3'),
                      onTap: () => Navigator.of(context).pop('item3'),
                    ),
                  ],
                ),
              ),
            ),
          ],
        );
      },
      transitionBuilder: (context, animation, secondaryAnimation, child) {
        return SlideTransition(
          position: CurvedAnimation(
            parent: animation,
            curve: Curves.easeOut,
          ).drive(Tween<Offset>(
            begin: Offset(0, -1.0),
            end: Offset.zero,
          )),
          child: child,
        );
      },
    );
  }
);
Vaporization answered 5/11, 2019 at 9:48 Comment(1)
Do you know any way to make this Dismissible & Draggable ? (Dragging bottom to top to hide)Chavaree
P
1

I think the widget you want is a BackDrop.

Example here

And from the Actual Flutter Gallery they also use it in the options

Plait answered 4/6, 2019 at 9:25 Comment(1)
Actually I have a button on app bar name is filter, After click on filter button a overlay half screen open which have multiple Entry Text and button and after button click the overlay screen will dismiss. this overlay screen will come from top and back to top after dismiss like slide.Staves
C
1

After remove return of Icon Button it will work.

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

Future<void> main() async {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Center(
            child: Padding(
              padding: const EdgeInsets.only(top: 50),
              child: IconButton(
                  icon: const Icon(Icons.star),
                  onPressed: () {
                    showGeneralDialog(
                      context: context,
                      barrierDismissible: true,
                      transitionDuration: Duration(milliseconds: 500),
                      barrierLabel:
                          MaterialLocalizations.of(context).dialogLabel,
                      barrierColor: Colors.black.withOpacity(0.5),
                      pageBuilder: (context, _, __) {
                        return Column(
                          mainAxisAlignment: MainAxisAlignment.start,
                          children: <Widget>[
                            Container(
                              width: MediaQuery.of(context).size.width,
                              color: Colors.white,
                              child: Card(
                                child: ListView(
                                  shrinkWrap: true,
                                  children: <Widget>[
                                    ListTile(
                                      title: Text('Item 1'),
                                      onTap: () =>
                                          Navigator.of(context).pop('item1'),
                                    ),
                                    ListTile(
                                      title: Text('Item 2'),
                                      onTap: () =>
                                          Navigator.of(context).pop('item2'),
                                    ),
                                    ListTile(
                                      title: Text('Item 3'),
                                      onTap: () =>
                                          Navigator.of(context).pop('item3'),
                                    ),
                                  ],
                                ),
                              ),
                            ),
                          ],
                        );
                      },
                      transitionBuilder:
                          (context, animation, secondaryAnimation, child) {
                        return SlideTransition(
                          position: CurvedAnimation(
                            parent: animation,
                            curve: Curves.easeOut,
                          ).drive(Tween<Offset>(
                            begin: Offset(0, -1.0),
                            end: Offset.zero,
                          )),
                          child: child,
                        );
                      },
                    );
                  }),
            ),
          ),
        ],
      ),
    );
  }
}
Christiniachristis answered 31/10, 2023 at 10:58 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.