71

4つの角がすべて丸い長方形の関数を見つけましたが、上の2つの角だけを丸くしたいと思います。私に何ができる?

canvas.drawRoundRect(new RectF(0, 100, 100, 300), 6, 6, paint);
4

16 に答える 16

62

パスを使用します。21未満のAPIで動作するという利点があります(Arcもこのように制限されているため、クワッドします)。まだ誰もがロリポップを持っているわけではないので、これは問題です。ただし、RectFを指定し、それを使用して値を設定し、アークを使用してAPI 1に戻すことはできますが、静的を使用することはできません(オブジェクトを構築するための新しいオブジェクトを宣言しないと)。

丸みを帯びた長方形を描く:

    path.moveTo(right, top + ry);
    path.rQuadTo(0, -ry, -rx, -ry);
    path.rLineTo(-(width - (2 * rx)), 0);
    path.rQuadTo(-rx, 0, -rx, ry);
    path.rLineTo(0, (height - (2 * ry)));
    path.rQuadTo(0, ry, rx, ry);
    path.rLineTo((width - (2 * rx)), 0);
    path.rQuadTo(rx, 0, rx, -ry);
    path.rLineTo(0, -(height - (2 * ry)));
    path.close();

完全な機能として:

static public Path RoundedRect(float left, float top, float right, float bottom, float rx, float ry, boolean conformToOriginalPost) {
    Path path = new Path();
    if (rx < 0) rx = 0;
    if (ry < 0) ry = 0;
    float width = right - left;
    float height = bottom - top;
    if (rx > width/2) rx = width/2;
    if (ry > height/2) ry = height/2;
    float widthMinusCorners = (width - (2 * rx));
    float heightMinusCorners = (height - (2 * ry));

    path.moveTo(right, top + ry);
    path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
    path.rLineTo(-widthMinusCorners, 0);
    path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
    path.rLineTo(0, heightMinusCorners);

    if (conformToOriginalPost) {
        path.rLineTo(0, ry);
        path.rLineTo(width, 0);
        path.rLineTo(0, -ry);
    }
    else {
        path.rQuadTo(0, ry, rx, ry);//bottom-left corner
        path.rLineTo(widthMinusCorners, 0);
        path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
    }

    path.rLineTo(0, -heightMinusCorners);

    path.close();//Given close, last lineto can be removed.

    return path;
}

それらを横切るのではなく、それらのコーナービットまでずっと並べたいと思うでしょう。これは、conformToOriginalPostにtrueを設定することです。そこのコントロールポイントに線を引くだけです。

あなたがそれをすべてやりたいが、ロリポップ以前のものを気にしないなら、そしてあなたのrxとryが十分に高いなら、それは円を描くべきであると緊急に主張します。

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
static public Path RoundedRect(float left, float top, float right, float bottom, float rx, float ry, boolean conformToOriginalPost) {
    Path path = new Path();
    if (rx < 0) rx = 0;
    if (ry < 0) ry = 0;
    float width = right - left;
    float height = bottom - top;
    if (rx > width/2) rx = width/2;
    if (ry > height/2) ry = height/2;
    float widthMinusCorners = (width - (2 * rx));
    float heightMinusCorners = (height - (2 * ry));

    path.moveTo(right, top + ry);
    path.arcTo(right - 2*rx, top, right, top + 2*ry, 0, -90, false); //top-right-corner
    path.rLineTo(-widthMinusCorners, 0);
    path.arcTo(left, top, left + 2*rx, top + 2*ry, 270, -90, false);//top-left corner.
    path.rLineTo(0, heightMinusCorners);
    if (conformToOriginalPost) {
        path.rLineTo(0, ry);
        path.rLineTo(width, 0);
        path.rLineTo(0, -ry);
    }
    else {
        path.arcTo(left, bottom - 2 * ry, left + 2 * rx, bottom, 180, -90, false); //bottom-left corner
        path.rLineTo(widthMinusCorners, 0);
        path.arcTo(right - 2 * rx, bottom - 2 * ry, right, bottom, 90, -90, false); //bottom-right corner
    }

    path.rLineTo(0, -heightMinusCorners);

    path.close();//Given close, last lineto can be removed.
    return path;
}

