skip to Main Content

I’m trying to re-create a button I made with React Native that had different colours for each side giving it a kind of chiseled effect, a bit like Photoshop bevel and emboss, but also with rounded corners. At the moment I have a container outside the button which has the border on it, and inside I’m using RawMaterialButton. The code for the container is like this:

Container(
    BoxDecoration(
    border: Border(
    left: BorderSide(
    color: Colors.black,
    width: 1.0,
    ),
    top: BorderSide(
    color: Colors.black,
    width: 1.0,
     ),
    ),
   ),
  )

How can I make the corners for this border/container rounded?

Like this but with rounded corners:

enter image description here

2

Answers


  1. This is not a 100% working solution. I just wrote some Path functions to draw all the sides using CustomPainter.

    RoundedChiseledBorder

    class RoundedChiseledBorder extends StatelessWidget {
      final Widget child;
    
      final Color leftBorderColor;
      final Color rightBorderColor;
      final Color bottomBorderColor;
      final Color topBorderColor;
    
      final double borderRadius;
      final double borderWidth;
    
      RoundedChiseledBorder({
        @required this.child,
        this.borderRadius = 1,
        this.borderWidth = 2,
        this.bottomBorderColor = Colors.black,
        this.topBorderColor = Colors.black,
        this.rightBorderColor = Colors.black,
        this.leftBorderColor = Colors.black,
      });
    
      @override
      Widget build(BuildContext context) {
        return Stack(
          children: <Widget>[
            Positioned.fill(
              child: CustomPaint(
                painter: RoundedBorderPainter(
                  radius: borderRadius,
                  strokeWidth: borderWidth,
                  bottomBorderColor: bottomBorderColor,
                  leftBorderColor: leftBorderColor,
                  rightBorderColor: rightBorderColor,
                  topBorderColor: topBorderColor,
                ),
              ),
            ),
            child,
          ],
        );
      }
    }
    

    RoundedBorderPainterBorder

    import 'package:vector_math/vector_math.dart' as vm;
    
    class RoundedBorderPainter extends CustomPainter {
      final Color leftBorderColor;
      final Color rightBorderColor;
      final Color bottomBorderColor;
      final Color topBorderColor;
      final double strokeWidth;
      final StrokeCap strokeCap = StrokeCap.round;
      double radius;
    
      Size size;
    
      RoundedBorderPainter({
        this.leftBorderColor = Colors.black,
        this.rightBorderColor = Colors.black,
        this.topBorderColor = Colors.black,
        this.bottomBorderColor = Colors.black,
        this.strokeWidth = 2,
        this.radius = 1,
      }) {
        if (radius <= 1) this.radius = 1;
      }
    
      @override
      void paint(Canvas canvas, Size size) {
        radius = size.shortestSide / 2 < radius ? size.shortestSide / 2 : radius;
        this.size = size;
        Paint topPaint = Paint()
          ..color = topBorderColor
          ..strokeWidth = strokeWidth
          ..strokeCap = strokeCap
          ..style = PaintingStyle.stroke;
        Paint rightPaint = Paint()
          ..color = rightBorderColor
          ..strokeCap = strokeCap
          ..strokeWidth = strokeWidth
          ..style = PaintingStyle.stroke;
        Paint bottomPaint = Paint()
          ..color = bottomBorderColor
          ..strokeCap = strokeCap
          ..strokeWidth = strokeWidth
          ..style = PaintingStyle.stroke;
        Paint leftPaint = Paint()
          ..strokeCap = strokeCap
          ..color = leftBorderColor
          ..strokeWidth = strokeWidth
          ..style = PaintingStyle.stroke;
    
        canvas.drawPath(getPath1(), topPaint);
        canvas.drawPath(getPath2(), rightPaint);
        canvas.drawPath(getPath3(), bottomPaint);
        canvas.drawPath(getPath4(), leftPaint);
      }
    
      Path getPath1() {
        return Path()
          ..addPath(getTopLeftPath2(), Offset(0, 0))
          ..addPath(getTopPath(), Offset(0, 0))
          ..addPath(getTopRightPath1(), Offset(0, 0));
      }
    
      Path getPath2() {
        return Path()
          ..addPath(getTopRightPath2(), Offset(0, 0))
          ..addPath(getRightPath(), Offset(0, 0))
          ..addPath(getBottomRightPath1(), Offset(0, 0));
      }
    
      Path getPath3() {
        return Path()
          ..addPath(getBottomRightPath2(), Offset(0, 0))
          ..addPath(getBottomPath(), Offset(0, 0))
          ..addPath(getBottomLeftPath1(), Offset(0, 0));
      }
    
      Path getPath4() {
        return Path()
          ..addPath(getBottomLeftPath2(), Offset(0, 0))
          ..addPath(getLeftPath(), Offset(0, 0))
          ..addPath(getTopLeftPath1(), Offset(0, 0));
      }
    
      Path getTopPath() {
        return Path()
          ..moveTo(0 + radius, 0)
          ..lineTo(size.width - radius, 0);
      }
    
      Path getRightPath() {
        return Path()
          ..moveTo(size.width, 0 + radius)
          ..lineTo(size.width, size.height - radius);
      }
    
      Path getBottomPath() {
        return Path()
          ..moveTo(size.width - radius, size.height)
          ..lineTo(0 + radius, size.height);
      }
    
      Path getLeftPath() {
        return Path()
          ..moveTo(0, size.height - radius)
          ..lineTo(0, 0 + radius);
      }
    
      Path getTopRightPath1() {
        return Path()
          ..addArc(
            Rect.fromLTWH(size.width - (radius * 2), 0, radius * 2, radius * 2),
            vm.radians(-45),
            vm.radians(-45),
          );
      }
    
      Path getTopRightPath2() {
        return Path()
          ..addArc(
            Rect.fromLTWH(size.width - (radius * 2), 0, radius * 2, radius * 2),
            vm.radians(0),
            vm.radians(-45),
          );
      }
    
      Path getBottomRightPath1() {
        return Path()
          ..addArc(
            Rect.fromLTWH(size.width - (radius * 2), size.height - (radius * 2), radius * 2, radius * 2),
            vm.radians(45),
            vm.radians(-45),
          );
      }
    
      Path getBottomRightPath2() {
        return Path()
          ..addArc(
            Rect.fromLTWH(size.width - (radius * 2), size.height - (radius * 2), radius * 2, radius * 2),
            vm.radians(90),
            vm.radians(-45),
          );
      }
    
      Path getBottomLeftPath1() {
        return Path()
          ..addArc(
            Rect.fromLTWH(0, size.height - (radius * 2), radius * 2, radius * 2),
            vm.radians(135),
            vm.radians(-45),
          );
      }
    
      Path getBottomLeftPath2() {
        return Path()
          ..addArc(
            Rect.fromLTWH(0, size.height - (radius * 2), radius * 2, radius * 2),
            vm.radians(180),
            vm.radians(-45),
          );
      }
    
      Path getTopLeftPath1() {
        return Path()
          ..addArc(
            Rect.fromLTWH(0, 0, radius * 2, radius * 2),
            vm.radians(225),
            vm.radians(-45),
          );
      }
    
      Path getTopLeftPath2() {
        return Path()
          ..addArc(
            Rect.fromLTWH(0, 0, radius * 2, radius * 2),
            vm.radians(270),
            vm.radians(-45),
          );
      }
    
      @override
      bool shouldRepaint(CustomPainter oldDelegate) {
        return true;
      }
    }
    
    

    USAGE

    To use it just call

    class HomePage extends StatelessWidget {
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: RoundedChiseledBorder(
              borderRadius: 10,
              borderWidth: 4,
              bottomBorderColor: Colors.red,
              leftBorderColor: Colors.black,
              rightBorderColor: Colors.amber,
              topBorderColor: Colors.green,
              child: Container(
                height: 30,
                width: 300,
                alignment: Alignment.center,
                child: Text('Hello'),
              ),
            ),
          ),
        );
      }
    }
    
    Login or Signup to reply.
  2. Ajil’s solution looks like the right direction to go. You are right though, it’s an amazing amount of work for such a small thing.

    Here is my tedious effort, it needs to be simplified to tidy it up but it produces a more accurate representation of your image.

    class Example extends StatefulWidget {
      @override
      _ExampleState createState() {
        return _ExampleState();
      }
    }
    
    class _ExampleState extends State<Example> {
      double height;
      double width;
    
      @override
      void initState() {
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        height = MediaQuery.of(context).size.height;
        width = MediaQuery.of(context).size.width;
    
        const double pi = 3.1415926535897932;
        return Scaffold(
            appBar: AppBar(
              title: Text("Some project"),
            ),
            body: Center(
              child:
                  Container(
                      width: width = 350,
                      height: height = 300,
                      child: Stack(children: <Widget>[
                        Align(
                            alignment: Alignment.center,
                            child: Container(
                              width: 300,
                              height: 300,
                              // color: Colors.red,
                              child: FlatButton(
                                  onPressed: () {
                                    print('button pressed');
                                  },
                                  child: Text(
                                    'BUTTON',
                                    textAlign: TextAlign.center,
                                    style: TextStyle(
                                        fontSize: 20, fontWeight: FontWeight.bold),
                                  )),
                            )),
                        Align(
                          //TOP BORDER
                          alignment: Alignment.topCenter,
                          child: Container(
                            decoration: BoxDecoration(
                              color: Colors.blue[200],
                              border:
                                  Border.all(width: 3.0, color: Colors.transparent),
                              borderRadius: BorderRadius.only(
                                  topLeft: Radius.circular(10.0),
                                  topRight: Radius.circular(10.0)),
                            ),
                            height: 50,
                            width: width,
                          ),
                        ),
                        Align(
                          //LEFT BORDER
                          alignment: Alignment.topLeft,
                          child: Container(
                            height: height,
                            width: 30,
                            decoration: BoxDecoration(
                                color: Colors.blue[100],
                                border: Border.all(
                                    width: 3.0, color: Colors.transparent),
                                borderRadius: BorderRadius.only(
                                    topLeft: Radius.circular(10.0),
                                    bottomLeft: Radius.circular(10.0))),
                          ),
                        ),
                        Align(
                          //RIGHT BORDER
                          alignment: Alignment.topRight,
                          child: Container(
                            height: height,
                            width: 15,
                            decoration: BoxDecoration(
                                color: Colors.blue[300],
                                border: Border.all(
                                    width: 3.0, color: Colors.transparent),
                                borderRadius: BorderRadius.only(
                                    topRight: Radius.circular(10.0),
                                    bottomRight: Radius.circular(10.0))),
                          ),
                        ),
                        Align(
                          //BOTTOM BORDER
                          alignment: Alignment.bottomCenter,
                          child: Container(
                            height: 15,
                            width: double.infinity,
                            decoration: BoxDecoration(
                                color: Colors.blue,
                                border: Border.all(
                                    width: 3.0, color: Colors.transparent),
                                borderRadius: BorderRadius.only(
                                    bottomLeft: Radius.circular(10.0),
                                    bottomRight: Radius.circular(10.0))),
                          ),
                        ),
                        Align(
                          //TOPLEFT BORDER
                          alignment: Alignment.topLeft,
                          child: Container(
                            decoration: BoxDecoration(
                              gradient: SweepGradient(
                                  center: FractionalOffset.bottomRight,
                                  startAngle: pi * 1.349,
                                  endAngle: pi * 1.35,
                                  colors: [
                                    Colors.blue[100],
                                    Colors.blue[200],
                                  ]),
                              border:
                                  Border.all(width: 3.0, color: Colors.transparent),
                              borderRadius: BorderRadius.only(
                                topLeft: Radius.circular(10.0),
                              ),
                            ),
                            width: 30,
                            height: 50,
                          ),
                        ),
                        Align(
                            //TOP RIGHT BORDER
                            alignment: Alignment.topRight,
                            child: Container(
                              decoration: BoxDecoration(
                                  gradient: SweepGradient(
                                      center: FractionalOffset.topRight,
                                      startAngle: 1.86,
                                      endAngle: 1.87,
                                      colors: [
                                        Colors.blue[300],
                                        Colors.blue[200],
                                      ]),
                                  border: Border.all(
                                      width: 3.0, color: Colors.transparent),
                                  borderRadius: BorderRadius.only(
                                    topRight: Radius.circular(10.0),
                                  )),
                              width: 15,
                              height: 50,
                            )),
                        Align(
                          //BOTTOMLEFT BORDER
                          alignment: Alignment.bottomLeft,
                          child: Container(
                            decoration: BoxDecoration(
                              gradient: SweepGradient(
                                  center: FractionalOffset.bottomLeft,
                                  startAngle: 5.8,
                                  endAngle: 5.81,
                                  colors: [
                                    Colors.blue[100],
                                    Colors.blue,
                                  ]),
                              border:
                                  Border.all(width: 3.0, color: Colors.transparent),
                              borderRadius: BorderRadius.only(
                                bottomLeft: Radius.circular(10.0),
                              ),
                            ),
                            width: 30,
                            height: 15,
                          ),
                        ),
                        Align(
                            //BOTTOM RIGHT BORDER
                            alignment: Alignment.bottomRight,
                            child: Container(
                              decoration: BoxDecoration(
                                  gradient: SweepGradient(
                                      center: FractionalOffset.bottomRight,
                                      startAngle: 3.99,
                                      endAngle: 4,
                                      colors: [
                                        Colors.blue,
                                        Colors.blue[300],
                                      ]),
                                  border: Border.all(
                                      width: 3.0, color: Colors.transparent),
                                  borderRadius: BorderRadius.only(
                                    bottomRight: Radius.circular(10.0),
                                    // bottomRight: Radius.circular(10.0)
                                  )),
                              width: 15,
                              height: 15,
                            ))
                      ])),
            ));
      }
    }
    

    How it looks

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search