risposta-alla-domanda-sullo-sviluppo-web-bd.com

Come rendere il layout con angoli arrotondati ..?

Come posso creare un layout con angoli arrotondati? Voglio applicare gli angoli arrotondati al mio LinearLayout.

421
Addy

1: Definisci layout_bg.xml in drawable:

<?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: aggiungi layout_bg.xml come sfondo al tuo layout

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

Per API 21+, Usa clip viste

Il ritaglio di contorni arrotondato è stato aggiunto alla classe View nell'API 21. Vedi questo training doc o this reference per maggiori informazioni.

Questa caratteristica integrata rende gli angoli arrotondati molto facili da implementare. Funziona su qualsiasi vista o layout e supporta il clipping appropriato.

Ecco cosa fare:

  • Crea una forma arrotondata disegnabile e impostala come sfondo della tua vista: Android:background="@drawable/round_outline"
  • Secondo la documentazione, tutto ciò che devi fare è questo: Android:clipToOutline="true"

Sfortunatamente, sembra che ci sia un bug e questo attributo XML attualmente non è riconosciuto. Fortunatamente, possiamo impostare il clipping in Java:

  • Nella tua attività o frammento: View.setClipToOutline(true)

Che aspetto ha:

enter image description here

Nota speciale su ImageViews

setClipToOutline() funziona solo quando lo sfondo della vista è impostato su una forma disegnabile. Se esiste questa forma di sfondo, Visualizza considera il contorno dello sfondo come i bordi per gli scopi di ritaglio e ombreggiatura.

Ciò significa che se si desidera arrotondare gli angoli di un ImageView con setClipToOutline(), l'immagine deve provenire da Android:src anziché da Android:background (poiché lo sfondo viene utilizzato per la forma arrotondata). Se DEVI utilizzare lo sfondo per impostare l'immagine anziché src, puoi utilizzare questa soluzione alternativa per le viste nidificate:

  • Crea un layout esterno con lo sfondo impostato per disegnare la forma
  • Avvolgi il layout attorno a ImageView (senza padding)
  • ImageView (incluso qualsiasi altra cosa nel layout) verrà ora ritagliato sulla forma arrotondata del layout esterno.
85
hungryghost

Ecco una copia di un file XML per creare un drawable con uno sfondo bianco, un bordo nero e angoli arrotondati:

 <?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>

salvalo come un file xml nella directory drawable, usalo come se dovessi usare uno sfondo disegnabile (icona o file di risorse) usando il suo nome risorsa (R.drawable.your_xml_name)

56
kyogs

Ho fatto in questo modo:

Controlla Screenshot:

 Relative layout Background

Crea drawable file chiamato con custom_rectangle.xml in drawable folder:

<?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>

Ora applica Sfondo rettangolo on Visualizza :

mView.setBackground(R.drawlable.custom_rectangle);

Fatto

25
Hiren Patel

Usa CardView nella libreria di supporto per Android v7. Anche se è un po 'pesante, risolve tutti i problemi, e abbastanza facile. Non come il metodo set drawable in background, potrebbe ritagliare i subviews con successo.

<?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>
24
Evan JIANG

Penso che un modo migliore per farlo sia unire 2 cose:

  1. crea una bitmap del layout, come mostrato in here .

  2. fai un disegno arrotondato dalla bitmap, come mostrato in here

  3. imposta il drawable su un imageView.

Questo gestirà i casi che altre soluzioni non sono riuscite a risolvere, come ad esempio avere contenuti che hanno angoli.

Penso che sia anche un po 'più compatibile con la GPU, in quanto mostra un singolo livello invece di 2.

L'unico modo migliore è creare una vista totalmente personalizzata, ma è un sacco di codice e potrebbe richiedere molto tempo. Penso che quello che ho suggerito qui sia il meglio di entrambi i mondi.

Ecco un frammento di come può essere fatto:

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

}

EDIT: trovato una bella alternativa, basata su libreria "RoundKornersLayouts" . Avere una classe che verrà utilizzata per tutte le classi di layout che desideri estendere, da arrotondare:

//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()
    }

}

Quindi, in ciascuna delle tue classi di layout personalizzate, aggiungi un codice simile a questo:

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

}

Se desideri supportare gli attributi, usa questo come scritto sulla libreria:

<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>

Un'altra alternativa, che potrebbe essere più semplice per la maggior parte degli usi: utilizzare MaterialCardView. Consente di personalizzare gli angoli arrotondati, il colore e la larghezza del tratto e l'elevazione.

Esempio:

<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>

E il risultato:

 enter image description here

Si noti che c'è un leggero problema di artefatti ai bordi del tratto (lascia lì alcuni pixel del contenuto), se lo si utilizza. Si può notare se si ingrandisce. Ho segnalato il problema here .

20

Prova questo...

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 il tuo sfondo vista

Android:background="@drawable/custom_layout"
10

Un modo migliore per farlo sarebbe:

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>

Questo funzionerà anche sotto l'API 21, e ti darà qualcosa di simile a questo:

 Result


Se sei disposto a fare un po 'più di sforzo per un controllo migliore, usa Android.support.v7.widget.CardView con il suo attributo cardCornerRadius (e imposta l'attributo elevation a 0dp per eliminare ogni ombra di accompagnamento con cardView). Inoltre, funzionerà da livello API a partire da 15.

5
Abdul Wasae

Se si desidera arrotondare il layout, è preferibile utilizzare CardView, che ha fornito molte funzioni per rendere il design più bello.

<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>

Con questo card_view: cardCornerRadius = "5dp", puoi cambiare il raggio.

5

Usa CardView per ottenere bordi arrotondati per qualsiasi layout. Usa card_view: cardCornerRadius = "5dp" per cardview per ottenere bordi del layout arrotondati.

<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
<?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, metti semplicemente il padding con lo stesso valore del tratto, in modo che il bordo possa essere visibile, dimensioni dell'immagine senza riguardo

3
escar

Il metodo migliore e più semplice sarebbe utilizzare card_background drawable nel proprio layout. Ciò segue anche le linee guida sulla progettazione dei materiali di Google. Basta includere questo in te LinearLayout:

Android:background="@drawable/card_background"

Aggiungi questo alla tua directory drawable e chiamalo 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

Funzione per il raggio dell'angolo impostato a livello di programmazione

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

Utilizzando

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

view.setBackground(gradientDrawable);
3
Phan Van Linh

Ho preso risposta @gauravsapiens con i miei commenti all'interno per darti una ragionevole apprensione su quali saranno i parametri che avranno effetto.

<?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>

Se stai solo cercando di creare una forma che arrotonda gli angoli, rimuoverà il padding e il tratto andrà bene. Se rimuovi il solido, in effetti avrai creato angoli arrotondati su uno sfondo trasparente.

Per il gusto di essere pigri ho creato una forma sotto, che è solo un solido sfondo bianco con angoli arrotondati - buon divertimento! :)

<?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
Create your 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-->

Finally in your layout.xml file write below line

 Android:background="@drawable/layout_background"
0
Bapusaheb Shinde
 <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