したがって、conformToOriginalPostは、実際には、下の2ビットを丸めずに丸められた四角形を描画します。

arcquadimage

于 2015-02-22T08:03:46.890 に答える
54

私は2つの長方形を描きます:

canvas.drawRect(new RectF(0, 110, 100, 290), paint);
canvas.drawRoundRect(new RectF(0, 100, 100, 200), 6, 6, paint);

またはそのようなもの、あなたはちょうどそれらを重ねて、上部の角が丸くなるようにします。できれば、このためのメソッドを作成する必要があります

于 2011-05-05T10:48:54.903 に答える
47

API 21以降では、Pathクラスに、addRoundRect()このように使用できる新しいメソッドが追加されました。

corners = new float[]{
    80, 80,        // Top left radius in px
    80, 80,        // Top right radius in px
    0, 0,          // Bottom right radius in px
    0, 0           // Bottom left radius in px
};

final Path path = new Path();
path.addRoundRect(rect, corners, Path.Direction.CW);
canvas.drawPath(path, mPaint);

Kotlinで

val corners = floatArrayOf(
    80f, 80f,   // Top left radius in px
    80f, 80f,   // Top right radius in px
    0f, 0f,     // Bottom right radius in px
    0f, 0f      // Bottom left radius in px
)

val path = Path()
path.addRoundRect(rect, corners, Path.Direction.CW)
canvas.drawPath(path, mPaint)
于 2019-05-21T12:41:57.787 に答える
31

この答えを変更し て、どのコーナーを丸くしたいのか、どのコーナーをシャープにしたいのかを設定できるようにしました。プレロリポップでも動作します

使用例

右上と右下の角だけが丸みを帯びています

 Path path = RoundedRect(0, 0, fwidth , fheight , 5,5,
                     false, true, true, false);
 canvas.drawPath(path,myPaint);

RoundRect:

    public static Path RoundedRect(
            float left, float top, float right, float bottom, float rx, float ry,
               boolean tl, boolean tr, boolean br, boolean bl
    ){
        Path path = new Path();
        if (rx < 0) rx = 0;
        if (ry < 0) ry = 0;
        float width = right - left;
        float height = bottom - top;
        if (rx > width / 2) rx = width / 2;
        if (ry > height / 2) ry = height / 2;
        float widthMinusCorners = (width - (2 * rx));
        float heightMinusCorners = (height - (2 * ry));

        path.moveTo(right, top + ry);
        if (tr)
            path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
        else{
            path.rLineTo(0, -ry);
            path.rLineTo(-rx,0);
        }
        path.rLineTo(-widthMinusCorners, 0);
        if (tl)
            path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
        else{
            path.rLineTo(-rx, 0);
            path.rLineTo(0,ry);
        }
        path.rLineTo(0, heightMinusCorners);

        if (bl)
            path.rQuadTo(0, ry, rx, ry);//bottom-left corner
        else{
            path.rLineTo(0, ry);
            path.rLineTo(rx,0);
        }

        path.rLineTo(widthMinusCorners, 0);
        if (br)
            path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
        else{
            path.rLineTo(rx,0);
            path.rLineTo(0, -ry);
        }

        path.rLineTo(0, -heightMinusCorners);

        path.close();//Given close, last lineto can be removed.

        return path;
    }
于 2016-02-27T11:03:30.603 に答える
12

Kotlinで記述されたシンプルなヘルパー関数。

private fun Canvas.drawTopRoundRect(rect: RectF, paint: Paint, radius: Float) {
    // Step 1. Draw rect with rounded corners.
    drawRoundRect(rect, radius, radius, paint)

    // Step 2. Draw simple rect with reduced height,
    // so it wont cover top rounded corners.
    drawRect(
            rect.left,
            rect.top + radius,
            rect.right,
            rect.bottom,
            paint
    )
}

使用法:

canvas.drawTopRoundRect(rect, paint, radius)
于 2017-11-05T20:38:05.870 に答える
11

パスを使用すると、これを簡単に実現できます。

