如何在 Flutter 中创建带有圆角的模态底页?

Posted

技术标签:

【中文标题】如何在 Flutter 中创建带有圆角的模态底页?【英文标题】:How to create a modal bottomsheet with circular corners in Flutter? 【发布时间】:2018-10-26 19:43:48 【问题描述】:

showModalBottomSheet 不提供任何样式或装饰。我想创建类似 Google Tasks 底页的东西。

【问题讨论】:

【参考方案1】:

对于持久性底页,在材质应用小部件的主题属性中添加以下代码

ThemeData(          
          bottomSheetTheme: BottomSheetThemeData(
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(10.0),
            ),
          ),
        ),

【讨论】:

【参考方案2】:
showModalBottomSheet(
context:context
shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(
          top: Radius.circular(20),
        ),
      ),
      clipBehavior: Clip.antiAliasWithSaveLayer,
)

【讨论】:

如果您解释了您提供的代码如何回答问题,这将是一个更好的答案。 更好的答案谢谢。 这应该被接受,因为它不需要全局设置画布颜色。更简洁【参考方案3】:

您也可以在装饰容器中提供borderRadius。

 showModalBottomSheet(
                context: context,
                builder: (builder)
                  return  Container(
                        decoration: BoxDecoration(
                            color: Colors.white,
                            borderRadius: BorderRadius.only(
                                topLeft: const Radius.circular(15.0),
                                topRight: const Radius.circular(15.0))),
                        child: Center(
                          child: Text("This is a modal sheet"),
                        ),
                  );
                
            );

【讨论】:

【参考方案4】:

您可以在showModalBottomSheet 内添加RoundedRectangleBorder 小部件:

showModalBottomSheet<void>(
    shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
            topLeft: Radius.circular(10.0),
            topRight: Radius.circular(10.0)
        ),
    ),
)

【讨论】:

【参考方案5】:

我有这个代码,对我来说很好用。请检查一下,让我知道你的意见。

showBottomSheet(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.vertical(
              top: Radius.circular(20),
            ),
          ),
          context: context,
          builder: (context) => Container(
                height: 250,

                child: new Container(
                    decoration: new BoxDecoration(
                        color: Theme.of(context).primaryColor,
                        borderRadius: new BorderRadius.only(
                            topLeft: const Radius.circular(20.0),
                            topRight: const Radius.circular(20.0))),
                    child: new Center(
                      child: new Text("This is a modal sheet"),
                    )),
              ))

【讨论】:

我正在使用它,它的工作!谢谢@mohammad,你拯救了我的一天。【参考方案6】:

我认为做圆角模态的最好方法是使用RoundedRectangleBorder 和垂直BorderRadius,只设置它的top 属性:

showModalBottomSheet(
        context: context,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.vertical(top: Radius.circular(25.0)),
        ),
        builder: (BuildContext context) 
          // return your layout
        );

对左上角和右上角使用单独的半径有点冗长且容易出错。

【讨论】:

【参考方案7】:

刚刚回答了一个相关问题

您可以为您的bottomSheet添加角根据其中的内容扩展您的bottomSheet(不限于屏幕的一半大小)

查看答案here

https://***.com/a/59541927/9236994

【讨论】:

【参考方案8】:
    showModalBottomSheet(
     backgroundColor: Colors.transparent,
     context: context,
     builder: (ctx) 
      return Container( 
      decoration: BoxDecoration(
      color: Colors.green, // or some other color
      borderRadius: BorderRadius.only(
      topLeft: Radius.circular(10.0),
      topRight: Radius.circular(10.0)
       ) 
     );
    );

【讨论】:

【参考方案9】:

把之前所有的答案放在一起,我可以达到最好的结果(在我看来)。

showModalBottomSheet(
        context: context,
        backgroundColor: Colors.white,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.only(topLeft: Radius.circular(15.0), topRight: Radius.circular(15.0)),
        ),
        builder: (context) 
          return Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[     
              ListTile(
                leading: Icon(Icons.email),
                title: Text('Send email'),
                onTap: () 
                  print('Send email');
                ,
              ),
              ListTile(
                leading: Icon(Icons.phone),
                title: Text('Call phone'),
                 onTap: () 
                    print('Call phone');
                  ,
               ),                  
            ],
          );
        );

