web-dev-qa-db-de.com

Wie erstelle ich ein Layout mit abgerundeten Ecken?

Wie kann ich ein Layout mit abgerundeten Ecken erstellen? Ich möchte meinem LinearLayout abgerundete Ecken zuweisen.

445
Addy

1: Definiere layout_bg.xml in Drawables:

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <solid Android:color="#FFFFFF"/>
    <stroke Android:width="3dp" Android:color="#B1BCBE" />
    <corners Android:radius="10dp"/>
    <padding Android:left="0dp" Android:top="0dp" Android:right="0dp" Android:bottom="0dp" />
</shape>

2: Fügen Sie Ihrem Layout layout_bg.xml als Hintergrund hinzu

Android:background="@drawable/layout_bg"
903
Gaurav Arora

Verwenden Sie für API 21+ Clip-Ansichten

Der Klasse View in API 21 wurde ein abgerundeter Gliederungsausschnitt hinzugefügt. Weitere Informationen finden Sie in diesem Schulungsdokument oder in diesem Referenz .

Diese eingebaute Funktion macht abgerundete Ecken sehr einfach zu implementieren. Es funktioniert in jeder Ansicht oder in jedem Layout und unterstützt das ordnungsgemäße Zuschneiden.

Hier ist was zu tun:

  • Erstellen Sie eine runde Form, die gezeichnet werden kann, und legen Sie sie als Hintergrund für Ihre Ansicht fest: Android:background="@drawable/round_outline"
  • In der Dokumentation heißt es dann nur noch: Android:clipToOutline="true"

Leider scheint es einen Fehler zu geben, und dieses XML-Attribut wird derzeit nicht erkannt. Zum Glück können wir das Clipping in Java einstellen:

  • In Ihrer Aktivität oder Fragment: View.setClipToOutline(true)

Wie es aussieht:

enter image description here

Besonderer Hinweis zu ImageViews

setClipToOutline() funktioniert nur, wenn der Hintergrund der Ansicht auf eine Form eingestellt ist, die gezeichnet werden kann. Wenn diese Hintergrundform vorhanden ist, behandelt View die Kontur des Hintergrunds als Rahmen für Beschneidungs- und Schattenzwecke.

Das heißt, wenn Sie in einer ImageView mit setClipToOutline() die Ecken abrunden möchten, muss Ihr Bild von Android:src anstelle von Android:background stammen (da der Hintergrund für die abgerundete Form verwendet wird). Wenn Sie Hintergrund verwenden MÜSSEN, um Ihr Bild anstelle von src festzulegen, können Sie diese Problemumgehung für verschachtelte Ansichten verwenden:

  • Erstellen Sie ein äußeres Layout, dessen Hintergrund auf Ihre zu zeichnende Form eingestellt ist
  • Wickeln Sie dieses Layout um Ihre ImageView (ohne Auffüllen)
  • Die ImageView (einschließlich aller anderen Elemente im Layout) wird jetzt auf die abgerundete Form des äußeren Layouts gekürzt.
96
hungryghost

Hier ist eine Kopie einer XML-Datei, um eine Grafik mit weißem Hintergrund, schwarzem Rand und abgerundeten Ecken zu erstellen:

 <?xml version="1.0" encoding="UTF-8"?> 
    <shape xmlns:Android="http://schemas.Android.com/apk/res/Android"> 
        <solid Android:color="#ffffffff"/>    

        <stroke Android:width="3dp"
                Android:color="#ff000000"
                />

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

        <corners Android:bottomRightRadius="7dp" Android:bottomLeftRadius="7dp" 
         Android:topLeftRadius="7dp" Android:topRightRadius="7dp"/> 
    </shape>

speichern Sie es als XML-Datei im Verzeichnis drawable. Verwenden Sie es unter Verwendung des Ressourcennamens (R.drawable.your_xml_name) so, als würden Sie einen beliebigen zeichnbaren Hintergrund (Symbol oder Ressourcendatei) verwenden.

59
kyogs

Verwenden Sie CardView in der Unterstützungsbibliothek von Android v7. Obwohl es ein bisschen schwer ist, löst es alle Probleme und ist einfach genug. Anders als die festgelegte Methode zum Zeichnen des Hintergrunds können Teilansichten erfolgreich abgeschnitten werden.