val radiusArr = floatArrayOf(
    15f, 15f,
    15f, 15f,
    0f, 0f,
    0f, 0f
)
val myPath = Path()
myPath.addRoundRect(
    RectF(0f, 0f, 400f, 400f),
    radiusArr,
    Path.Direction.CW
)

canvas.drawPath(myPath, paint)
于 2019-12-16T10:03:42.337 に答える
10
public static Path composeRoundedRectPath(RectF rect, float topLeftDiameter, float topRightDiameter,float bottomRightDiameter, float bottomLeftDiameter){
    Path path = new Path();
    topLeftDiameter = topLeftDiameter < 0 ? 0 : topLeftDiameter;
    topRightDiameter = topRightDiameter < 0 ? 0 : topRightDiameter;
    bottomLeftDiameter = bottomLeftDiameter < 0 ? 0 : bottomLeftDiameter;
    bottomRightDiameter = bottomRightDiameter < 0 ? 0 : bottomRightDiameter;

    path.moveTo(rect.left + topLeftDiameter/2 ,rect.top);
    path.lineTo(rect.right - topRightDiameter/2,rect.top);
    path.quadTo(rect.right, rect.top, rect.right, rect.top + topRightDiameter/2);
    path.lineTo(rect.right ,rect.bottom - bottomRightDiameter/2);
    path.quadTo(rect.right ,rect.bottom, rect.right - bottomRightDiameter/2, rect.bottom);
    path.lineTo(rect.left + bottomLeftDiameter/2,rect.bottom);
    path.quadTo(rect.left,rect.bottom,rect.left, rect.bottom - bottomLeftDiameter/2);
    path.lineTo(rect.left,rect.top + topLeftDiameter/2);
    path.quadTo(rect.left,rect.top, rect.left + topLeftDiameter/2, rect.top);
    path.close();

    return path;
}
于 2016-06-30T12:53:12.303 に答える
7

私は以下の手順に従ってこれを達成しました。

これらは、丸みを帯びた長方形がきれいに見えるための前提条件です。

  • エッジの半径は(長方形の高さ/ 2)に等しくなければなりません。これは、値が異なる場合、曲線が長方形の直線と交わる場所が

次は、角の丸い長方形を描く手順です。

  • まず、半径=長方形の高さ/ 2で、左側と右側に2つの円を描きます。

  • 次に、これらの円の間に長方形を描画して、目的の角の丸い長方形を取得します。

以下のコードを投稿しています

private void drawRoundedRect(Canvas canvas, float left, float top, float right, float bottom) {
    float radius = getHeight() / 2;
    canvas.drawCircle(radius, radius, radius, mainPaint);
    canvas.drawCircle(right - radius, radius, radius, mainPaint);
    canvas.drawRect(left + radius, top, right - radius, bottom, mainPaint);
}

これで、次のような非常に優れた角の丸い長方形になります。ここに画像の説明を入力してください

于 2016-05-13T09:43:36.623 に答える
6

これは古い質問ですが、多くのカスタムコードやハッキーな描画を行わずにネイティブSDKを使用しているため、ソリューションを追加したいと思いました。このソリューションは、API1に戻ってサポートされます。

これを適切に行う方法は、パスを作成することです(他の回答で述べたように)が、前の回答はaddRoundedRect、各コーナーの半径を取る関数呼び出しを見落としているようです。

変数

private val path = Path()
private val paint = Paint()

セットアップペイント

paint.color = Color.RED
paint.style = Paint.Style.FILL

サイズ変更でパスを更新

onMeasureビューやドローアブルなど、onDrawではない場所でこれを呼び出しonBoundChangeます。(この例のように)変更されない場合は、ペイントを設定した場所にこのコードを配置できます。

val radii = floatArrayOf(
    25f, 25f, //Top left corner
    25f, 25f, //Top right corner
    0f, 0f,   //Bottom right corner
    0f, 0f,   //Bottom left corner
)

path.reset() //Clears the previously set path
path.addRoundedRect(0f, 0f, 100f, 100f, radii, Path.Direction.CW)

このコードは、上部の角が半径25で丸みを帯びた100x100の丸みを帯びた長方形を作成します。

