颤振-如何在颤振中制作卡片的自定义圆形形状?

时间:2020-05-07 13:45:24

标签: flutter flutter-layout

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

我为此做了很多尝试,但是我无法使其形状像设计一样。

1 个答案:

答案 0 :(得分:1)

我已经用ShapeBorder制作了一个示例,您可以将其复制(粘贴到dartPad并使用。 将图标替换为图像。

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

这是结果,希望它可以为您提供帮助:

enter image description here

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