<?xml version="1.0" encoding="utf-8"?>
<Android.support.v7.widget.CardView xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:card_view="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    card_view:cardBackgroundColor="@Android:color/transparent"
    card_view:cardCornerRadius="5dp"
    card_view:cardElevation="0dp"
    card_view:contentPadding="0dp">
    <YOUR_LINEARLAYOUT_HERE>
</Android.support.v7.widget.CardView>
28
Evan JIANG

Ich habe das so gemacht:

Screenshot prüfen:

Relative layout Background

Erstellen Sie eine zeichnbare Datei mit dem Namen custom_rectangle.xml in einem zeichnbaren Ordner:

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

    <solid Android:color="@Android:color/white" />

    <corners Android:radius="10dip" />

    <stroke
        Android:width="1dp"
        Android:color="@Android:color/white" />

</shape>

Wenden Sie nun Rechteckhintergrund auf Ansicht an:

mView.setBackground(R.drawlable.custom_rectangle);

Fertig

26
Hiren Patel

Ich denke, ein besserer Weg, dies zu tun, besteht darin, zwei Dinge zusammenzuführen:

  1. machen Sie eine Bitmap des Layouts, wie hier gezeigt .

  2. machen Sie eine gerundete Zeichnung aus der Bitmap, wie gezeigt hier

  3. legen Sie die Zeichenfläche in einer ImageView fest.

Hiermit werden Fälle behandelt, die von anderen Lösungen nicht gelöst werden konnten, z. B. Inhalte mit Ecken.

Ich denke, es ist auch ein bisschen GPU-freundlicher, da es eine einzelne Schicht anstelle von 2 zeigt.

Der einzig bessere Weg ist, eine vollständig angepasste Ansicht zu erstellen, aber das ist viel Code und kann viel Zeit in Anspruch nehmen. Ich denke, was ich hier vorgeschlagen habe, ist das Beste aus beiden Welten.

Hier ist ein Ausschnitt, wie es gemacht werden kann:

RoundedCornersDrawable.Java

/**
 * shows a bitmap as if it had rounded corners. based on :
 * http://rahulswackyworld.blogspot.co.il/2013/04/Android-drawables-with-rounded_7.html
 * easy alternative from support library: RoundedBitmapDrawableFactory.create( ...) ; 
 */
public class RoundedCornersDrawable extends BitmapDrawable {

    private final BitmapShader bitmapShader;
    private final Paint p;
    private final RectF rect;
    private final float borderRadius;

    public RoundedCornersDrawable(final Resources resources, final Bitmap bitmap, final float borderRadius) {
        super(resources, bitmap);
        bitmapShader = new BitmapShader(getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        final Bitmap b = getBitmap();
        p = getPaint();
        p.setAntiAlias(true);
        p.setShader(bitmapShader);
        final int w = b.getWidth(), h = b.getHeight();
        rect = new RectF(0, 0, w, h);
        this.borderRadius = borderRadius < 0 ? 0.15f * Math.min(w, h) : borderRadius;
    }

    @Override
    public void draw(final Canvas canvas) {
        canvas.drawRoundRect(rect, borderRadius, borderRadius, p);
    }
}

CustomView.Java

public class CustomView extends ImageView {
    private View mMainContainer;
    private boolean mIsDirty=false;

    // TODO for each change of views/content, set mIsDirty to true and call invalidate

    @Override
    protected void onDraw(final Canvas canvas) {
        if (mIsDirty) {
            mIsDirty = false;
            drawContent();
            return;
        }
        super.onDraw(canvas);
    }