パスを描く

onDrawビューまたはdrawドローアブルの場合は、これを呼び出します。

canvas.drawPath(path, paint)
于 2019-09-03T07:19:18.570 に答える
5

ソリッドサイドを描画する簡単で効率的な方法の1つは、クリッピングを使用することです。rectクリッピングは基本的に無料であり、カスタムパスよりもはるかに少ないコードで記述できます。

左上と右上を50ピクセルで丸めた、300x300の長方形が必要な場合は、次の操作を実行できます。

canvas.save();
canvas.clipRect(0, 0, 300, 300);
canvas.drawRoundRect(new RectF(0, 0, 300, 350), 50, 50, paint);
canvas.restore();

このアプローチは、隣接する2つまたは3つのコーナーでの丸めに対してのみ機能するため、パスベースのアプローチよりも構成が少し難しくなりますが、drawRoundRect()は完全にハードウェアアクセラレーションされている(つまり、三角形にテッセレートされている)ため、ラウンドレクを使用する方が効率的です。一方、drawPath()は常にソフトウェアレンダリングにフォールバックします(ソフトウェア-パスビットマップを描画し、それをアップロードしてGPUにキャッシュします)。

頻度の低い小さな描画では大きなパフォーマンスの問題ではありませんが、パスをアニメーション化する場合、ソフトウェア描画のコストによってフレーム時間が長くなり、フレームをドロップする可能性が高くなります。パスマスクもメモリを消費します。

パスベースのアプローチを使用する場合は、GradientDrawableを使用してコード行を簡略化することをお勧めします(たとえば、ビットマップを描画するためにカスタムシェーダーを設定する必要がない場合)。

mGradient.setBounds(0, 0, 300, 300);
mGradient.setCornerRadii(new int[] {50,50, 50,50, 0,0, 0,0});

GradientDrawable#setCornerRadii()を使用すると、任意のコーナーを任意の丸みに設定し、状態間で合理的にアニメーション化できます。

于 2017-08-22T00:19:22.560 に答える
3

drawLine()を使用して、drawArc()から関数を使用して、その部分を1つずつ描画できますCanvas

于 2011-05-05T10:47:25.073 に答える
3

半径が高さの半分の場合に丸みを帯びた辺を描画するPath#arcTo()バージョン。

fun getPathOfRoundedRectF(
    rect: RectF,
    topLeftRadius: Float = 0f,
    topRightRadius: Float = 0f,
    bottomRightRadius: Float = 0f,
    bottomLeftRadius: Float = 0f
): Path {
    val tlRadius = topLeftRadius.coerceAtLeast(0f)
    val trRadius = topRightRadius.coerceAtLeast(0f)
    val brRadius = bottomRightRadius.coerceAtLeast(0f)
    val blRadius = bottomLeftRadius.coerceAtLeast(0f)

    with(Path()) {
        moveTo(rect.left + tlRadius, rect.top)

        //setup top border
        lineTo(rect.right - trRadius, rect.top)

        //setup top-right corner
        arcTo(
            RectF(
                rect.right - trRadius * 2f,
                rect.top,
                rect.right,
                rect.top + trRadius * 2f
            ), -90f, 90f
        )

        //setup right border
        lineTo(rect.right, rect.bottom - trRadius)

        //setup bottom-right corner
        arcTo(
            RectF(
                rect.right - brRadius * 2f,
                rect.bottom - brRadius * 2f,
                rect.right,
                rect.bottom
            ), 0f, 90f
        )

        //setup bottom border
        lineTo(rect.left + blRadius, rect.bottom)

        //setup bottom-left corner
        arcTo(
            RectF(
                rect.left,
                rect.bottom - blRadius * 2f,
                rect.left + blRadius * 2f,
                rect.bottom
            ), 90f, 90f
        )

        //setup left border
        lineTo(rect.left, rect.top + tlRadius)

        //setup top-left corner
        arcTo(
            RectF(
                rect.left,
                rect.top,
                rect.left + tlRadius * 2f,
                rect.top + tlRadius * 2f
            ),
            180f,
            90f
        )

        close()

        return this
    }
}

