【问题标题】:Rounded bottom on appbar应用栏上的圆底
【发布时间】:2018-05-08 20:52:09
【问题描述】:

我想制作一个圆底的应用栏,如下所示:

我将如何实现这样的应用栏? 我已尝试阅读 CustomPainter 的文档,但我觉得这不是要走的路。

【问题讨论】:

  • 我改进了我的答案,以获得像素完美的方法

标签: dart flutter


【解决方案1】:

在 Flutter 中,您可以在 AppBar 小部件中使用 shape 属性自定义形状。

  AppBar(
    title: Text('My App'),
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.vertical(
        bottom: Radius.circular(30),
      ),
    ),
  ),

【讨论】:

    【解决方案2】:

    您可以使用BoxDecoration 将边框半径和阴影添加到Container/DecoratedBox

     new Container(
        height: 200.0,
        decoration: new BoxDecoration(
          color: Colors.orange,
          boxShadow: [
            new BoxShadow(blurRadius: 40.0)
          ],
          borderRadius: new BorderRadius.vertical(
              bottom: new Radius.elliptical(
                  MediaQuery.of(context).size.width, 100.0)),
        ),
      ),
    

    虽然您可能会注意到:这不是像素完美的。边界不是一个实际的圆,而是一个省略号。这可能是不受欢迎的。

    一种更现实但更复杂的方法是根据屏幕宽度绘制一个半径为圆的圆。这将溢出容器。然后剪辑它。

    你需要一些东西:LayoutBuilder,来获得宽度。 ClipRect 不要在容器的约束之外进行绘制。和OverflowBox,布置一个比它的父级更大的圆。

    class RoundedAppBar extends StatelessWidget implements PreferredSizeWidget {
      @override
      Widget build(BuildContext context) {
        return new SizedBox.fromSize(
          size: preferredSize,
          child: new LayoutBuilder(builder: (context, constraint) {
            final width = constraint.maxWidth * 8;
            return new ClipRect(
              child: new OverflowBox(
                maxHeight: double.infinity,
                maxWidth: double.infinity,
                child: new SizedBox(
                  width: width,
                  height: width,
                  child: new Padding(
                    padding: new EdgeInsets.only(
                      bottom: width / 2 - preferredSize.height / 2),                    
                    child: new DecoratedBox(
                      decoration: new BoxDecoration(
                        color: Colors.orange,
                        shape: BoxShape.circle,
                        boxShadow: [
                          new BoxShadow(color: Colors.black54, blurRadius: 10.0)
                        ],
                      ),
                    ),
                  ),
                ),
              ),
            );
          }),
        );
      }
    
      @override
      Size get preferredSize => const Size.fromHeight(200.0);
    }
    

    以目的为中心,只是为了展示剪辑的工作原理

    【讨论】:

    • 这太好了,谢谢!我不明白的一件事是如何摆脱底部的额外边距/填充。我尝试移除填充并使宽度/高度更小。这是问题的图片:i.imgur.com/Qjrcme1.png
    • 将内部填充从 width / 2 更改为 width / 2 - preferredSize.height / 2。这是一个错误,对不起。固定的。您可能还想将高度降低到200.0\
    • 非常感谢!我还在填充中添加了模糊半径,以防止阴影被切断。
    • 有没有办法将此样式应用于所有应用栏?
    • 如何给所有的appbars添加一个简单的边框??
    【解决方案3】:

    使用 ClipPath 有一种简单的方法来实现这一点 -

    1. 为 AppBar 应用背景颜色

    2. 在正文中的 AppBar 正下方创建一个高度(例如 240)的 SizedBox/Container 并应用相同的背景颜色

    3. 使用 ClipPath 小部件包装 SizedBox/Container

         ClipPath(
         clipper: CustomShape(), // this is my own class which extendsCustomClipper
         child: Container(
         height: 150,
         color: kPrimaryColor,
         ),
       ),
      

    现在创建一个类似于 CustomShape 的类,它扩展 CustomClipper 如下所示

    class CustomShape extends CustomClipper<Path> {
      @override
      getClip(Size size) {
        double height = size.height;
        double width = size.width;
        var path = Path();
        path.lineTo(0, height - 50);
        path.quadraticBezierTo(width / 2, height, width, height - 50);
        path.lineTo(width, 0);
        path.close();
        
        return path;
     }
    
      @override
        bool shouldReclip(CustomClipper oldClipper) {
        return true;
     }
    }
    

    改变你的身高分数,我将身高保持在 50 以获得你想要的漂亮曲线

    输出如下 -

    【讨论】:

      【解决方案4】:

      您的上述对我帮助很大,我只是在努力解决一件事,那就是使圆杆的高度小很多。

      我改变了这一行的高度

       Size get preferredSize => const Size.fromHeight(200.0);
      

      但它影响不够,我什至将它设置为 0,但标准仍然很高。

      【讨论】:

      • 没关系通过将上述内容放在堆栈中解决它
      【解决方案5】:

      您可以通过以下方式获得确切的输出:

      AppBar(
          toolbarHeight:MediaQuery.of(context).size.height/4,
          leading: Container(),
          shape: RoundedRectangleBorder(
            borderRadius: new BorderRadius.vertical(
              bottom: new Radius.elliptical(SizeConfig.screenWidth, 56.0),
            ),
          ),
        ),
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-06
        • 1970-01-01
        • 2020-05-12
        • 1970-01-01
        • 2019-02-11
        相关资源
        最近更新 更多