wake-up-neo.com

So erstellen Sie eine Ansicht in Android mit abgerundeten Ecken

Ich versuche in Android eine Ansicht mit abgerundeten Kanten zu erstellen. Die Lösung, die ich bisher gefunden habe, besteht darin, eine Form mit abgerundeten Ecken zu definieren und sie als Hintergrund für diese Ansicht zu verwenden.

Hier ist, was ich getan habe, definieren Sie eine Zeichnung wie unten angegeben

 

<padding
Android:top="2dp"
Android:bottom="2dp"/>
<corners Android:bottomRightRadius="20dp"
Android:bottomLeftRadius="20dp"
Android:topLeftRadius="20dp"
Android:topRightRadius="20dp"/>

Jetzt habe ich dies als Hintergrund für mein Layout verwendet (siehe unten)

<LinearLayout
        Android:orientation="vertical"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginLeft="10dp"
        Android:layout_marginRight="10dp"
        Android:layout_marginBottom="10dp"
        Android:clipChildren="true"
        Android:background="@drawable/rounded_corner">

Das funktioniert perfekt, ich kann sehen, dass die Ansicht abgerundete Kanten hat. 

Mein Layout enthält jedoch viele weitere untergeordnete Ansichten. Sagen Sie eine ImageView oder eine MapView. Wenn ich eine ImageView innerhalb des obigen Layouts platziere, werden die Ecken des Bildes nicht beschnitten/beschnitten, sondern erscheinen voll.

Ich habe andere Problemumgehungen gesehen, damit es so funktioniert wie die, die hier erklärt wurde. 

Gibt es eine Methode, um abgerundete Ecken für eine Ansicht und alle ihre .__ festzulegen. Untergeordnete Ansichten sind in der Hauptansicht enthalten, die gerundet wurde Ecken?

Vielen Dank.

58
Zach

Ein anderer Ansatz besteht darin, eine benutzerdefinierte Layoutklasse wie die folgende zu erstellen. Dieses Layout zeichnet zunächst seinen Inhalt als Offscreen-Bitmap, maskiert die Offscreen-Bitmap mit einem abgerundeten Rect und zeichnet dann die Offscreen-Bitmap auf der tatsächlichen Leinwand.

Ich habe es ausprobiert und es scheint zu funktionieren (zumindest für meinen einfachen Testfall). Dies wirkt sich natürlich auf die Leistung im Vergleich zu einem normalen Layout aus.

package com.example;

import Android.content.Context;
import Android.graphics.*;
import Android.util.AttributeSet;
import Android.util.DisplayMetrics;
import Android.util.TypedValue;
import Android.widget.FrameLayout;

public class RoundedCornerLayout extends FrameLayout {
    private final static float CORNER_RADIUS = 40.0f;

    private Bitmap maskBitmap;
    private Paint paint, maskPaint;
    private float cornerRadius;

    public RoundedCornerLayout(Context context) {
        super(context);
        init(context, null, 0);
    }

    public RoundedCornerLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle) {
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);

        Paint = new Paint(Paint.ANTI_ALIAS_FLAG);

        maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
        maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

        setWillNotDraw(false);
    }

    @Override
    public void draw(Canvas canvas) {
        Bitmap offscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas offscreenCanvas = new Canvas(offscreenBitmap);

        super.draw(offscreenCanvas);

        if (maskBitmap == null) {
            maskBitmap = createMask(canvas.getWidth(), canvas.getHeight());
        }

        offscreenCanvas.drawBitmap(maskBitmap, 0f, 0f, maskPaint);
        canvas.drawBitmap(offscreenBitmap, 0f, 0f, Paint);
    }

    private Bitmap createMask(int width, int height) {
        Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
        Canvas canvas = new Canvas(mask);

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        Paint.setColor(Color.WHITE);

        canvas.drawRect(0, 0, width, height, Paint);

        Paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, Paint);

        return mask;
    }
}

Verwenden Sie dies wie ein normales Layout:

<com.example.RoundedCornerLayout
    Android:layout_width="200dp"
    Android:layout_height="200dp">

    <ImageView
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:src="@drawable/test"/>

    <View
        Android:layout_width="match_parent"
        Android:layout_height="100dp"
        Android:background="#ff0000"
        />

</com.example.RoundedCornerLayout>
103

shape.xml

<shape xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:shape="rectangle">

    <solid Android:color="#f6eef1" />

    <stroke
        Android:width="2dp"
        Android:color="#000000" />

    <padding
        Android:bottom="5dp"
        Android:left="5dp"
        Android:right="5dp"
        Android:top="5dp" />

    <corners Android:radius="5dp" />

</shape>

und in deinem Layout

<LinearLayout
        Android:orientation="vertical"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:layout_marginLeft="10dp"
        Android:layout_marginRight="10dp"
        Android:layout_marginBottom="10dp"
        Android:clipChildren="true"
        Android:background="@drawable/shape">

        <ImageView
             Android:layout_width="match_parent"
             Android:layout_height="match_parent"
             Android:src="@drawable/your image"
             Android:background="@drawable/shape">

