【问题标题】:How do you adjust the height and borderRadius of a BottomSheet in Flutter?Flutter中如何调整BottomSheet的高度和边框半径?
【发布时间】:2018-08-04 17:01:45
【问题描述】:

我可能在这里遗漏了一些明显的东西,但我的 BottomSheet 只占用了屏幕的下半部分,尽管其中的小部件占用了更多空间。所以现在在 BottomSheet 中有滚动行为。我希望能够增加 BottomSheet,以便用户不必滚动太多。

我还想在我的 BottomSheet 顶部添加一个边框半径,使其看起来更像“模态”-y 或“制表符”。

代码:

void _showBottomSheet(BuildContext context) {
    showModalBottomSheet<Null>(
      context: context,
      builder: (BuildContext context) {
        return _bottomSheetScreen; // defined earlier on
      },
    );
}

我试过了:

showModalBottomSheet<Null>(
  context: context,
  builder: (BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        borderRadius: _borderRadius,
      ),
      height: 1000.0,
      child: _bottomSheetScreen,
    );
  },
);

但是好像只影响BottomSheet里面的内容,并没有自定义BottomSheet本身。

【问题讨论】:

  • 目前不可能。如果您想要自定义的东西,请使用 Navigator 推送自定义模式。在 github 中也有一个关于扩展底部工作表的类似问题:github.com/flutter/flutter/issues/497
  • 很高兴知道,我会提出这个问题。感谢您提供有关在 Navigator 中使用自定义模式的建议,我没想到!

标签: material-design flutter bottom-sheet


【解决方案1】:

bottomSheet 的默认高度是 screenSize 的一半

如果您希望 bottomSheet 根据您的内容动态扩展

使用下面的代码

showModalBottomSheet<dynamic>(
isScrollControlled: true,
context: context,
builder: (BuildContext bc) {
  return Wrap(
      children: <Widget>[...]
  )
 }
)

这会根据里面的内容自动展开bottomSheet

