Flutter如何设置标题显示在模态底部表单中?

7

有没有可能在这个showModalBottomSheet上设置标题和返回按钮?

我期望的是像这样的效果...

enter image description here

2个回答

19

在Flutter中,确实可以像这样做。您可以使用Column Widget,并将其第一个子项设置为标题栏或类似的内容,其中包含标题和返回箭头图标。

以下是相应的代码:

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
                              )
                            ),
                        ]
                        )
                      )
                    );
                }
              );
            }
          )
        )
      )
    );
  }
}

这是输出结果:

输入图像说明

如果你不想使用InkWell小部件,你可以像这样使用IconButton小部件:

...

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

但是如果你注意到了,标题文本实际上并没有居中显示。在这种情况下,我们可以将ListTile小部件替换为Stack小部件,并像这样操作:

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();
                        }
                    )
                )
            ]
        ),
    ]
)

...

这是输出内容:

输入图像描述

但如果我们的标题非常长,会发生什么?它肯定会看起来像这样:

输入图像描述

很丑,是吧?我们可以看到我们的文本小部件与我们的 IconButton 小部件重叠了。为了避免这种情况,我们可以用 Row 小部件替换我们的 Stack 小部件。

以下是代码:

...

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
                    )
                ),

            ]
        ),
    ]
)

输出结果将会是这样:

输入图像描述

如果标题不是很长,则会是这样:

输入图像描述


很好的回答,但我认为你的图片顺序有些不正确。也许将图片缩小一点会是个好主意(就像这里解释的那样:https://meta.stackoverflow.com/a/253405/3894304)。 - Marcel Hofgesang

2

我想我的解决方案可能有些幼稚,但对我来说完美地解决了问题。你也可以尝试一下。

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,
                    ),
                  ),
                ),
              ),
            ]),
          );}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接