stuckedunderflow
stuckedunderflow

Reputation: 3767

Flutter How to set Title to Show Modal Bottom Sheet?

Is there a possibility to set title and perhaps navigation back button on this showModalBottomSheet?

I expect something like this...

enter image description here

Upvotes: 7

Views: 12888

Answers (2)

Anil Poudyal
Anil Poudyal

Reputation: 501

I guess I have naive solution but this works perfectly for me. You might as well try it.

showModalBottomSheet(
        barrierColor: Colors.transparent,
        enableDrag: true,
        shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.vertical(top: Radius.circular(20))),
        context: context,
        builder:(context){

 return Padding(
            padding: const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0),
            child: Stack(children: [
              Padding(
                padding: const EdgeInsets.only(top: 65),
                child: SingleChildScrollView(
                  child:<<Scrollable Wdgets>>,
                ),
              ),
              Card(
                elevation: 3,
                color: Colors.grey[850],
                child: ListTile(
                  leading: Text("YOUR TITLE",
                      style: TextStyle(
                          color: Colors.white,
                          fontSize: 20,
                          fontWeight: FontWeight.w500)),
                  trailing: GestureDetector(
                    onTap: () {
                      Navigator.pop(context);
                    },
                    child: Icon(
                      Icons.close,
                      color: Colors.white,
                      size: 20,
                    ),
                  ),
                ),
              ),
            ]),
          );}

Upvotes: 2

Jerome Escalante
Jerome Escalante

Reputation: 4387

Yes it's possible to do something like that in Flutter. You can use Column Widget and make its first child as a title bar or something like that with title and back arrow icon.

Here's the code for that:

import 'dart:async';

import 'package:flutter/material.dart';



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

class MyApp extends StatelessWidget {

   @override
   Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        canvasColor: Colors.transparent,
        ),
      home: MyHomePage(),
    );
  } 
}

class MyHomePage extends StatefulWidget{

  @override
  HomePageS createState()=> HomePageS();
}

class HomePageS extends State<MyHomePage>{

  @override
  Widget build(BuildContext context){

    return Scaffold(
      body: Container(
        color: Colors.white,
        child: Center(
          child: FlatButton(
            child: Text("Show BottomSheet"),
            onPressed: () async{
              showModalBottomSheet(
                context: context,
                builder: (BuildContext context){
                  return ClipRRect(
                    borderRadius: BorderRadius.only(topLeft: Radius.circular(20.0), topRight: Radius.circular(20.0)),
                    child: Container(
                      color: Colors.white,
                      child: Column(
                        children: [
                          ListTile(
                            leading: Material( 
                              color: Colors.transparent,
                              child: InkWell(
                                onTap: (){
                                  Navigator.of(context).pop();
                                },
                                child: Icon(Icons.arrow_back) // the arrow back icon
                                ),
                              ),                          
                            title: Center(
                              child: Text("My Title") // Your desired title
                              )
                            ),
                        ]
                        )
                      )
                    );
                }
              );
            }
          )
        )
      )
    );
  }
}

Here is the output:

enter image description here

If you don't wanna use the InkWell widget, you can use the IconButton widget like this:

...

ListTile(
    leading: IconButton(
        icon: Icon(Icons.arrow_back),
        onPressed: (){
            Navigator.of(context).pop();
        }                  
    ),                      
    title: Center(
        child: Text("My Title")
        )
    ),
...

But if you noticed, the title text is not really centered. In this case, we can replace the ListTile widget to a Stack widget and do something like this:

child: Column(
    children: [
        Stack(
            children: [
                Container(
                    width: double.infinity,
                    height: 56.0,
                    child: Center(
                        child: Text("My Title") // Your desired title
                        ),
                    ),

                Positioned(
                    left: 0.0,
                    top: 0.0,
                    child: IconButton(
                        icon: Icon(Icons.arrow_back), // Your desired icon
                        onPressed: (){
                            Navigator.of(context).pop();
                        }
                    )
                )
            ]
        ),
    ]
)

...

This is the output:

enter image description here

But what would happen if we have a very long text for our title? It would definitely look like this:

enter image description here

Ugly, right? We can see that our Text widget overlaps with our IconButton widget. To avoid this, we can replace our Stack widget with a Row widget.

Here's the code for that:

...

child: Column(
    children: [
        Row( // A Row widget
            mainAxisAlignment: MainAxisAlignment.spaceBetween, // Free space will be equally divided and will be placed between the children.
            children: [

                IconButton( // A normal IconButton
                    icon: Icon(Icons.arrow_back),
                    onPressed: (){
                        Navigator.of(context).pop();
                    }
                ),

                Flexible( // A Flexible widget that will make its child flexible
                    child: Text(
                        "My Title is very very very very very very very long", // A very long text
                        overflow: TextOverflow.ellipsis, // handles overflowing of text
                    ),
                ),


                Opacity( // A Opacity widget
                    opacity: 0.0, // setting opacity to zero will make its child invisible
                    child: IconButton(
                        icon: Icon(Icons.clear), // some random icon
                        onPressed: null, // making the IconButton disabled
                    )
                ),

            ]
        ),
    ]
)

Output would be like this:

enter image description here

And this (if the title is not long):

enter image description here

Upvotes: 19

Related Questions