    /**
     * draws the view's content to a bitmap. code based on :
     * http://nadavfima.com/Android-snippet-inflate-a-layout-draw-to-a-bitmap/
     */
    public static Bitmap drawToBitmap(final View viewToDrawFrom, final int width, final int height) {
        // Create a new bitmap and a new canvas using that bitmap
        final Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(bmp);
        viewToDrawFrom.setDrawingCacheEnabled(true);
        // Supply measurements
        viewToDrawFrom.measure(MeasureSpec.makeMeasureSpec(canvas.getWidth(), MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(canvas.getHeight(), MeasureSpec.EXACTLY));
        // Apply the measures so the layout would resize before drawing.
        viewToDrawFrom.layout(0, 0, viewToDrawFrom.getMeasuredWidth(), viewToDrawFrom.getMeasuredHeight());
        // and now the bmp object will actually contain the requested layout
        canvas.drawBitmap(viewToDrawFrom.getDrawingCache(), 0, 0, new Paint());
        return bmp;
    }

    private void drawContent() {
        if (getMeasuredWidth() <= 0 || getMeasuredHeight() <= 0)
            return;
        final Bitmap bitmap = drawToBitmap(mMainContainer, getMeasuredWidth(), getMeasuredHeight());
        final RoundedCornersDrawable drawable = new RoundedCornersDrawable(getResources(), bitmap, 15);
        setImageDrawable(drawable);
    }

}

BEARBEITEN: fand eine nette Alternative, basierend auf "RoundKornersLayouts" Bibliothek . Haben Sie eine Klasse, die für alle Layoutklassen verwendet wird, die Sie erweitern möchten, und die gerundet werden soll:

//based on https://github.com/JcMinarro/RoundKornerLayouts
class CanvasRounder(cornerRadius: Float, cornerStrokeColor: Int = 0, cornerStrokeWidth: Float = 0F) {
    private val path = Android.graphics.Path()
    private lateinit var rectF: RectF
    private var strokePaint: Paint?
    var cornerRadius: Float = cornerRadius
        set(value) {
            field = value
            resetPath()
        }

    init {
        if (cornerStrokeWidth <= 0)
            strokePaint = null
        else {
            strokePaint = Paint()
            strokePaint!!.style = Paint.Style.STROKE
            strokePaint!!.isAntiAlias = true
            strokePaint!!.color = cornerStrokeColor
            strokePaint!!.strokeWidth = cornerStrokeWidth
        }
    }

    fun round(canvas: Canvas, drawFunction: (Canvas) -> Unit) {
        val save = canvas.save()
        canvas.clipPath(path)
        drawFunction(canvas)
        if (strokePaint != null)
            canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, strokePaint)
        canvas.restoreToCount(save)
    }

    fun updateSize(currentWidth: Int, currentHeight: Int) {
        rectF = Android.graphics.RectF(0f, 0f, currentWidth.toFloat(), currentHeight.toFloat())
        resetPath()
    }

    private fun resetPath() {
        path.reset()
        path.addRoundRect(rectF, cornerRadius, cornerRadius, Path.Direction.CW)
        path.close()
    }

}

Fügen Sie dann in jeder Ihrer benutzerdefinierten Layoutklassen Code hinzu, der dem folgenden ähnelt:

class RoundedConstraintLayout : ConstraintLayout {
    private lateinit var canvasRounder: CanvasRounder

    constructor(context: Context) : super(context) {
        init(context, null, 0)
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init(context, attrs, 0)
    }

    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
        init(context, attrs, defStyle)
    }

    private fun init(context: Context, attrs: AttributeSet?, defStyle: Int) {
        val array = context.obtainStyledAttributes(attrs, R.styleable.RoundedCornersView, 0, 0)
        val cornerRadius = array.getDimension(R.styleable.RoundedCornersView_corner_radius, 0f)
        val cornerStrokeColor = array.getColor(R.styleable.RoundedCornersView_corner_stroke_color, 0)
        val cornerStrokeWidth = array.getDimension(R.styleable.RoundedCornersView_corner_stroke_width, 0f)
        array.recycle()
        canvasRounder = CanvasRounder(cornerRadius,cornerStrokeColor,cornerStrokeWidth)
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
            setLayerType(FrameLayout.LAYER_TYPE_SOFTWARE, null)
        }
    }

    override fun onSizeChanged(currentWidth: Int, currentHeight: Int, oldWidth: Int, oldheight: Int) {
        super.onSizeChanged(currentWidth, currentHeight, oldWidth, oldheight)
        canvasRounder.updateSize(currentWidth, currentHeight)
    }

    override fun draw(canvas: Canvas) = canvasRounder.round(canvas) { super.draw(canvas) }

    override fun dispatchDraw(canvas: Canvas) = canvasRounder.round(canvas) { super.dispatchDraw(canvas) }

}

Wenn Sie Attribute unterstützen möchten, verwenden Sie diese wie in der Bibliothek beschrieben:

<resources>
  <declare-styleable name="RoundedCornersView">
      <attr name="corner_radius" format="dimension"/>
      <attr name="corner_stroke_width" format="dimension"/>
      <attr name="corner_stroke_color" format="color"/>
  </declare-styleable>
</resources>

