【问题标题】:Flutter - How to make the custom rounded shape of card in flutter?Flutter - 如何在颤动中制作自定义圆形卡片?
【发布时间】:2020-08-22 20:14:01
【问题描述】:

我想制作一张如下图所示的圆形卡片

我为它做了很多尝试,但我无法让它像设计一样的形状。

【问题讨论】:

  • 你需要一个自定义的ShapeBorder 类,与Card.shape 属性一起使用
  • 你能帮我写代码吗?
  • @MrinalJain 我已经回答了一个完整的 ShapeBorder 示例,希望对您有所帮助。
  • @camillo777 感谢您的回答,我会尝试使用它并让您知道它是怎么回事。

标签: flutter flutter-layout


【解决方案1】:

我用 ShapeBorder 制作了一个示例,您可以复制它(粘贴到 dartPad 并使用。 用图片替换图标。

PS。我添加了一个 LayoutBuilder 以使其对响应式布局更加健壮。

这是结果,希望对你有帮助:

import "package:flutter/material.dart";
import "dart:math";

void main() {
  runApp(MaterialApp(
      debugShowCheckedModeBanner: false, home: Scaffold(body: HomeScreen())));
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
        width: 300,
        height: 800,
        child: Column(children: <Widget>[
          MyCustomCard(),
          MyCustomCard(),
        ]));
  }
}

class MyCustomCard extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (_, BoxConstraints bc) {
      return Container(
        padding: EdgeInsets.all(10),
        color: Colors.black,
        child: Stack(children: <Widget>[
          Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                SizedBox(
                  height: 80,
                ),
                Container(
                    width: double.infinity,
                    //height: 400,
                    decoration: ShapeDecoration(
                      gradient: LinearGradient(
                        begin: Alignment.topCenter,
                        end: Alignment.bottomCenter,
                        colors: [Color(0xff3344ff), Color(0x883344ff)],
                        stops: [0, 1],
                      ),
                      shape: CustomCardShape(
                          //kW:MediaQuery.of(context).size.width-40,
                          ),
                    ),
                    child: Padding(
                      padding: EdgeInsets.all(20),
                      child: Column(
                          mainAxisAlignment: MainAxisAlignment.start,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: <Widget>[
                            SizedBox(height: 20),
                            Text(
                              "Steve Jobs",
                              style: TextStyle(
                                color: Colors.white,
                                fontSize: 14,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                            Text(
                              "Seattle",
                              style:
                                  TextStyle(color: Colors.white, fontSize: 18),
                            ),
                            SizedBox(height: 20),
                            Text(
                              "hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello hello ",
                              style:
                                  TextStyle(color: Colors.white, fontSize: 14),
                            ),
                          ]),
                    )),
              ]),
          Positioned(
            top: 20,
            //left: (MediaQuery.of(context).size.width/2)-60, //100,
            left: bc.constrainWidth() / 2 - 50,
            child: Container(
              alignment: Alignment.center,
              width: 80,
              decoration: BoxDecoration(
                color: Colors.black,
                shape: BoxShape.circle,
              ),
              child: Icon(Icons.home, color: Colors.white, size: 80),
            ),
          ),
        ]), // stack
      );
    });
  }
}

class CustomCardShape extends ShapeBorder {
  //final double kH = 350; // card height
  //final double kW; // = 260; // card width

  final double circleW = 100;

  CustomCardShape(); //{this.kW});

  @override
  EdgeInsetsGeometry get dimensions => EdgeInsets.all(0);

  @override
  Path getInnerPath(Rect rect, {TextDirection textDirection}) => null;

  @override
  Path getOuterPath(Rect rect, {TextDirection textDirection}) {
    rect = Rect.fromPoints(rect.topLeft, rect.bottomRight);

    double kW = rect.width - 20;
    double kH = rect.height;
    double www = (kW - circleW - 20) / 2;
    double wwwR = www;

    return Path()
      ..moveTo(rect.topLeft.dx, rect.topLeft.dy + 20)
      ..lineTo(rect.topLeft.dx, rect.topLeft.dy + kH)

      // rect bottom left
      ..arcTo(Rect.fromLTWH(rect.topLeft.dx, rect.topLeft.dy + kH, 20, 20), -pi,
          -pi / 2, false)
      ..lineTo(rect.topLeft.dx + kW, rect.topLeft.dy + kH + 20)

      // rect bottom right
      ..arcTo(Rect.fromLTWH(rect.topLeft.dx + kW, rect.topLeft.dy + kH, 20, 20),
          -3 * pi / 2, -pi / 2, false)
      ..lineTo(rect.topLeft.dx + kW + 20, rect.topLeft.dy + 20)

      // rect top right
      ..arcTo(Rect.fromLTWH(rect.topLeft.dx + kW, rect.topLeft.dy, 20, 20), 0,
          -pi / 2, false)
      ..lineTo(rect.topLeft.dx + kW - www, rect.topLeft.dy)

      // circle bottom right
      ..arcTo(
          Rect.fromLTWH(
              rect.topLeft.dx + kW - wwwR, rect.topLeft.dy - 20, 20, 20),
          pi / 2,
          pi / 2,
          false)
      ..lineTo(rect.topLeft.dx + kW - wwwR, rect.topLeft.dy - 20)

      // circle
      ..arcTo(
          Rect.fromLTWH(rect.topLeft.dx + kW - wwwR - circleW,
              rect.topLeft.dy - 20 - 50, circleW, circleW),
          0,
          -pi,
          false)
      ..lineTo(rect.topLeft.dx + kW - wwwR - circleW, rect.topLeft.dy - 20)

      // circle bottom left
      ..arcTo(
          Rect.fromLTWH(
              rect.topLeft.dx + 20 + www - 20, rect.topLeft.dy - 20, 20, 20),
          0,
          pi / 2,
          false)
      ..lineTo(rect.topLeft.dx, rect.topLeft.dy)

      // rect top left
      ..arcTo(Rect.fromLTWH(rect.topLeft.dx, rect.topLeft.dy, 20, 20), -pi / 2,
          -pi / 2, false)
      ..close();
  }

  @override
  void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {}

  @override
  ShapeBorder scale(double t) => this;
}

【讨论】:

  • 卡片采用自定义宽度和高度,如何使其响应父容器宽度?
  • 你好@MrinalJain 我已经修改并在同一个答案中添加了一个响应式示例。
  • 你好@MrinalJain 我编辑了一点,添加了一个 LayoutBuilder 以使其对响应式布局更加健壮。希望对您有所帮助!
猜你喜欢
  • 2021-09-29
  • 2021-09-19
  • 2020-12-24
  • 2022-01-04
  • 2018-08-21
  • 2018-11-18
  • 1970-01-01
  • 2021-02-08
  • 2020-01-14
相关资源
最近更新 更多