Loupe

Android - un container avec des coins arrondis

Il est souvent intéressant de dessiner un élément ayant des coins arrondis. Avec Xamarin Forms, on pourrait utiliser la propriété CornerRadius très facilement, mais elle n'existe pas en Android natif. Dans cet article, nous verrons comment créer un contrôle dérivant de FrameLayout pour nous apporter ce comportement partout où cela est nécessaire.

Pour réaliser cette prouesse, on dérive de FrameLayout et on va surcharger la méthode Draw (même pas besoin de définir un style personnalisé comme dans un précédent article !). Dans celle-ci, on créé un bitmap sur lequel on demande à notre contrôle FrameLayout de base de dessiner son contenu. On appliquera ensuite un mask pour ne garder que le rectangle arrondi (une sorte de masque d'écrêtage de Photoshop) et c'est ce qu'on dessinera.

 public class RoundedCornerLayout : FrameLayout {
   private static float CORNER_RADIUS = 8.0f;

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

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

   public RoundedCornerLayout (Context context, IAttributeSet attrs) 
   : base (context, attrs) {
   init (context, attrs, 0);
   }

   public RoundedCornerLayout (Context context, IAttributeSet attrs, int defStyle) 
   : base (context, attrs, defStyle) {
   init (context, attrs, defStyle);
   }

   private void init (Context context, IAttributeSet attrs, int defStyle) {
   DisplayMetrics metrics = context.Resources.DisplayMetrics;
   cornerRadius = TypedValue.ApplyDimension (ComplexUnitType.Dip, CORNER_RADIUS, metrics);

   paint = new Paint (PaintFlags.AntiAlias);

   maskPaint = new Paint (PaintFlags.AntiAlias | PaintFlags.AntiAlias);
   maskPaint.SetXfermode (new PorterDuffXfermode (PorterDuff.Mode.Clear));

   SetWillNotDraw (false);
   }

   public override void Draw (Canvas canvas) {
   Bitmap offscreenBitmap = Bitmap.CreateBitmap (
     canvas.Width,
     canvas.Height,
     Bitmap.Config.Argb8888);
   Canvas offscreenCanvas = new Canvas (offscreenBitmap);

   base.Draw (offscreenCanvas);

   if (maskBitmap == null) {
     maskBitmap = CreateMask (canvas.Width, canvas.Height);
   }

   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.Alpha8);
   Canvas canvas = new Canvas (mask);

   Paint paintC = new Paint (PaintFlags.AntiAlias);
   paintC.Color = Color.White;

   canvas.DrawRect (0, 0, width, height, paintC);

   paintC.SetXfermode (new PorterDuffXfermode (PorterDuff.Mode.Clear));
   canvas.DrawRoundRect (new RectF (0, 0, width, height),
     cornerRadius, cornerRadius, paintC);

   return mask;
   }
 }

Une fois celui-ci défini on pourra l'utiliser assez facilement dans nos Layouts.

<?xml version="1.0" encoding="UTF-8" ?>
<MonNampespace.RoundedCornerLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:id="@+id/custom_toast_container"
	android:orientation="vertical"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:padding="12dp"
	android:background="#DAAA">

</MonNampespace.RoundedCornerLayout>

Je m'en sers par exemple pour afficher des toasts notifications avec un contenu personnalisée (titre + contenu) : 
Screenshot_1581600635.png

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus