Comment faire une vue dans android avec des coins arrondis

J’essaie de faire une vue dans android avec des bords arrondis. La solution que j’ai trouvée jusqu’à présent consiste à définir une forme avec des coins arrondis et à l’utiliser comme arrière-plan de cette vue.

Voici ce que j’ai fait, définissez un dessin comme indiqué ci-dessous

  

Maintenant, j’ai utilisé ceci comme arrière-plan pour ma mise en page comme ci-dessous

  

Cela fonctionne parfaitement bien, je peux voir que la vue a des bords arrondis.

Mais ma mise en page a beaucoup d’autres vues enfants. Dites une ImageView ou une MapView. Lorsque je place un ImageView à l’intérieur de la mise en page ci-dessus, les coins de l’image ne sont pas tronqués / recadrés, mais apparaissent pleins.

J’ai vu d’autres solutions pour le faire fonctionner comme celui expliqué ici .

Mais existe-t-il une méthode pour définir des coins arrondis pour une vue et toutes ses vues enfants sont contenues dans cette vue principale aux coins arrondis?

Merci.

Une autre approche consiste à créer une classe de présentation personnalisée comme celle ci-dessous. Cette disposition dessine d’abord son contenu sur une image bitmap hors-champ, masque l’image bitmap hors champ avec un rectangle arrondi, puis dessine l’image bitmap hors-champ sur la canvas réelle.

Je l’ai essayé et cela semble fonctionner (du moins pour mon testcase simple). Cela affectera bien sûr les performances par rapport à une mise en page régulière.

 package com.example; import android.content.Context; import android.graphics.*; import android.util.AtsortingbuteSet; import android.util.DisplayMesortingcs; 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, AtsortingbuteSet attrs) { super(context, attrs); init(context, attrs, 0); } public RoundedCornerLayout(Context context, AtsortingbuteSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); } private void init(Context context, AtsortingbuteSet attrs, int defStyle) { DisplayMesortingcs mesortingcs = context.getResources().getDisplayMesortingcs(); cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, mesortingcs); 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; } } 

Utilisez ceci comme une mise en page normale:

     

shape.xml

       

et à l’intérieur de vous

    

Ou vous pouvez utiliser un android.support.v7.widget.CardView comme ceci:

    

Si vous rencontrez des problèmes lors de l’ajout d’écouteurs tactiles à la mise en page. Utilisez cette mise en page en tant que mise en page parent.

 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.AtsortingbuteSet; import android.util.DisplayMesortingcs; 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, AtsortingbuteSet attrs) { super(context, attrs); init(context, attrs, 0); } public RoundedCornerLayout(Context context, AtsortingbuteSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); } private void init(Context context, AtsortingbuteSet attrs, int defStyle) { DisplayMesortingcs mesortingcs = context.getResources().getDisplayMesortingcs(); cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, mesortingcs); 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); } } 

comme

    ... your child goes here   

créer un fichier xml round.xml dans un dossier pouvant être dessiné

    

puis utilisez round.xml comme arrière-plan pour les éléments. Ensuite, cela donnera des coins arrondis

Dans Android L, vous pourrez simplement utiliser View.setClipToOutline pour obtenir cet effet. Dans les versions précédentes, il était impossible de découper simplement le contenu d’un ViewGroup aléatoire dans une certaine forme.

Vous devrez penser à quelque chose qui vous donnerait un effet similaire:

  • Si vous n’avez besoin que de coins arrondis dans ImageView, vous pouvez utiliser un shader pour «peindre» l’image sur la forme que vous utilisez comme arrière-plan. Jetez un oeil à cette bibliothèque pour un exemple.

  • Si vous avez vraiment besoin que tous les enfants soient coupés, vous pouvez peut-être revoir votre mise en page? Un avec un fond de la couleur que vous utilisez, et un «trou» rond au milieu? Vous pouvez en fait créer un ViewGroup personnalisé qui dessine cette forme sur tous les enfants remplaçant la méthode onDraw.

La réponse de Jaap van Hengstum fonctionne très bien, mais je pense que cela coûte cher et si nous appliquons cette méthode sur un bouton, par exemple, l’effet tactile est perdu car la vue est rendue en tant que bitmap.

Pour moi, la meilleure méthode et la plus simple consiste à appliquer un masque sur la vue, comme ça:

 @Override protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) { super.onSizeChanged(width, height, oldWidth, oldHeight); float cornerRadius = ; 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); } 

suivez ce tutoriel et toute la discussion en dessoushttp://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/

d’après ce post écrit par Guy Romain, l’un des principaux développeurs de la boîte à outils Android, il est possible de faire un conteneur (et toutes ses vues enfants) avec des coins arrondis, mais il a expliqué que cela coûtait trop cher (à partir des performances de problèmes de rendu).

Je vous recommande d’aller en fonction de son post, et si vous voulez des coins arrondis, alors implémentez des coins arrondis ImageView selon ce post. ensuite, vous pouvez le placer dans un conteneur avec n’importe quel arrière-plan et vous obtiendrez l’effet souhaité.

c’est aussi ce que j’ai fait aussi éventuellement.

Le lien du didacticiel que vous avez fourni semble suggérer que vous devez définir les propriétés layout_width et layout_height de vos éléments enfants sur match_parent.

  

essayez cette propriété avec votre disposition linéaire cela vous aidera
outils: context = “. youractivity”

Différence avec la réponse de Jaap van Hengstum:

  1. Utilisez BitmapShader au lieu de masquer le bitmap.
  2. Créez le bitmap seulement une fois.
 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, AtsortingbuteSet attrs) { super(context, attrs); init(); } public RoundedFrameLayout(Context context, AtsortingbuteSet 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); } } 
 public class RoundedCornerLayout extends FrameLayout { private double mCornerRadius; public RoundedCornerLayout(Context context) { this(context, null, 0); } public RoundedCornerLayout(Context context, AtsortingbuteSet attrs) { this(context, attrs, 0); } public RoundedCornerLayout(Context context, AtsortingbuteSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); } private void init(Context context, AtsortingbuteSet attrs, int defStyle) { DisplayMesortingcs mesortingcs = context.getResources().getDisplayMesortingcs(); 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); } } 

Le CardView fonctionné pour moi dans l’API 27 dans Android Studio 3.0.1. Le colorPrimary été référencé dans le fichier res/values/colors.xml et n’est qu’un exemple. Pour le layout_width de 0dp il s’étendra à la largeur du parent. Vous devrez configurer les contraintes et width / height selon vos besoins.

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

Utilisez shape dans xml avec rectangle.set la propriété de bottom ou upper radius comme want.then appliquez ce xml comme arrière-plan à votre vue …. ou … utilisez des dégradés pour le faire à partir du code.