简体   繁体   中英

Flutter: How to make a Container shape with corner border

I have this piece of code.

 Container(
      decoration: BoxDecoration(
        color: Colors.red,
        borderRadius: BorderRadius.circular(18),
      ),
      child: Center(
        child: Text(
          'Monday',
          style: TextStyle(
            color: Colors.white,
            fontSize: 30,
          ),
        ),
      ),
    );

That produces this

在此处输入图片说明

But I want something that looks like this.

在此处输入图片说明

By Knowing CustomPainter widget's paint


class MyCustomPainter extends CustomPainter {
  final double padding;
  final double frameSFactor;

  MyCustomPainter({
    required this.padding,
    required this.frameSFactor,
  });
  @override
  void paint(Canvas canvas, Size size) {
    final frameHWidth = size.width * frameSFactor;

    Paint paint = Paint()
      ..color = Colors.redAccent
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.fill
      ..strokeWidth = 4;

    /// background
    canvas.drawRRect(
        RRect.fromRectAndRadius(
          Rect.fromLTRB(0, 0, size.width, size.height),
          Radius.circular(18),
        ),
        paint);

    /// top left
    canvas.drawLine(
      Offset(0 + padding, padding),
      Offset(
        padding + frameHWidth,
        padding,
      ),
      paint..color = Colors.black,
    );

    canvas.drawLine(
      Offset(0 + padding, padding),
      Offset(
        padding,
        padding + frameHWidth,
      ),
      paint..color = Colors.black,
    );

    /// top Right
    canvas.drawLine(
      Offset(size.width - padding, padding),
      Offset(size.width - padding - frameHWidth, padding),
      paint..color = Colors.black,
    );
    canvas.drawLine(
      Offset(size.width - padding, padding),
      Offset(size.width - padding, padding + frameHWidth),
      paint..color = Colors.black,
    );

    /// Bottom Right
    canvas.drawLine(
      Offset(size.width - padding, size.height - padding),
      Offset(size.width - padding - frameHWidth, size.height - padding),
      paint..color = Colors.black,
    );
    canvas.drawLine(
      Offset(size.width - padding, size.height - padding),
      Offset(size.width - padding, size.height - padding - frameHWidth),
      paint..color = Colors.black,
    );

    /// Bottom Left
    canvas.drawLine(
      Offset(0 + padding, size.height - padding),
      Offset(0 + padding + frameHWidth, size.height - padding),
      paint..color = Colors.black,
    );
    canvas.drawLine(
      Offset(0 + padding, size.height - padding),
      Offset(0 + padding, size.height - padding - frameHWidth),
      paint..color = Colors.black,
    );
  }
@override 
bool shouldRepaint(covariant CustomPainter oldDelegate) => true; //based on your use-cases
 }

And use Like

  SizedBox(
                height: 200,
                width: 200,
                child: CustomPaint(
                  painter: MyCustomPainter(frameSFactor: .1, padding: 20),
                  child: Center(
                    child: Text(
                      'With Painter',
                      style: TextStyle(
                        color: Colors.black,
                        fontSize: 30,
                      ),
                    ),
                  ),
                ),
              ),

Also using Container decoration



class CustomDecoration extends Decoration {
  final Color? backgroundColor;
  final double frameSFactor;
  //defalut padding _Need to check
  final double gap;

  CustomDecoration({
    this.backgroundColor = Colors.transparent,
    required this.frameSFactor,
    required this.gap,
  });
  @override
  BoxPainter createBoxPainter([VoidCallback? onChanged]) {
    return CustomDecorationPainter(
        backgroundColor: backgroundColor!,
        frameSFactor: frameSFactor,
        padding: gap);
  }
}

class CustomDecorationPainter extends BoxPainter {
  final Color backgroundColor;
  final double frameSFactor;
  final double padding;

  CustomDecorationPainter({
    required this.backgroundColor,
    required this.frameSFactor,
    required this.padding,
  });

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    print(configuration.size!.height);

