如何在Flutter中绘制自定义圆角矩形边框(ShapeBorder)?

Bra*_*sen 6 dart flutter

我正在尝试扩展ShapeBorder类以添加一些功能.但只是玩弄这个paint方法,我找到了一些我没想到的东西:

在此输入图像描述 边框的角落和矩形的角落似乎不匹配.我使用了以下代码:

class CustomRoundedRectangleBorder extends ShapeBorder {

  final double borderWidth;
  final BorderRadius borderRadius;

  const CustomRoundedRectangleBorder({
    this.borderWidth: 1.0,
    this.borderRadius: BorderRadius.zero,
  })
      : assert(borderRadius != null);

  @override
  EdgeInsetsGeometry get dimensions {
    return new EdgeInsets.all(borderWidth);
  }

  @override
  ShapeBorder scale(double t) {
    return new CustomRoundedRectangleBorder(
      borderWidth: borderWidth * (t),
      borderRadius: borderRadius * (t),
    );
  }

  @override
  ShapeBorder lerpFrom(ShapeBorder a, double t) {
    assert(t != null);
    if (a is CustomRoundedRectangleBorder) {
      return new CustomRoundedRectangleBorder(
        borderWidth: ui.lerpDouble(a.borderWidth, borderWidth, t),
        borderRadius: BorderRadius.lerp(a.borderRadius, borderRadius, t),
      );
    }
    return super.lerpFrom(a, t);
  }

  @override
  ShapeBorder lerpTo(ShapeBorder b, double t) {
    assert(t != null);
    if (b is CustomRoundedRectangleBorder) {
      return new CustomRoundedRectangleBorder(
        borderWidth: ui.lerpDouble(borderWidth, b.borderWidth, t),
        borderRadius: BorderRadius.lerp(borderRadius, b.borderRadius, t),
      );
    }
    return super.lerpTo(b, t);
  }

  @override
  Path getInnerPath(Rect rect, { TextDirection textDirection }) {
    return new Path()
      ..addRRect(borderRadius.resolve(textDirection).toRRect(rect).deflate(
          borderWidth));
  }

  @override
  Path getOuterPath(Rect rect, { TextDirection textDirection }) {
    return new Path()
      ..addRRect(borderRadius.resolve(textDirection).toRRect(rect));
  }

  @override
  void paint(Canvas canvas, Rect rect, { TextDirection textDirection }) {
    rect = rect.deflate(borderWidth / 2.0);

    Paint paint;
    final RRect borderRect = borderRadius.resolve(textDirection).toRRect(rect);
    paint = new Paint()
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = borderWidth;
    canvas.drawRRect(borderRect, paint);
  }
}
Run Code Online (Sandbox Code Playgroud)

并创建矩形如下:

new Container(
              height: 100.0,
              width: 200.0,
              padding: new EdgeInsets.all(10.0),
              decoration: new ShapeDecoration(
                color: Colors.black,
                shape: new CustomRoundedRectangleBorder(
                  borderRadius: new BorderRadius.all(new Radius.circular(20.0)),
                  borderWidth: 10.0,
                ),
                // side: new BorderSide(color: Colors.white)
              ),
              child: new Center(child: new Text("My Button"),),
            ),
Run Code Online (Sandbox Code Playgroud)

我觉得Flutter源代码采用了类似的方法,但也许我没有看到任何东西.

编辑 改变style我的方式paint,PaintingStyle.fill从而在原始矩形而不是边框​​上绘制一个矩形,我似乎得到了正确的边框:

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

//    rect = rect.deflate(borderWidth / 2.0);

    Paint paint;
    final RRect borderRect = borderRadius.resolve(textDirection).toRRect(rect);
    paint = new Paint()
      ..color = Colors.red.withOpacity(0.25)
      ..style = PaintingStyle.fill
      ..strokeWidth = borderWidth;
    canvas.drawRRect(borderRect, paint);
  }
Run Code Online (Sandbox Code Playgroud)

我仍然对如何做到这一点感到困惑......

Abd*_*med 17

这对我有用!

\n
class MyButton extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    return DecoratedBox(\n      decoration:\n      ShapeDecoration(\n          shape: RoundedRectangleBorder(\n          side:new  BorderSide(color: Color(0xFF2A8068)), \n          borderRadius: new BorderRadius.all(new Radius.circular(4))),\n          color: Color(0xFF2A8068)),\n      child: Theme(\n        data: Theme.of(context).copyWith(\n            buttonTheme: ButtonTheme.of(context).copyWith(\n                materialTapTargetSize: MaterialTapTargetSize.shrinkWrap)),\n        child: OutlineButton(\n          shape:  RoundedRectangleBorder(\n              side:new  BorderSide(color: Color(0xFF2A8068)), //the outline color\n              borderRadius: new BorderRadius.all(new Radius.circular(4))),\n          child: Text(\n            "\xd8\xa7\xd8\xa8\xd8\xaf\xd8\xa3", //your text here\n             style: new TextStyle(\n              color: Colors.white, //your textColor\n            ),\n          ),\n          onPressed: () => {},\n        ),\n      ),\n    );\n
Run Code Online (Sandbox Code Playgroud)\n


小智 9

您可以使用canvas.drawRRect

canvas.drawRRect(RRect.fromRectAndRadius(Rect.fromLTWH(size.width / 2 - gap - smallMarkWidth - 15,gap * 8,gap + 70,gap * 5,),Radius.circular(15.0)),backgroundPaint);
Run Code Online (Sandbox Code Playgroud)


Tho*_*mas 6

你应该使用canvas.drawPath而不是drawRect

Paint paint = new Paint()
  ..color = borderColor
  ..style = PaintingStyle.stroke
  ..strokeWidth = borderWidth;

canvas.drawPath(getOuterPath(rect), paint);
Run Code Online (Sandbox Code Playgroud)

如果你只是想要一个边框,它就足以使用了

 @override
  Path getInnerPath(Rect rect, {TextDirection textDirection}) {
    return new Path()
      ..fillType = PathFillType.evenOdd
      ..addPath(getOuterPath(rect), Offset.zero);
  }
Run Code Online (Sandbox Code Playgroud)


yas*_*173 5

您可以使用ClipRRect小部件代替 drawRect,它使用起来很简单。

ClipRRect(
        borderRadius: BorderRadius.circular(10),
        child: Container(),
      ),
Run Code Online (Sandbox Code Playgroud)


Nik*_*ikh 5

绘制带有阴影的自定义圆形边框。

new Container(

                decoration:
                new BoxDecoration(
                  borderRadius: new BorderRadius.circular(10.0),
                  color: Colors.white,

                  boxShadow: [
                    new BoxShadow(
                        color: Colors.grey,
                        blurRadius: 3.0,
                        offset: new Offset(1.0, 1.0))
                  ],
                ),
)
Run Code Online (Sandbox Code Playgroud)

绘制没有阴影的自定义圆形边框。

new Container(
        decoration:
                new BoxDecoration(
                  borderRadius: new BorderRadius.circular(10.0),
                  color: Colors.grey,


                ),
)
Run Code Online (Sandbox Code Playgroud)