简体   繁体   English

Flutter中BottomSheet的height和borderRadius如何调整?

[英]How do you adjust the height and borderRadius of a BottomSheet in Flutter?

I'm probably missing something obvious here, but my BottomSheet only takes up the bottom half the screen, even though the widgets in it take up more space.我可能在这里遗漏了一些明显的东西,但我的 BottomSheet 只占据了屏幕的下半部分,即使其中的小部件占用了更多空间。 So now there is scrolling behavior inside the BottomSheet.所以现在 BottomSheet 内部有滚动行为。 I'd like to be able to increase the BottomSheet so that the user doesn't have to scroll as much.我希望能够增加 BottomSheet,以便用户不必滚动那么多。

I also want to add a borderRadius to the top of my BottomSheet, so that it looks more "modal"-y or "tab"-like.我还想在 BottomSheet 的顶部添加一个 borderRadius,这样它看起来更像“modal”-y 或“tab”。

Code:代码:

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

I've tried:我试过了:

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

but it seems like that only affects the contents inside the BottomSheet, and does not customize the BottomSheet itself.但它似乎只影响 BottomSheet 中的内容,并且不会自定义 BottomSheet 本身。

Default height for bottomSheet is half the screenSize bottomSheet默认高度是 screenSize 的一半

If you want your bottomSheet to EXPAND according to your content DYNAMICALLY如果您希望您的bottomSheet根据您的内容动态展开

use below code使用下面的代码

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

This will automatically expand the bottomSheet according to content inside.这将根据里面的内容自动扩展bottomSheet

For adding a radius on top of bottomSheet return below code to `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(),
   ),
)

Complete code meeting both requirements满足这两个要求的完整代码

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

It's possible this way这是可能的

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. Set isScrollControlled: true and backgroundColor: Colors.transparent for the modal为模式设置isScrollControlled: truebackgroundColor: Colors.transparent
  2. Provide a Container with required height: as root widget to modal builder提供具有所需height:Container height:作为模态构建器的根小部件
  3. Provide BoxDecoration with required borderRadius for the Container提供BoxDecoration与所需borderRadiusContainer

示例截图

You can use a Column Inside a SingleChildScrollView to dynamically change the height of bottom sheet and also it gets scrollable once it exceeds the available max height, make sure the isScrollControlled is set to true, And for the border radius the shape property will help you add the borderRadius to the bottomsheet.您可以使用 SingleChildScrollView 内的 Column 来动态更改底部工作表的高度,并且一旦超过可用的最大高度,它就会变得可滚动,确保isScrollControlled设置为 true,对于边框半径, shape属性将帮助您添加到底片的边界半径。 here's a dartpad example for the same这是相同的飞镖示例


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

Use showBottomSheet instead of showModalBottomSheet使用showBottomSheet而不是 showModalBottomSheet

Create global key and a listener创建全局密钥和侦听器

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

Write your method to show the sheet编写您的方法来显示工作表

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

initialize the listener初始化监听器

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

Call the method wherever you required在您需要的任何地方调用该方法

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

Hope it helps !希望它有帮助!

Lately I found an workaround for this.最近我找到了一个解决方法。 By setting the canvasColor property to Colors.transparent in your app's theme, we can make the BottomSheet's overlay disappear.通过设置canvasColor属性Colors.transparent在您的应用程序的主题,我们可以使BottomSheet的覆盖消失。

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

Once you set this up, you may use ClipRRect or Decoration with rounded corners.设置完成后,您可以使用 ClipRRect 或带圆角的装饰。

带圆角的底板

No need to wrap anything.不需要包裹任何东西。 Only set:只设置:

  • isScrollControlled: true in showModalBottomSheet isScrollControlled: trueshowModalBottomSheet isScrollControlled: true
  • shrinkWrap: true, in ListView shrinkWrap: true,ListView

Here is the minimal general code:这是最小的通用代码:

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

You can get inspired by my case which depends on the number of AlbumRow dynamically.你可以从我的案例中得到启发,这取决于AlbumRow动态数量。 If the height reaches the maximum, you can get to the bottom by scrolling.如果高度达到最大值,您可以通过滚动到达底部。

在此处输入图片说明 在此处输入图片说明


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

Use the Code Below使用下面的代码

Note : If You are using column then use mainAxisSize: MainAxisSize.min注意:如果您使用的是列,则使用mainAxisSize: MainAxisSize.min


// make isScrollControlled : true
// if using column then make - mainAxisSize: MainAxisSize.min

showModalBottomSheet<dynamic>(
isScrollControlled: true,
context: context,
builder: (BuildContext bc) {
  return YourWidget();
 }
)

In the above code by @Shyju Madathil you need to add key in scaffold to make it work在@Shyju Madathil 的上述代码中,您需要在脚手架中添加密钥以使其工作

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

here is the simplest code working in 2021这是 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
      });

You can adjust the height by setting the height of your main container either by a constant ex : 800 or by using MediaQuery ex :您可以通过常量 ex : 800 或使用 MediaQuery ex 设置主容器的高度来调整高度:

if i want to show only 2 /3 of the screen如果我只想显示屏幕的 2 /3

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

for the radius first you have to set the对于半径首先你必须设置

 showModalBottomSheet(
                          backgroundColor: Colors.transparent,

and then you container color to White or any color you wanted , example :然后将容器颜色设置为白色或您想要的任何颜色,例如:

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

You can adjust the height by setting isScrollControlled: true and wrapping the BottomSheet inside FractionallySizedBox .您可以通过设置isScrollControlled: true并将BottomSheet包裹在FractionallySizedBox来调整高度。 It would look something like this:它看起来像这样:

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

Based on Vicky's answer, Wrap could make alignments miserable.根据 Vicky 的回答, Wrap可能会使对齐变得很糟糕。 Use instead Column(mainAxisSize: MainAxisSize.min, children: [...]) in the widget.在小部件中改用Column(mainAxisSize: MainAxisSize.min, children: [...]) Implementing that in your example should look like:在您的示例中实现它应该如下所示:

void _showBottomSheet(BuildContext context) {
    showModalBottomSheet<Null>(
      context: context,
      builder: (BuildContext context) {
        return Column(
        mainAxisAxisSize: MainAxisSize.min,
        children: [
          _bottomSheetScreen
        ]); // defined earlier on
      },
    );
}

If you want to control the scrolls with swipes, then try setting isScrollControlled: true on the showModalBottomSheet() .如果您想通过滑动来控制滚动,请尝试在showModalBottomSheet()上设置isScrollControlled: true

Simple way to do this:这样做的简单方法:

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

For changing the height of bottomsheet it's better to use the bottomsheet's constraints and isScrollControlled properties.要更改底片的高度,最好使用底片的constraintsisScrollControlled属性。

Like this:像这样:

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()
);

For border radius use the shape property:对于边框半径,请使用shape属性:

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

In my case, setting the 'isScrollable' parameter to "true" makes the bottomsheet go past halfway through the screen.在我的例子中,将“isScrollable”参数设置为“true”会使底页 go 超过屏幕的一半。

This is my solution.It can adjust height and has a max height.If the content over max height.It can be scrolled这是我的解决方案。它可以调整高度并具有最大高度。如果内容超过最大高度。它可以滚动

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM