web-dev-qa-db-fra.com

Masque ImageView avec un arrière-plan arrondi

J'ai un Custom ListView qui contient une ImageView et une TextView. Tout fonctionne bien.

Ce que je veux, c'est que l'image affichée dans la liste soit en coin arrondi. Depuis le Webservice, les images sont en forme de rectangle. Mais je veux l'afficher dans Round corner ImageView comme ci-dessous.

enter image description here

Quelqu'un peut-il me montrer comment je peux masquer l'image dans un coin arrondi? 

J'ai déjà essayé en créant le fichier extractible comme ci-dessous et en l'appliquant comme src dans ImageView. Mais rien ne fonctionne pour moi.

<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android" >
   <item>
      <shape Android:shape="oval" >
         <solid Android:color="#FFFFFF" />
         <padding
            Android:bottom="10dp"
            Android:left="10dp"
            Android:right="10dp"
            Android:top="10dp" />
         <corners Android:radius="5dp" />
      </shape>
   </item>
   <item>
      <shape Android:shape="oval" >
         <padding
            Android:bottom="5dp"
            Android:left="5dp"
            Android:right="5dp"
            Android:top="5dp" />
         <solid Android:color="#FFFFFF" />
      </shape>
   </item>
</layer-list>

Édité:

enter image description hereAidez-moi, s'il vous plaît.

Toute aide serait appréciée.

Merci

J'ai appliqué la solution ci-dessous:

<FrameLayout
    Android:id="@+id/imagemaskframe"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:padding="10dp" >

    <ImageView
        Android:id="@+id/op_ivpic"
        Android:layout_width="80dp"
        Android:layout_height="80dp"
        Android:layout_gravity="center"
        Android:scaleType="fitXY" />

    <ImageView
        Android:id="@+id/iv_mask_op"
        Android:layout_width="80dp"
        Android:layout_height="80dp"
        Android:layout_gravity="center"
        Android:adjustViewBounds="true"
        Android:scaleType="fitXY"
        Android:src="@drawable/imgmask" />

</FrameLayout>
31
GrIsHu

Je vous suggère d'utiliser une autre méthode:

Une FrameLayout et deux ImageView peuvent le faire.

<FrameLayout>
    <ImageView />  your image 
    <ImageView />  put a image which has a transparent circle in it
</FrameLayout>

votre image peut alors être vue via un cercle transparent.

17
MengMeng

Le meilleur moyen est de le faire dans Canvas en utilisant PorterDuff opérations et/ou Shaders. Supposons que votre Bitmap soit disponible et stockée dans mBitmap.

Option 1: Utilisation de Shaders.

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    // Load the bitmap as a shader to the Paint.
    final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    final Shader shader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
    Paint.setShader(shader);

    // Draw a circle with the required radius.
    final float halfWidth = canvas.getWidth()/2;
    final float halfHeight = canvas.getHeight()/2;
    final float radius = Math.max(halfWidth, halfHeight);
    canvas.drawCircle(halfWidth, halfHeight, radius, Paint);
}

Option 2: Utiliser le mode PorterDuff.

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    // Create a circular path.
    final float halfWidth = canvas.getWidth()/2;
    final float halfHeight = canvas.getHeight()/2;
    final float radius = Math.max(halfWidth, halfHeight);
    final Path path = new Path();
    path.addCircle(halfWidth, halfHeight, radius, Path.Direction.CCW);

    final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    Paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
    canvas.drawPath(path, Paint);
}

Remarque:

  1. Ce n'est pas bien de créer des objets dans des appels onDraw (). Par conséquent, vous devriez initialement avoir votre peinture et votre shader ailleurs. Cela pourrait probablement être fait lorsque vous définissez l'image bitmap sur la vue.
  2. Canvas devra peut-être être sauvegardé et restauré s'il n'est pas sauvegardé par une texture matérielle. Les idées générales autour de cela ne sont pas mentionnées ici.
  3. N'oubliez pas d'ajouter setWillNotDraw(false); au constructeur.

Références supplémentaires:

  1. https://sriramramani.wordpress.com/2012/12/21/shaders/ contient des informations sur Shaders.
  2. http://mxr.mozilla.org/mozilla-central/source/mobile/Android/base/ShapedButton.Java utilise Path pour incurver le bouton dans Firefox pour Android.
  3. http://sriramramani.wordpress.com/2012/08/27/constructing-squishy-buttons/ contient des informations sur les enregistrements Canvas, les cas de restauration et les cas spéciaux pour pré-ICS.
30
sriramramani

Je recommanderais certainement Picasso, comme d’autres. Ce morceau de code pour l'une de mes classes d'activité a fait l'affaire pour moi. Il utilisait une couleur que j'avais définie dans color.xml et une présentation simple (voir ci-dessous).

       ImageView profile_image = (ImageView) findViewById(R.id.profile_image);
       mContext = profile_image.getContext();

        // ----------------------------------------------------------------
        // apply rounding to image
        // see: https://github.com/vinc3m1/RoundedImageView
        // ----------------------------------------------------------------
        Transformation transformation = new RoundedTransformationBuilder()
                .borderColor(getResources().getColor(R.color.my_special_orange))
                .borderWidthDp(5)
                .cornerRadiusDp(50)
                .oval(false)
                .build();

        Picasso.with(mContext)
                .load("http://{some_url}.jpg")
                .fit()
                .transform(transformation)
                .into(profile_image);

Et le fichier de mise en page correspondant:

    <LinearLayout
        Android:orientation="horizontal"
        Android:layout_width="fill_parent"
        Android:layout_height="120dp"
        Android:layout_alignParentTop="true"
        Android:layout_alignParentStart="true"
        Android:padding="12dp">


        <ImageView
            Android:id="@+id/profile_image"
            Android:layout_width="80dp"
            Android:layout_height="80dp"
            Android:layout_gravity="center"/>

        <LinearLayout
            Android:orientation="vertical"
            Android:layout_width="match_parent"
            Android:layout_height="80dp"
            Android:layout_gravity="center"
            Android:padding="12dp">


            <TextView
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:textAppearance="?android:attr/textAppearanceLarge"
                Android:text="First-Name"
                Android:id="@+id/profile_first_name"
                />

            <TextView
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:textAppearance="?android:attr/textAppearanceSmall"
                Android:text="Lastname"
                Android:id="@+id/profile_last_name" />
        </LinearLayout>



        </LinearLayout>
</RelativeLayout>

Voici le résultat: 

 image

20
David Geller

A RoundedBitmapDrawable from de la bibliothèque de support v4 peut être appliqué à ImageView pour obtenir l'effet souhaité:

ImageView imageView = (ImageView)findViewById(R.id.imageView);
Bitmap avatar = BitmapFactory.decodeResource(getResources(), R.drawable.avatar);
RoundedBitmapDrawable roundDrawable = RoundedBitmapDrawableFactory.create(getResources(), avatar);
roundDrawable.setCircular(true);
imageView.setImageDrawable(roundDrawable);
13
Godfrey Duke

Une solution simple et sans fond noir !

public class CircleImageView extends ImageView
{
    public CircleImageView(Context context)
    {
        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        // Create a circular path.
        final float halfWidth = canvas.getWidth()/2;
        final float halfHeight = canvas.getHeight()/2;
        final float radius = Math.max(halfWidth, halfHeight);
        final Path path = new Path();
        path.addCircle(halfWidth, halfHeight, radius, Path.Direction.CCW);

        canvas.clipPath(path);

        super.onDraw(canvas);
    }
}
4
0x131313

Reportez-vous au code suivant, qui fait exactement ce que vous voulez.

https://github.com/vinc3m1/RoundedImageView

Comme vous l'avez dit, si vous ne voulez pas de vue personnalisée, essayez alors l'idée suivante

créer une image .png de 9 correctifs (comme un cadre photo) avec un coin arrondi et un arrière-plan transparent

puis créez une disposition relative/FrameLayout avec deux vues d'image comme suit 

<RelativeLayout ....>
   <ImageView Android:id="@+id/myImage" ..>
   <ImageView Android:id="@+id/myRoundCorner" Android:src="@drawable/myRoundCornerdFrame">
</RelativeLayout>

assurez-vous que les deux vues d'image ont les mêmes attributs, à l'exception de la source d'image, et assurez-vous également que la vue d'image qui a la source comme source myRoundCornerFrame doit être au-dessus (en haut) de la vue d'affichage.

3
Jayabal

Il suffit d’essayer Android-shape-imageview - cela devrait vous aider.

2
jimpanzer

créez un fichier xml avec le nom roundimage.xml dans le dossier drawable hdpi et essayez le code suivant. 

<?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/darker_gray" />
       <corners Android:bottomRightRadius="50dip"
        Android:bottomLeftRadius="50dip"  
        Android:topRightRadius="50dip"
        Android:topLeftRadius="50dip"/>
   </shape>

puis incluez le fichier dans le fond de votre image en tant que

Android:background="@drawable/roundimage"

Je vous demande de changer les dimensions et les couleurs selon vos besoins.

veuillez utiliser ce code

package com.company.app.utils;

import Android.graphics.Bitmap;
import Android.graphics.Canvas;
import Android.graphics.Paint;
import Android.graphics.PorterDuffXfermode;
import Android.graphics.Rect;
import Android.graphics.RectF;
import Android.graphics.Bitmap.Config;
import Android.graphics.PorterDuff.Mode;

public class ImageHelper {
    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
                .getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

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

utilisez ceci comme cela fonctionne.

si vous voulez un coin carré, utilisez ce 

public static Bitmap getRoundedCornerBitmap(Context context, Bitmap input, int pixels ,

int w , int h , boolean squareTL, boolean squareTR, boolean squareBL, boolean squareBR)
{

Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final float densityMultiplier = context.getResources().getDisplayMetrics().density;

final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, w, h);
final RectF rectF = new RectF(rect);

//make sure that our rounded corner is scaled appropriately
final float roundPx = pixels*densityMultiplier;

Paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
Paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, Paint);


//draw rectangles over the corners we want to be square
if (squareTL ){
    canvas.drawRect(0, 0, w/2, h/2, Paint);
}
if (squareTR ){
    canvas.drawRect(w/2, 0, w, h/2, Paint);
}
if (squareBL ){
    canvas.drawRect(0, h/2, w/2, h, Paint);
}
if (squareBR ){
    canvas.drawRect(w/2, h/2, w, h, Paint);
}

Paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(input, 0,0, Paint);

return output;
}

De plus, j'ai écrasé ImageView pour l'inclure afin de pouvoir le définir au format XML. Vous voudrez peut-être ajouter une partie de la logique que le super appel fait ici, mais je l’ai commentée car elle n’est pas utile dans mon cas.

@Override
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas);
    Drawable drawable = getDrawable();

    Bitmap b =  ((BitmapDrawable)drawable).getBitmap() ;
    Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

    int w = getWidth(), h = getHeight();


    Bitmap roundBitmap=CropImageView.getRoundedCornerBitmap( getContext(), 
    bitmap,10, w, h , true, false,true, false);
    canvas.drawBitmap(roundBitmap, 0,0 , null);
}
0
Abb

En développant la réponse de sriramramani (y compris le correctif pour fond noir), voici mon simple ImageView dans son intégralité:

public class ExampleImageView extends ImageView {
  public ExampleImageView(Context context) {
    super(context);

    init();
  }

  public ExampleImageView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);

    init();
  }

  public ExampleImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);

    init();
  }

  void init() {
    setWillNotDraw(false);
  }

  @Override
  protected void onDraw(Canvas canvas) {

    int count = canvas.saveLayer(0, 0, getWidth(), getHeight(), null,
            Canvas.MATRIX_SAVE_FLAG |
                    Canvas.CLIP_SAVE_FLAG |
                    Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
                    Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
                    Canvas.CLIP_TO_LAYER_SAVE_FLAG);

    super.onDraw(canvas);

    // Create a circular path.
    final float halfWidth = canvas.getWidth()/2;
    final float halfHeight = canvas.getHeight()/2;
    final float radius = Math.max(halfWidth, halfHeight);
    final Path path = new Path();
    path.addCircle(halfWidth, halfHeight, radius, Path.Direction.CCW);

    final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    Paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
    canvas.drawPath(path, Paint);

    canvas.restoreToCount(count);
  }
}

Une chose si je supprime cette ligne:

setWillNotDraw(false);

Tout fonctionne toujours. Vous ne savez pas si c'est nécessaire?

0
mmd1080

voici ce que j'ai fait .. mais mon bg img était rectangle.

        ImageView ivLogo;
        ivLogo=(ImageView)fragment.mRoot.findViewById(R.id.iv_offer_logo);

puis en fixant l'image, 

      if(response.result.Partner.logo_url != null &&                 !response.result.Partner.logo_url.equals("")){
                 ivLogo.setPadding(3,3,3,3);
               DisplayImageOptions options =
                 WWFunctions.getDisplayImage(0);
            ImageLoader imageLoader = ImageLoader.getInstance();
                    imageLoader.init(ImageLoaderConfiguration.createDefault(mOfferDetailsFragment.getActivity() ));
          imageLoader.displayImage(response.result.Partner.logo_url, ivLogo, options);
        }
0
Prachi

Pour ceux qui utilisent déjà Glide, vous pouvez obtenir l'effet avec RequestOptions :

RequestOptions requestOptions = new RequestOptions();
requestOptions = requestOptions.transforms(new CenterCrop(), new RoundedCorners(radiusInPixels));
Glide.with(context)
    .load(imageUrl)
    .apply(requestOptions)
    .into(imageView);
0
rednuht