对于bottomSheet顶部添加半径将下面的代码返回到`bottomSheet'

Container(
  child: Container(
    decoration: new BoxDecoration(
      color: forDialog ? Color(0xFF737373) : Colors.white,
      borderRadius: new BorderRadius.only(
            topLeft: const Radius.circular(25.0),
            topRight: const Radius.circular(25.0))),
      child: yourWidget(),
   ),
)

满足这两个要求的完整代码

showModalBottomSheet<dynamic>(
isScrollControlled: true,
context: context,
builder: (BuildContext bc) {
  return Wrap(
      children: <Widget>[
          Container(
                 child: Container(
                  decoration: new BoxDecoration(
                    color: forDialog ? Color(0xFF737373) : Colors.white,
                    borderRadius: new BorderRadius.only(
                          topLeft: const Radius.circular(25.0),
                          topRight: const Radius.circular(25.0))),
                    child: yourWidget(),
                 ),
              )
      ]
   )
 }
)

【讨论】:

  • 如果Wrap中有ListView,就不能滚动。如果我把Wrap换成Column,就会溢出。为什么?
  • @parcool 尝试使用SingleChildScrollView 小部件而不是ListView 小部件,这可能对您的查询有所帮助。
  • @parcool 实际上,您只需将ListView 包裹在Expanded 周围,因为如果ListViewColumn 的直接子代,Flutter 将无法推断其大小,因为ListView 的大小也取决于其子级。
  • 要在顶部添加半径,我更喜欢将其添加到模态的 shape 属性中。形状: RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(12))),
  • @RaviParmar 我很确定当您将ListView.shrinkWrap 设置为true 或在Expanded 内(后者取决于父母和兄弟姐妹)时,它确实允许它几乎放在任何地方。无论如何,我只是在@parcool 提到的内容中提到了这一点,这绝不是对这个答案的建议。
【解决方案2】:

可以这样

showModalBottomSheet(
  context: context,
  isScrollControlled: true,
  backgroundColor: Colors.transparent,
  builder: (context) => Container(
    height: MediaQuery.of(context).size.height * 0.75,
    decoration: new BoxDecoration(
      color: Colors.white,
      borderRadius: new BorderRadius.only(
        topLeft: const Radius.circular(25.0),
        topRight: const Radius.circular(25.0),
      ),
    ),
    child: Center(
      child: Text("Modal content goes here"),
    ),
  ),
);
  1. 为模态设置isScrollControlled: truebackgroundColor: Colors.transparent
  2. 提供Container 和所需的height: 作为模式构建器的根小部件
  3. Container 提供BoxDecoration 所需的borderRadius

【讨论】:

  • 希望我能投票两次,非常感谢
  • 哇,这看起来太棒了!如此简单而有效
【解决方案3】:

您可以使用 SingleChildScrollView 内的 Column 来动态更改底部工作表的高度,并且一旦超过可用的最大高度,它就会变得可滚动,请确保将 isScrollControlled 设置为 true, 对于边框半径,shape 属性将帮助您将边框半径添加到底页。 这是一个dartpad example 相同的


  Future<void> _showBottomSheet() async {
    return showModalBottomSheet(
      isScrollControlled: true,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(13)),
      backgroundColor: Colors.white,
      context: context,
      builder: (context) => SingleChildScrollView(
          child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: List.generate(kBoxes, (index) => _squareBox(index)))),
    );
  }

【讨论】:

    【解决方案4】:

    无需包装任何东西。仅设置:

    • isScrollControlled: trueshowModalBottomSheet
    • shrinkWrap: true,ListView

    这是最小的通用代码:

    import 'package:flutter/material.dart';
    
    Future<Widget> show123(BuildContext context) {
      return showModalBottomSheet<dynamic>(
          useRootNavigator: true,
          isScrollControlled: true,
          context: context,
          builder: (BuildContext bc) {
            return ListView(
              shrinkWrap: true,
              children: [
                ListItem(),
                ListItem(),
                ListItem(),
              ],
            );
          });
    }
    
    

    您可以从我的案例中获得启发,这取决于AlbumRow 的数量是动态的。如果高度达到最大值,可以滚动到底部。

    
    import 'package:flutter/material.dart';
    
    Future<Widget> showBottomSheet(BuildContext context) {
      return showModalBottomSheet<dynamic>(
          useRootNavigator: true,
          barrierColor: Colors.black.withOpacity(0.5),
          isScrollControlled: true,
          context: context,
          builder: (BuildContext bc) {
            return ConstrainedBox(
              constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.9),
              child: Container(
                decoration: new BoxDecoration(
                    color: Colors.blue, borderRadius: new BorderRadius.only(topLeft: const Radius.circular(25.0), topRight: const Radius.circular(25.0))),
                child: ListView(
                  shrinkWrap: true,
                  children: [
                    Padding(
                      padding: const EdgeInsets.fromLTRB(30, 30, 30, 45),
                      child: Text(
                        'Choose Album',
                        textAlign: TextAlign.center,
                      ),
                    ),
                    AlbumRow(title: 'For Weekends arta iretnairstnaisetn aistn aisetn'),
                    AlbumRow(title: 'Creative'),
                    AlbumRow(title: 'Christmas'),
                    AlbumRow(title: 'For Weekends arta iretnairstnaisetn aistn aisetn'),
                  ],
                ),
              ),
            );
          });
    }
    

    【讨论】:

    • 当应用您的解决方案时,当底部工作表超过指定的约束高度时,拖动以关闭底部工作表不起作用
    【解决方案5】:

    使用 showBottomSheet 代替 showModalBottomSheet

    创建全局键和监听器

    final _scaffoldKey = new GlobalKey<ScaffoldState>();
    VoidCallback _showPersBottomSheetCallBack;
    

    写下你的方法来显示工作表

      void _showBottomSheet() {
        setState(() {
          _showPersBottomSheetCallBack = null;
        });
    
        _scaffoldKey.currentState
            .showBottomSheet((context) {
          return new Container(
            height: MediaQuery.of(context).size.height-100.0,
            color: Colors.greenAccent,
            child: new Center(
              child: new Text("Hi BottomSheet"),
            ),
          );
        })
            .closed
            .whenComplete(() {
          if (mounted) {
            setState(() {
              _showPersBottomSheetCallBack = _showBottomSheet;
            });
          }
        });
      }
    

    初始化监听器

    void initState() {
        super.initState();
        _showPersBottomSheetCallBack = _showBottomSheet;
      }
    

    在需要的地方调用方法

    new RaisedButton(
                      onPressed: _showPersBottomSheetCallBack,
                      child: new Text("Persistent"),
                    ),
    

    希望对你有帮助!

    【讨论】:

      【解决方案6】:

      最近我找到了解决方法。通过在您的应用主题中将canvasColor 属性设置为Colors.transparent,我们可以使BottomSheet 的覆盖消失。

      return new MaterialApp(
        title: 'MyApp',
        theme: new ThemeData(
          primarySwatch: Colors.blue,
          canvasColor: Colors.transparent,
        ),
        //...
      );
      

      设置完成后,您可以使用 ClipRRect 或圆角装饰。

      【讨论】:

      • 这将使所有屏幕背景变为黑色
      • 它使所有材质元素的背景透明。因此,您已经为材质组件设置了自定义颜色。
      【解决方案7】:

      使用下面的代码

      注意:如果您使用的是列,则使用 ma​​inAxisSize: MainAxisSize.min

      
      // make isScrollControlled : true
      // if using column then make - mainAxisSize: MainAxisSize.min
      
      showModalBottomSheet<dynamic>(
      isScrollControlled: true,
      context: context,
      builder: (BuildContext bc) {
        return YourWidget();
       }
      )
      

      【讨论】:

        【解决方案8】:

        在@Shyju Madathil 的上述代码中,您需要在脚手架中添加密钥才能使其工作

        return new Scaffold(
          key: _scaffoldKey,
          ....
        

        【讨论】:

          【解决方案9】:

          这是 2021 年最简单的代码

           showModalBottomSheet(
                context: context,
                isScrollControlled: true,  // <-- make bottom sheet resize to content height
                shape: RoundedRectangleBorder(  // <-- for border radius
                  borderRadius: BorderRadius.only(
                    topLeft: Radius.circular(15.0),
                    topRight: Radius.circular(15.0),
                  ),
                ),
                builder: (BuildContext context) {
                 return Container() // <-- any widget you want
                });
          

          【讨论】:

            【解决方案10】:

            要更改底页的高度,最好使用底页的constraintsisScrollControlled 属性。

            像这样:

            showModalBottomSheet(
              constraints: BoxConstraints.loose(Size(
                        MediaQuery.of(context).size.width,
                        MediaQuery.of(context).size.height * 0.75)), // <= this is set to 3/4 of screen size.
              isScrollControlled: true, // <= set to true. setting this without constrains may cause full screen bottomsheet.
              context: context,
              builder: (context) => yourWidget()
            );
            

            对于边框半径,请使用shape 属性:

            showModalBottomSheet(
              shape: const RoundedRectangleBorder(
                  borderRadius: BorderRadius.vertical(top: Radius.circular(45))), // <= set preferable radius.
              context: context,
              builder: (context) => yourWidget()
            );
            

            【讨论】:

              【解决方案11】:

              您可以通过设置主容器的高度来调整高度,或者通过常量 ex:800 或使用 MediaQuery ex:

              如果我只想显示 2 /3 的屏幕

              MediaQuery.of(context).size.height -
                    (MediaQuery.of(context).size.height / 3)
              

              首先你必须设置半径

               showModalBottomSheet(
                                        backgroundColor: Colors.transparent,
              

              然后你将容器颜色设置为白色或任何你想要的颜色,例如:

              return Container(
                decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.only(
                        topLeft: const Radius.circular(16),
                        topRight: const Radius.circular(16))),
                child:
              

              【讨论】:

                【解决方案12】:

                您可以通过设置isScrollControlled: true 并将BottomSheet 包裹在FractionallySizedBox 中来调整高度。它看起来像这样:

                 showModalBottomSheet<void>(
                    context: context,
                    //This
                    isScrollControlled: true,
                    builder: (BuildContext context) {
                      return StatefulBuilder(
                          builder: (BuildContext context, StateSetter state) {
                        return FractionallySizedBox(
                            //Here specify the high of the BottomSheet
                            heightFactor: 0.9,
                            child:BottomSheet(
                            .
                            .
                            .
                            
                            .
                            .
                            .
                      ));
                      });
                    });
                

                【讨论】:

                  【解决方案13】:

                  简单的方法:

                  showModalBottomSheet(
                                        shape: RoundedRectangleBorder(
                                          borderRadius: BorderRadius.only(
                                            topRight: Radius.circular(15),
                                            topLeft: Radius.circular(15),
                                          ),
                                        ),
                                        context: context,
                                        builder: (context) {
                                          return Wrap(
                                            children: [
                                              Container(
                                                height: 40,
                                                child: Center(
                                                  child: Text(
                                                    "Edit Profile",
                                                    style: TextStyle(
                                                      fontWeight: FontWeight.bold,
                                                    ),
                                                  ),`
                                                ),
                                              ),                           
                                            ],
                                          );
                                        });
                  

                  【讨论】:

                    【解决方案14】:

                    这是我的解决方案。它可以调整高度并具有最大高度。如果内容超过最大高度。它可以滚动

                     showModalBottomSheet<void>(
                        context: context,
                        isScrollControlled: true,
                        backgroundColor: Colors.white,
                        // elevation: 10,
                        shape: const RoundedRectangleBorder(
                            borderRadius: BorderRadius.only(
                          topLeft: Radius.circular(12),
                          topRight: Radius.circular(12),
                        )),
                        builder: (context) {
                          return ConstrainedBox(
                            constraints: const BoxConstraints(maxHeight: 300),
                            child: SingleChildScrollView(
                                scrollDirection: Axis.vertical,
                                child: Column(
                                  children: List.generate(20, (index) => Text("data$index")),
                                )),
                          );
                        },
                      );
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2021-01-20
                      • 2022-01-17
                      • 1970-01-01
                      • 1970-01-01
                      • 2011-03-09
                      • 1970-01-01
                      • 2019-12-23
                      • 2020-06-12
                      相关资源
                      最近更新 更多