</LinearLayout>
38

Oder Sie können einen Android.support.v7.widget.CardView wie folgt verwenden:

<Android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.Android.com/apk/res-auto"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    card_view:cardBackgroundColor="@color/white"
    card_view:cardCornerRadius="4dp">

    <!--YOUR CONTENT-->
</Android.support.v7.widget.CardView>
34
rocketspacer

Wenn Sie Probleme beim Hinzufügen von Touch-Listenern zum Layout haben. Verwenden Sie dieses Layout als übergeordnetes Layout.

import Android.content.Context;
import Android.graphics.Bitmap;
import Android.graphics.Canvas;
import Android.graphics.Paint;
import Android.graphics.Path;
import Android.graphics.RectF;
import Android.graphics.Region;
import Android.util.AttributeSet;
import Android.util.DisplayMetrics;
import Android.util.TypedValue;
import Android.view.View;
import Android.widget.FrameLayout;

public class RoundedCornerLayout extends FrameLayout {
    private final static float CORNER_RADIUS = 6.0f;
    private float cornerRadius;

    public RoundedCornerLayout(Context context) {
        super(context);
        init(context, null, 0);
    }

    public RoundedCornerLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle) {
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }


    @Override
    protected void dispatchDraw(Canvas canvas) {
        int count = canvas.save();

        final Path path = new Path();
        path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), cornerRadius, cornerRadius, Path.Direction.CW);
        canvas.clipPath(path, Region.Op.REPLACE);

        canvas.clipPath(path);
        super.dispatchDraw(canvas);
        canvas.restoreToCount(count);
    }


}

wie 

<?xml version="1.0" encoding="utf-8"?>
<com.example.view.RoundedCornerLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <RelativeLayout
        Android:id="@+id/patentItem"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:paddingRight="20dp">
        ... your child goes here
    </RelativeLayout>
</com.example.view.RoundedCornerLayout>
16
Sushant

erstellen Sie eine XML-Datei "round.xml" im Zeichnungsordner

<solid Android:color="#FFFFFF" />
<stroke Android:width=".05dp" Android:color="#d2d2d2" />
<corners Android:topLeftRadius="5dp" Android:topRightRadius="5dp" Android:bottomLeftRadius="5dp" Android:bottomRightRadius="5dp" />

verwenden Sie dann round.xml als Hintergrund für Elemente. Dann werden abgerundete Ecken angezeigt

8
Ajay Venugopal

In Android L können Sie einfach View.setClipToOutline verwenden, um diesen Effekt zu erzielen. In früheren Versionen gibt es keine Möglichkeit, den Inhalt einer beliebigen ViewGroup in eine bestimmte Form zu schneiden.

Sie müssen sich etwas einfallen lassen, das Ihnen einen ähnlichen Effekt bringt:

  • Wenn Sie in ImageView nur abgerundete Ecken benötigen, können Sie das Bild über einen Shader über die Form legen, die Sie als Hintergrund verwenden. Betrachten Sie diese Bibliothek für ein Beispiel.

  • Wenn Sie wirklich brauchen, dass jedes Kind abgeschnitten wird, können Sie vielleicht einen anderen Blick auf Ihr Layout werfen? Einer mit einem Hintergrund in welcher Farbe auch immer Sie verwenden und ein rundes Loch in der Mitte? Sie könnten tatsächlich eine benutzerdefinierte Ansichtsgruppe erstellen, die diese Form über alle untergeordneten Elemente der onDraw-Methode zeichnet.

7
ivagarz

Jaap van Hengstums Antwort funktioniert großartig, aber ich denke, es ist teuer und wenn wir diese Methode beispielsweise auf einen Button anwenden, geht der Berührungseffekt verloren, da die Ansicht als Bitmap dargestellt wird.

Für mich besteht die beste und die einfachste Methode darin, eine Maske auf die Ansicht anzuwenden:

@Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
    super.onSizeChanged(width, height, oldWidth, oldHeight);

    float cornerRadius = <whatever_you_want>;
    this.path = new Path();
    this.path.addRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, Path.Direction.CW);
}

@Override
protected void dispatchDraw(Canvas canvas) {
    if (this.path != null) {
        canvas.clipPath(this.path);
    }
    super.dispatchDraw(canvas);
}
7
Donkey
public class RoundedCornerLayout extends FrameLayout {
    private double mCornerRadius;

    public RoundedCornerLayout(Context context) {
        this(context, null, 0);
    }

    public RoundedCornerLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle) {
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }

    public double getCornerRadius() {
        return mCornerRadius;
    }

    public void setCornerRadius(double cornerRadius) {
        mCornerRadius = cornerRadius;
    }

    @Override
    public void draw(Canvas canvas) {
        int count = canvas.save();

        final Path path = new Path();
        path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), (float) mCornerRadius, (float) mCornerRadius, Path.Direction.CW);
        canvas.clipPath(path, Region.Op.REPLACE);

        canvas.clipPath(path);
        super.draw(canvas);
        canvas.restoreToCount(count);
    }
}
2
Mahmoud Shahoud