2つの丸い角 3つの丸い角 3つの丸い角

于 2020-07-02T07:15:06.070 に答える
2

左の丸い角で丸い長方形を描く

  private void drawRoundRect(float left, float top, float right, float bottom, Paint paint, Canvas canvas) {
        Path path = new Path();
        path.moveTo(left, top);
        path.lineTo(right, top);
        path.lineTo(right, bottom);
        path.lineTo(left + radius, bottom);
        path.quadTo(left, bottom, left, bottom - radius);
        path.lineTo(left, top + radius);
        path.quadTo(left, top, left + radius, top);
        canvas.drawPath(path, onlinePaint);
    }
于 2015-07-20T07:02:38.297 に答える
2

PaintDrawableを使用する方がよい場合があります。

    val topLeftRadius = 10
    val topRightRadius = 10
    val bottomLeftRadius = 0
    val bottomRightRadius = 0
    val rect = Rect(0, 0, 100, 100)
    val paintDrawable = PaintDrawable(Color.RED)
    val outter = floatArrayOf(topLeftRadius, topLeftRadius, topRightRadius, topRightRadius,
            bottomLeftRadius, bottomLeftRadius, bottomRightRadius, bottomRightRadius)
    paintDrawable.setCornerRadii(outter)
    paintDrawable.bounds = rect
    paintDrawable.draw(canvas)
于 2019-01-16T03:32:51.340 に答える
2

上記の質問に対する私の答えは次のとおりです。ここでは、低レベルのAPIでも使用できる関数とPath一緒に使用するKotlin拡張関数を作成しました。quadTo

fun Canvas.drawRoundRectPath(
rectF: RectF,
radius: Float,
roundTopLeft: Boolean,
roundTopRight: Boolean,
roundBottomLeft: Boolean,
roundBottomRight: Boolean,
paint: Paint) {

val path = Path()

//Move path cursor to start point
if (roundBottomLeft) {
    path.moveTo(rectF.left, rectF.bottom - radius)
} else {
    path.moveTo(rectF.left, rectF.bottom)
}

// drawing line and rounding top left curve
if (roundTopLeft) {
    path.lineTo(rectF.left, rectF.top + radius)
    path.quadTo(rectF.left, rectF.top, rectF.left + radius, rectF.top)
} else {
    path.lineTo(rectF.left, rectF.top)
}

// drawing line an rounding top right curve
if (roundTopRight) {
    path.lineTo(rectF.right - radius, rectF.top)
    path.quadTo(rectF.right, rectF.top, rectF.right, rectF.top + radius)
} else {
    path.lineTo(rectF.right, rectF.top)
}

// drawing line an rounding bottom right curve
if (roundBottomRight) {
    path.lineTo(rectF.right, rectF.bottom - radius)
    path.quadTo(rectF.right, rectF.bottom, rectF.right - radius, rectF.bottom)
} else {
    path.lineTo(rectF.right, rectF.bottom)
}

// drawing line an rounding bottom left curve
if (roundBottomLeft) {
    path.lineTo(rectF.left + radius, rectF.bottom)
    path.quadTo(rectF.left, rectF.bottom, rectF.left, rectF.bottom - radius)
} else {
    path.lineTo(rectF.left, rectF.bottom)
}
path.close()

drawPath(path, paint)
}

キャンバスオブジェクトを使用して関数を呼び出し、RectF曲線を適用するディメンションを使用してを渡すことができます。

また、丸めたいコーナーのブール値を渡すことができます。この回答は、個々のコーナーの半径を受け入れるようにさらにカスタマイズできます。

于 2020-10-01T10:22:31.207 に答える
1

たぶん、次のコードがあなたを助けることができます

        Paint p = new Paint();
        p.setColor(color);

        float[] corners = new float[]{
                15, 15,        // Top, left in px
                15, 15,        // Top, right in px
                15, 15,          // Bottom, right in px
                15, 15           // Bottom,left in px
        };

        final Path path = new Path();
        path.addRoundRect(rect, corners, Path.Direction.CW);
        // Draw 
        canvas.drawPath(path, p);
于 2021-08-27T08:50:26.640 に答える