Eine weitere Alternative, die für die meisten Anwendungen möglicherweise einfacher ist: Verwenden Sie MaterialCardView. Hiermit können Sie die abgerundeten Ecken, die Konturfarbe und -breite sowie die Höhe anpassen.

Beispiel:

<FrameLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android" xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools" Android:layout_width="match_parent"
    Android:layout_height="match_parent" Android:clipChildren="false" Android:clipToPadding="false"
    tools:context=".MainActivity">

    <com.google.Android.material.card.MaterialCardView
        Android:layout_width="100dp" Android:layout_height="100dp" Android:layout_gravity="center"
        app:cardCornerRadius="8dp" app:cardElevation="8dp" app:strokeColor="#f00" app:strokeWidth="2dp">

        <ImageView
            Android:layout_width="match_parent" Android:layout_height="match_parent" Android:background="#0f0"/>

    </com.google.Android.material.card.MaterialCardView>

</FrameLayout>

Und das Ergebnis:

enter image description here

Beachten Sie, dass an den Rändern des Strichs ein geringfügiges Artefaktproblem auftritt (einige Pixel des Inhalts verbleiben dort), wenn Sie diesen verwenden. Sie können es bemerken, wenn Sie hineinzoomen. Ich habe über dieses Problem berichtet hier .

EDIT: scheint behoben zu sein, aber nicht auf der IDE. Berichtet hier .

20

Versuche dies...

1.create drawable xml (custom_layout.xml):

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

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

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

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

</shape>

2.add Ihren Ansichtshintergrund

Android:background="@drawable/custom_layout"
10

Ein besserer Weg wäre:

background_activity.xml

<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:gravity="fill">
        <color Android:color="@color/black"/>
    </item>
    <item>
        <shape Android:gravity="fill">
            <solid Android:color="@color/white"/>
            <corners Android:radius="10dip"/>
            <padding Android:left="0dip" Android:top="0dip" Android:right="0dip" Android:bottom="0dip" />
        </shape>
    </item>
</layer-list>

Dies funktioniert auch unter API 21 und gibt Ihnen so etwas:

Result


Wenn Sie bereit sind, etwas mehr Aufwand zu betreiben, verwenden Sie Android.support.v7.widget.CardView mit seinem cardCornerRadius -Attribut (und setzen Sie elevation -Attribut auf 0dp, um Begleitmaterialien zu entfernen Schlagschatten mit der cardView). Dies funktioniert auch ab einer API-Stufe von nur 15.

5
Abdul Wasae

Wenn Sie Ihr Layout abgerundet gestalten möchten, ist es am besten, CardView zu verwenden, da es viele Funktionen bietet, die das Design schön machen.

<Android.support.v7.widget.CardView
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    card_view:cardCornerRadius="5dp">
      <LinearLayout
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content">

            <TextView
                Android:layout_width="0dp"
                Android:layout_height="wrap_content"
                Android:layout_weight=".3"
                Android:text="@string/quote_code"
                Android:textColor="@color/white"
                Android:textSize="@dimen/text_head_size" />
      </LinearLayout>
</Android.support.v7.widget.CardView>

Mit dieser card_view: cardCornerRadius = "5dp" können Sie den Radius ändern.

5

Verwenden Sie CardView, um abgerundete Kanten für beliebige Layouts zu erhalten. Verwenden Sie card_view: cardCornerRadius = "5dp" für die Kartenansicht, um abgerundete Layoutkanten zu erhalten.

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
  xmlns:card_view="http://schemas.Android.com/apk/res-auto"
  Android:layout_width="match_parent"
  Android:layout_height="match_parent"
  Android:orientation="vertical">

      <Android.support.v7.widget.CardView
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        card_view:cardCornerRadius="5dp">
          <LinearLayout
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:orientation="horizontal"
                Android:padding="15dp"
                Android:weightSum="1">

                <TextView
                    Android:layout_width="0dp"
                    Android:layout_height="wrap_content"
                    Android:layout_weight=".3"
                    Android:text="@string/quote_code"
                    Android:textColor="@color/white"
                    Android:textSize="@dimen/text_head_size" />

                <TextView
                    Android:layout_width="0dp"
                    Android:layout_height="wrap_content"
                    Android:layout_weight=".7"
                    Android:text="@string/quote_details"
                    Android:textColor="@color/white"
                    Android:textSize="@dimen/text_head_size" />
            </LinearLayout>
       </Android.support.v7.widget.CardView>
   </LinearLayout>