folgen Sie diesem Tutorial und der gesamten Diskussion darunter - http://www.curious-creature.org/2012/12/11/Android-recipe-1-image-with-rounded-corners/

laut diesem Beitrag von Guy Romain, einem der führenden Entwickler des gesamten Android-UI-Toolkits, ist es möglich, einen Container (und alle seine Kindansichten) mit abgerundeten Ecken zu erstellen, er erklärte jedoch, dass dies zu teuer ist (von Aufführungen von Rendering-Probleme).

Ich empfehle Ihnen, nach seinem Beitrag zu gehen, und wenn Sie abgerundete Ecken haben möchten, implementieren Sie entsprechend diesem Beitrag abgerundete Ecken ImageView. Dann können Sie es in einen Container mit Hintergrund einfügen, und Sie erhalten den gewünschten Effekt.

das habe ich auch irgendwann auch gemacht.

2
Tal Kanel

Der Tutorial-Link, den Sie angegeben haben, scheint darauf hinzuweisen, dass Sie die Eigenschaften layout_width und layout_height Ihrer untergeordneten Elemente auf match_parent setzen müssen.

<ImageView
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">
1
danielcooperxyz

Unterschied zur Antwort von Jaap van Hengstum:

  1. Verwenden Sie BitmapShader anstelle von Maskenbitmap.
  2. Bitmap nur einmal erstellen.
public class RoundedFrameLayout extends FrameLayout {
    private Bitmap mOffscreenBitmap;
    private Canvas mOffscreenCanvas;
    private BitmapShader mBitmapShader;
    private Paint mPaint;
    private RectF mRectF;

    public RoundedFrameLayout(Context context) {
        super(context);
        init();
    }

    public RoundedFrameLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public RoundedFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setWillNotDraw(false);
    }

    @Override
    public void draw(Canvas canvas) {
        if (mOffscreenBitmap == null) {
            mOffscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
            mOffscreenCanvas = new Canvas(mOffscreenBitmap);
            mBitmapShader = new BitmapShader(mOffscreenBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaint.setShader(mBitmapShader);
            mRectF = new RectF(0f, 0f, canvas.getWidth(), canvas.getHeight());
        }
        super.draw(mOffscreenCanvas);

        canvas.drawRoundRect(mRectF, 8, 8, mPaint);
    }
}
1
Peter Zhao

Die CardView hat für mich in API 27 in Android Studio 3.0.1 funktioniert. Die colorPrimary wurde in der res/values/colors.xml-Datei referenziert und ist nur ein Beispiel. Für die layout_width von 0dp reicht es bis zur Breite des übergeordneten Elements. Sie müssen die Einschränkungen und Breite/Höhe an Ihre Bedürfnisse anpassen.

<Android.support.v7.widget.CardView
    Android:id="@+id/cardView"
    Android:layout_width="0dp"
    Android:layout_height="200dp"
    Android:layout_marginEnd="8dp"
    Android:layout_marginStart="8dp"
    Android:layout_marginTop="8dp"
    app:cardCornerRadius="4dp"
    app:cardBackgroundColor="@color/colorPrimary">

    <!-- put your content here -->

</Android.support.v7.widget.CardView>
1
Lloyd Rochester

probieren Sie diese Eigenschaft mit Ihrem linearen Layout aus
tools: context = ". Ihre Aktivität"

1
user4050065
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {

        Bitmap roundedBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap
                .getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(roundedBitmap);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(rect);
        final float roundPx = pixels;

        Paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        Paint.setColor(color);
        canvas.drawRoundRect(rectF, roundPx, roundPx, Paint);

        Paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, Paint);

        return roundedBitmap;
    }
0

Erstellen Sie eine XML-Datei mit folgendem Code unter Ihrem Zeichenordner. (Der Name der von mir erstellten Datei lautet round_corner.xml.)

round_corner.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:shape="rectangle">

    <!-- view background color -->
    <solid
        Android:color="#a9c5ac" >
    </solid>

    <!-- view border color and width -->
    <stroke
        Android:width="3dp"
        Android:color="#1c1b20" >
    </stroke>

    <!-- If you want to add some padding -->
    <padding
        Android:left="4dp"
        Android:top="4dp"
        Android:right="4dp"
        Android:bottom="4dp"    >
    </padding>

    <!-- Here is the corner radius -->
    <corners
        Android:radius="10dp"   >
    </corners>

.__ Behalten Sie diese Zeichnung als Hintergrund für die Ansicht bei, an der Sie den abgerundeten Eckenrand beibehalten möchten. Wir behalten es für ein LinearLayout

<LinearLayout Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:background="@drawable/rounded_corner"
        Android:layout_centerInParent="true">

        <TextView Android:layout_width="fill_parent"
            Android:layout_height="wrap_content"
            Android:text="Hi, This layout has rounded corner borders ..."
            Android:gravity="center"
            Android:padding="5dp"/>

    </LinearLayout>
0
Rajneesh Shukla