【讨论】:

【参考方案10】:

于 2019 年 8 月 5 日更新

您现在可以使用默认的showModalBottomSheet 方法来完成此操作,该方法现在支持添加ShapeBorderbackgroundColor

showModalBottomSheet(
  shape: RoundedRectangleBorder(
     borderRadius: BorderRadius.circular(10.0),
  ),
  backgroundColor: Colors.white,
  ...
);

--

我没有像其他答案所建议的那样覆盖应用程序的整个主题(这导致我的应用程序的各个部分出现问题),而是决定查看showModalBottomSheet 的实现并自己找出问题所在。事实证明,所需要的只是将模式的主要代码包装在包含 canvasColor: Colors.transparent 技巧的 Theme 小部件中。我还让自定义半径和模态本身的颜色变得更加容易。

您可以在 pub 上使用 package 或包含相同代码的 gist。不要忘记导入正确的包/文件。

showRoundedModalBottomSheet(
    context: context,
    radius: 20.0,  // This is the default
    color: Colors.white,  // Also default
    builder: (context) => ???,
);

【讨论】:

+1。对我来说,仅包装包含显示模式栏的方法的按钮是不够的。但是用这样的主题包裹包含屏幕的脚手架是有效的。 @override Widget build(BuildContext context) return Theme( // We need this theme override so that the corners of the bottom sheet modal can be rounded data: ThemeData(canvasColor: Colors.transparent), child: Scaffold( .... 这个方法比较好,谢谢大佬 完美的解决方案,谢谢! 非常感谢您的回答。它有帮助。【参考方案11】:

您现在可以简单地设置shape 参数。 示例:

showModalBottomSheet(
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.all(Radius.circular(10.0)),
  ),
  context: context,
  builder: (context) => MyBottomSheet(),
);

【讨论】:

【参考方案12】:

这是需要的modalBottomSheet函数。

    void _modalBottomSheetMenu()
        showModalBottomSheet(
            context: context,
            builder: (builder)
              return new Container(
                height: 350.0,
                color: Colors.transparent, //could change this to Color(0xFF737373), 
                           //so you don't have to change MaterialApp canvasColor
                child: new Container(
                    decoration: new BoxDecoration(
                        color: Colors.white,
                        borderRadius: new BorderRadius.only(
                            topLeft: const Radius.circular(10.0),
                            topRight: const Radius.circular(10.0))),
                    child: new Center(
                      child: new Text("This is a modal sheet"),
                    )),
              );
            
        );
      

这个正常工作的最重要部分是,在 MaterialApp 中将 canvasColor 设置为透明,如下所示。

return new MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Tasks',
      theme: new ThemeData(
        primarySwatch: Colors.teal,
        canvasColor: Colors.transparent,
      ),
      home: new TasksHomePage(),
    );
  

我已经测试了代码,它运行良好,因为我还在克隆 Google Tasks 应用程序,该应用程序将在我的github 中开源。

【讨论】:

将 global canvasColor 更改为 bottomSheet 圆角并不是一个好的折衷方案。改用 Theme 包装器。此外,如果底部工作表内的小部件取决于主题,则使用 data: yourTheme().copyWith(canvasColor: Colors.transparent) 仅将画布颜色应用于其子项。最好的选择是更新的。 感谢@sh0umik,这是一个很棒的提示! 这样做会改变所有应用程序的画布颜色,这意味着,例如,“选择/复制/粘贴”本机工具提示将具有透明的背景颜色,而不是默认的白色。我认为这应该是正确的答案:***.com/a/62457068/7691350 带有 canvasColor 的主题包装器不起作用。所以我在 MaterialApp 主题中使用了bottomSheetTheme: BottomSheetThemeData(backgroundColor: Colors.transparent)

以上是关于如何在 Flutter 中创建带有圆角的模态底页?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中创建带有底部彩色边框的 AppBar?

如何在 Flutter 中创建这种形状?

如何创建具有自定义布局的模态底页?

如何在 xml 中设置模态底页的宽度?

如何在颤动中创建以下形状?

如何在 MFC 中创建圆角矩形按钮