4
vishnuc156

Funktion zum programmgesteuerten Einstellen des Eckenradius

static void setCornerRadius(GradientDrawable drawable, float topLeft,
        float topRight, float bottomRight, float bottomLeft) {
    drawable.setCornerRadii(new float[] { topLeft, topLeft, topRight, topRight,
            bottomRight, bottomRight, bottomLeft, bottomLeft });
}

static void setCornerRadius(GradientDrawable drawable, float radius) {
    drawable.setCornerRadius(radius);
}

Verwenden

GradientDrawable gradientDrawable = new GradientDrawable();
gradientDrawable.setColor(Color.GREEN);
setCornerRadius(gradientDrawable, 20f);
//or setCornerRadius(gradientDrawable, 20f, 40f, 60f, 80f); 

view.setBackground(gradientDrawable);
4
Phan Van Linh
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <solid Android:color="#FFFFFF"/>
    <stroke Android:width="3dip" Android:color="#B1BCBE" />
    <corners Android:radius="10dip"/>
    <padding Android:left="3dip" Android:top="3dip" Android:right="3dip" Android:bottom="3dip" />
</shape>

@David, setzen Sie einfach den gleichen Abstand wie den Strich, damit der Rand sichtbar ist, unabhängig von der Bildgröße

3
paezinc

Die beste und einfachste Methode wäre, card_background in Ihrem Layout zu verwenden. Dies entspricht auch den Materialdesign-Richtlinien von Google. Fügen Sie dies einfach in Ihr LinearLayout ein:

Android:background="@drawable/card_background"

Fügen Sie dies Ihrem Verzeichnis hinzu und nennen Sie es card_background.xml:

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

    <item>
        <shape Android:shape="rectangle">
            <solid Android:color="#BDBDBD"/>
            <corners Android:radius="5dp"/>
        </shape>
    </item>

    <item
        Android:left="0dp"
        Android:right="0dp"
        Android:top="0dp"
        Android:bottom="2dp">
        <shape Android:shape="rectangle">
            <solid Android:color="#ffffff"/>
            <corners Android:radius="5dp"/>
        </shape>
    </item>
</layer-list>
3

Erstellen Sie Ihre XML in Drawable, layout_background.xml

 <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:Android="http://schemas.Android.com/apk/res/Android" >
      <solid Android:color="@color/your_colour" />
      <stroke
            Android:width="2dp"
            Android:color="@color/your_colour" />
      <corners Android:radius="10dp" />      
    </shape>
 <--width, color, radius should be as per your requirement-->

und dann füge dies in deinen layout.xml ein

 Android:background="@drawable/layout_background"
2

Ich habe die Antwort von @gauravsapiens mit meinen Kommentaren aufgenommen, um Ihnen einen vernünftigen Einblick in die Auswirkungen der Parameter zu geben.

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

    <!-- Background color -->
    <solid Android:color="@color/white" />

    <!-- Stroke around the background, width and color -->
    <stroke Android:width="4dp" Android:color="@color/drop_shadow"/>

    <!-- The corners of the shape -->
    <corners Android:radius="4dp"/>

    <!-- Padding for the background, e.g the Text inside a TextView will be 
    located differently -->
    <padding Android:left="10dp" Android:right="10dp" 
             Android:bottom="10dp" Android:top="10dp" />

</shape>

Wenn Sie nur eine Form erstellen möchten, die die Ecken abrundet, reicht es aus, die Polsterung und den Strich zu entfernen. Wenn Sie den Volumenkörper ebenfalls entfernen, haben Sie tatsächlich abgerundete Ecken auf einem transparenten Hintergrund erstellt.

Um faul zu sein, habe ich darunter eine Form geschaffen, die nur ein fester weißer Hintergrund mit abgerundeten Ecken ist - viel Spaß! :)

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

    <!-- Background color -->
    <solid Android:color="@color/white" />

    <!-- The corners of the shape -->
    <corners Android:radius="4dp"/>

</shape>
1
ZooMagic
 <shape xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:padding="@dimen/_10sdp"
Android:shape="rectangle">

<solid Android:color="@color/header" />

<corners
    Android:bottomLeftRadius="@dimen/_5sdp"
    Android:bottomRightRadius="@dimen/_5sdp"
    Android:topLeftRadius="@dimen/_5sdp"
    Android:topRightRadius="@dimen/_5sdp" />
0
keval patel