    final Rect bounds = offset & configuration.size!;
    final frameHWidth = configuration.size!.width * frameSFactor;

    Paint paint = Paint()
      ..color = backgroundColor
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.fill
      ..strokeWidth = 4;

    /// background
    canvas.drawRRect(
        RRect.fromRectAndRadius(
          bounds,
          Radius.circular(18),
        ),
        paint..color = Colors.redAccent);

    paint.color = Colors.black;

    /// top left
    canvas.drawLine(
      bounds.topLeft + Offset(padding, padding),
      Offset(bounds.topLeft.dx + frameHWidth, bounds.topLeft.dy) +
          Offset(padding, padding),
      paint,
    );
    canvas.drawLine(
      bounds.topLeft + Offset(padding, padding),
      Offset(bounds.topLeft.dx, bounds.topLeft.dy + frameHWidth) +
          Offset(padding, padding),
      paint,
    );

    //top Right
    canvas.drawLine(
      Offset(bounds.topRight.dx - padding, bounds.topRight.dy + padding),
      Offset(bounds.topRight.dx - padding - frameHWidth,
          bounds.topRight.dy + padding),
      paint,
    );
    canvas.drawLine(
      Offset(bounds.topRight.dx - padding, bounds.topRight.dy + padding),
      Offset(bounds.topRight.dx - padding,
          bounds.topRight.dy + padding + frameHWidth),
      paint..color,
    );

    //bottom Right
    canvas.drawLine(
      Offset(bounds.bottomRight.dx - padding, bounds.bottomRight.dy - padding),
      Offset(bounds.bottomRight.dx - padding,
          bounds.bottomRight.dy - padding - frameHWidth),
      paint,
    );
    canvas.drawLine(
      Offset(bounds.bottomRight.dx - padding, bounds.bottomRight.dy - padding),
      Offset(bounds.bottomRight.dx - padding - frameHWidth,
          bounds.bottomRight.dy - padding),
      paint,
    );
//bottom Left
    canvas.drawLine(
      Offset(bounds.bottomLeft.dx + padding, bounds.bottomLeft.dy - padding),
      Offset(bounds.bottomLeft.dx + padding,
          bounds.bottomLeft.dy - padding - frameHWidth),
      paint,
    );
    canvas.drawLine(
      Offset(bounds.bottomLeft.dx + padding, bounds.bottomLeft.dy - padding),
      Offset(bounds.bottomLeft.dx + padding + frameHWidth,
          bounds.bottomLeft.dy - padding),
      paint,
    );
  }
}

And use like


 SizedBox(
                width: 200,
                height: 200,
                child: Container(
                  alignment: Alignment.center,
                  decoration: CustomDecoration(
                    frameSFactor: .1,
                    gap: 20,
                  ),
                  child: Text("With Decoration"),
                ),
              ),

you can add the button the way you like

在此处输入图片说明

You have to write a CustomPaniter class to achieve this, luckly there's a site which can generate code for a given svg or use Nested Stack with Container . This example gives the one which you expected.

CustomPainter class

class RPSCustomPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    Path path_0 = Path();
    path_0.moveTo(size.width * 0.1898734, 0);
    path_0.lineTo(size.width * 0.06962025, 0);
    path_0.cubicTo(size.width * 0.03117006, 0, 0, size.height * 0.03117006, 0,
        size.height * 0.06962025);
    path_0.lineTo(0, size.height * 0.1835443);
    path_0.lineTo(size.width * 0.02531646, size.height * 0.1835443);
    path_0.lineTo(size.width * 0.02531646, size.height * 0.06962025);
    path_0.cubicTo(
        size.width * 0.02531646,
        size.height * 0.04515196,
        size.width * 0.04515196,
        size.height * 0.02531646,
        size.width * 0.06962025,
        size.height * 0.02531646);
    path_0.lineTo(size.width * 0.1898734, size.height * 0.02531646);
    path_0.lineTo(size.width * 0.1898734, 0);
    path_0.close();
    path_0.moveTo(size.width * 0.1898734, size.height * 0.9746835);
    path_0.lineTo(size.width * 0.06962025, size.height * 0.9746835);
    path_0.cubicTo(
        size.width * 0.04515196,
        size.height * 0.9746835,
        size.width * 0.02531646,
        size.height * 0.9548481,
        size.width * 0.02531646,
        size.height * 0.9303797);
    path_0.lineTo(size.width * 0.02531646, size.height * 0.8164557);
    path_0.lineTo(0, size.height * 0.8164557);
    path_0.lineTo(0, size.height * 0.9303797);
    path_0.cubicTo(0, size.height * 0.9688291, size.width * 0.03117006,
        size.height, size.width * 0.06962025, size.height);
    path_0.lineTo(size.width * 0.1898734, size.height);
    path_0.lineTo(size.width * 0.1898734, size.height * 0.9746835);
    path_0.close();
    path_0.moveTo(size.width * 0.8227848, size.height);
    path_0.lineTo(size.width * 0.8227848, size.height * 0.9746835);
    path_0.lineTo(size.width * 0.9303797, size.height * 0.9746835);
    path_0.cubicTo(
        size.width * 0.9548481,
        size.height * 0.9746835,
        size.width * 0.9746835,
        size.height * 0.9548481,
        size.width * 0.9746835,
        size.height * 0.9303797);
    path_0.lineTo(size.width * 0.9746835, size.height * 0.8164557);
    path_0.lineTo(size.width, size.height * 0.8164557);
    path_0.lineTo(size.width, size.height * 0.9303797);
    path_0.cubicTo(size.width, size.height * 0.9688291, size.width * 0.9688291,
        size.height, size.width * 0.9303797, size.height);
    path_0.lineTo(size.width * 0.8227848, size.height);
    path_0.close();
    path_0.moveTo(size.width * 0.8227848, size.height * 0.02531646);
    path_0.lineTo(size.width * 0.8227848, 0);
    path_0.lineTo(size.width * 0.9303797, 0);
    path_0.cubicTo(size.width * 0.9688291, 0, size.width,
        size.height * 0.03117006, size.width, size.height * 0.06962025);
    path_0.lineTo(size.width, size.height * 0.1835443);
    path_0.lineTo(size.width * 0.9746835, size.height * 0.1835443);
    path_0.lineTo(size.width * 0.9746835, size.height * 0.06962025);
    path_0.cubicTo(
        size.width * 0.9746835,
        size.height * 0.04515196,
        size.width * 0.9548481,
        size.height * 0.02531646,
        size.width * 0.9303797,
        size.height * 0.02531646);
    path_0.lineTo(size.width * 0.8227848, size.height * 0.02531646);
    path_0.close();

    Paint paint_0_fill = Paint()..style = PaintingStyle.fill;
    paint_0_fill.color = Color(0xff181717).withOpacity(1.0);
    canvas.drawPath(path_0, paint_0_fill);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}

and use it like so

Stack(
        alignment: Alignment.bottomCenter,
        children: [
          Stack(
            alignment: Alignment.center,
            children: [
              Container(
                width: 200,
                height: 200,
                decoration: BoxDecoration(
                  color: Colors.red,
                  borderRadius: BorderRadius.circular(18),
                ),
                child: Center(
                  child: Text(
                    'Monday',
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 30,
                    ),
                  ),
                ),
              ),
              Padding(
                padding: EdgeInsets.all(24),
                child: CustomPaint(
                  size: Size(180, 180),
                  painter: RPSCustomPainter(),
                ),
              ),
            ],
          ),
          Padding(
            padding: EdgeInsets.only(bottom: 24),
            child: ClipRRect(
              borderRadius: BorderRadius.circular(100),
              child: Container(
                padding: EdgeInsets.all(4),
                color: Colors.black,
                child: Icon(
                  Icons.close,
                  color: Colors.white,
                  size: 16,
                ),
              ),
            ),
          ),
        ],
      ),

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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