web-dev-qa-db-fra.com

Comment faire une mise en page avec des coins arrondis ..?

Comment puis-je faire une mise en page avec des coins arrondis? Je souhaite appliquer des angles arrondis à ma LinearLayout.

445
Addy

1: Définir layout_bg.xml dans 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: Ajoutez layout_bg.xml comme arrière-plan de votre mise en page

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

Pour API 21+, utilisez les vues de clip

Des contours arrondis ont été ajoutés à la classe View de l'API 21. Voir ceci doc d'apprentissage ou this référence pour plus d'informations.

Cette fonctionnalité intégrée facilite la mise en œuvre des angles arrondis. Il fonctionne sur n’importe quelle vue ou disposition et prend en charge un découpage approprié.

Voici ce qu'il faut faire:

  • Créez une forme arrondie pouvant être dessinée et définissez-la comme arrière-plan de votre vue: Android:background="@drawable/round_outline"
  • Selon la documentation, tout ce que vous avez à faire est la suivante: Android:clipToOutline="true"

Malheureusement, il semble y avoir n bogue et cet attribut XML n'est actuellement pas reconnu. Heureusement, nous pouvons définir le découpage en Java:

  • Dans votre activité ou fragment: View.setClipToOutline(true)

A quoi ça ressemble:

enter image description here

Remarque spéciale sur ImageViews

setClipToOutline() ne fonctionne que lorsque l'arrière-plan de la vue est défini sur une forme pouvant être dessinée. Si cette forme d'arrière-plan existe, View considère le contour de l'arrière-plan comme des bordures à des fins de découpage et d'observation.

Cela signifie que si vous souhaitez arrondir les angles d'un ImageView avec setClipToOutline(), votre image doit provenir de Android:src au lieu de Android:background (car l'arrière-plan est utilisé pour la forme arrondie). Si vous DEVEZ utiliser l’arrière-plan pour définir votre image au lieu de src, vous pouvez utiliser cette solution de contournement des vues imbriquées:

  • Créez une mise en page externe avec l'arrière-plan ajusté à votre forme, dessinable
  • Enroulez cette disposition autour de votre ImageView (sans remplissage)
  • ImageView (y compris tout ce qui se trouve dans la mise en page) sera maintenant coupé à la forme arrondie de la mise en page externe.
96
hungryghost

Voici une copie d'un fichier XML pour créer un dessin avec un fond blanc, une bordure noire et des coins arrondis:

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

enregistrez-le sous forme de fichier xml dans le répertoire pouvant être dessiné. Utilisez-le comme vous utiliseriez n'importe quel fond dessiné (icône ou fichier de ressources) en utilisant son nom de ressource (R.drawable.votre_nom_xml)

59
kyogs

Utilisez CardView dans Android bibliothèque de support v7. Bien que ce soit un peu lourd, il résout tous les problèmes, et assez facilement. Contrairement à la méthode définie pour l’arrière-plan, elle peut découper les sous-vues avec succès.

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

J'ai fait comme ça:

Vérifiez la capture d'écran:

Relative layout Background

Créez un fichier pouvant être dessiné portant le nom custom_rectangle.xml dans un dossier pouvant être dessiné :

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

Appliquez maintenant l’arrière-plan du rectangle sur la vue :

mView.setBackground(R.drawlable.custom_rectangle);

Fait

26
Hiren Patel

Je pense qu'une meilleure façon de le faire est de fusionner 2 choses:

  1. faire un bitmap de la mise en page, comme indiqué ici .

  2. faire un arrondi tirable de la bitmap, comme indiqué ici

  3. définir le dessinable sur une imageView.

Cela permettra de gérer les cas que d'autres solutions n'ont pas réussi à résoudre, comme un contenu comportant des angles.

Je pense que c'est aussi un peu plus convivial pour le GPU, car il montre une seule couche au lieu de 2.

La seule meilleure solution consiste à créer une vue totalement personnalisée, mais cela prend beaucoup de code et peut prendre beaucoup de temps. Je pense que ce que j'ai suggéré ici est le meilleur des deux mondes.

Voici un extrait de la façon dont cela peut être fait:

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: a trouvé une alternative de Nice, basée sur la bibliothèque "RoundKornersLayouts" . Avoir une classe qui sera utilisée pour toutes les classes de mise en page que vous souhaitez étendre, à arrondir:

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

}

Ensuite, dans chacune de vos classes de mise en page personnalisées, ajoutez un code similaire à celui-ci:

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

}

Si vous souhaitez supporter les attributs, utilisez ceci comme écrit dans la bibliothèque:

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

Une autre alternative, qui pourrait être plus facile pour la plupart des utilisations: utilisez MaterialCardView. Il permet de personnaliser les coins arrondis, la couleur et la largeur du trait, ainsi que l’altitude.

Exemple:

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

Et le résultat:

enter image description here

Notez qu'il y a un léger problème d'artefacts sur les bords du trait (y laisse quelques pixels du contenu), si vous l'utilisez. Vous pouvez le remarquer si vous effectuez un zoom avant. J'ai signalé ce problème ici .

EDIT: semble être corrigé, mais pas sur l'IDE. Signalé ici .

20

Essaye ça...

1.créer XML dessinable (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 votre vue de fond

Android:background="@drawable/custom_layout"
10

Une meilleure façon de le faire serait:

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>

Cela fonctionnera également sous API 21 et vous donnera quelque chose comme ceci:

Result


Si vous souhaitez faire un peu plus d'effort pour un meilleur contrôle, utilisez Android.support.v7.widget.CardView avec son attribut cardCornerRadius (et définissez l'attribut elevation sur 0dp pour vous en débarrasser. ombre portée avec le cardView). En outre, cela fonctionnera à partir du niveau 15 de l'API.

5
Abdul Wasae

Si vous souhaitez rendre votre mise en page arrondie, il est préférable d’utiliser CardView, qui offre de nombreuses fonctionnalités pour rendre le design plus beau.

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

Avec cette card_view: cardCornerRadius = "5dp", vous pouvez changer le rayon.

5
Farruh Habibullaev

Utilisez CardView pour obtenir des bords arrondis pour n’importe quelle mise en page. Utilisez card_view: cardCornerRadius = "5dp" pour que cardview obtienne des bords de mise en page arrondis.

<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

Fonction pour définir le rayon de coin par programmation

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

En utilisant

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, il suffit de mettre la même valeur de remplissage que le contour, pour que la bordure puisse être visible, taille de l'image sans égard

3
paezinc

La méthode la plus simple et la meilleure consiste à utiliser card_background dessable dans votre mise en page. Cela suit également les directives de conception de matériaux de Google. Incluez simplement ceci dans votre LinearLayout:

Android:background="@drawable/card_background"

Ajoutez ceci à votre répertoire dessinable et nommez-le 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
Divyanshu Maithani

Créez votre XML dans 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-->

et ensuite, ajoutez ceci dans votre layout.xml

 Android:background="@drawable/layout_background"
2
Bapusaheb Shinde

J'ai pris @gauravsapiens répondre avec mes commentaires à l'intérieur pour vous donner une appréhension raisonnable de ce que les paramètres vont affecter.

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

Si vous souhaitez simplement créer une forme qui arrondit les angles, supprimez le rembourrage et le trait. Si vous supprimez également le solide, vous aurez effectivement créé des coins arrondis sur un fond transparent.

Par souci de paresse, j'ai créé une forme dessous, qui est juste un fond blanc uni avec des coins arrondis - profitez-en! :)

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