web-dev-qa-db-fra.com

Comment dessiner une bordure rectangulaire arrondie personnalisée (bordure de forme) dans Flutter?

J'essaie d'étendre la classe ShapeBorder pour ajouter des fonctionnalités. Mais en jouant avec la méthode Paint, j'ai trouvé quelque chose auquel je ne m'attendais pas: 

 enter image description here Les coins de la bordure et ceux du rectangle ne semblent pas correspondre. J'ai utilisé le code suivant:

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

Et créé le rectangle comme suit:

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"),),
            ),

J'ai l'impression que le code source de Flutter adopte une approche similaire, mais je ne vois peut-être rien.

EDIT Changer la style de ma Paint en PaintingStyle.fill, dessinant ainsi un rectangle sur le rectangle d'origine au lieu de bordures, il semble que j'obtienne les bordures correctes:

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

Je suis toujours perplexe sur la façon de faire cela ...

5
Bram Vanbilsen

Vous devez utiliser canvas.drawPath pas drawRect

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

canvas.drawPath(getOuterPath(rect), Paint);

aussi si vous voulez juste une frontière, il suffit d'utiliser 

 @override
  Path getInnerPath(Rect rect, {TextDirection textDirection}) {
    return new Path()
      ..fillType = PathFillType.evenOdd
      ..addPath(getOuterPath(rect), Offset.zero);
  }
5
Thomas

Vous pouvez utiliser 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);
1
vivek nakalgaonkar