web-dev-qa-db-de.com

Maske ImageView mit Hintergrund der runden Ecke

Ich habe einen Custom ListView, der eine ImageView und eine TextView enthält. Alles funktioniert gut.

Was ich möchte ist, dass das Bild in der Liste in der runden Ecke angezeigt wird. Vom Webservice bekomme ich die Bilder in Rechteckform. Aber ich möchte es in Round corner ImageView wie unten anzeigen.

enter image description here

Kann mir jemand zeigen, wie ich das Bild in einer runden Ecke maskieren kann? 

Ich habe bereits versucht, die zeichnende Datei wie unten beschrieben zu erstellen und als src in ImageView anzuwenden. Aber nichts funktioniert für mich.

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

BEARBEITET:

enter image description hereBitte hilf mir.

Jede Hilfe wird geschätzt.

Vielen Dank

Ich habe folgende Lösung angewendet:

<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

Ich empfehle Ihnen eine andere Methode zu verwenden:

Eine FrameLayout und zwei ImageView können es tun.

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

dann kann Ihr Bild über einen transparenten Kreis gesehen werden.

17
MengMeng

Am besten tun Sie dies in Canvas mit PorterDuff-Operationen und/oder Shaders. Angenommen, Ihre Bitmap ist verfügbar und in mBitmap gespeichert.

Option 1: Shader verwenden.

@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: Verwenden des PorterDuff-Modus.

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

Hinweis:

  1. Es ist nicht gut, Objekte in onDraw () - Aufrufen zu erstellen. Daher sollten Sie Paint und Shader an einem anderen Ort haben. Möglicherweise ist dies möglich, wenn Sie die Bild-Bitmap auf die Ansicht setzen.
  2. Canvas muss möglicherweise gespeichert und wiederhergestellt werden, wenn sie nicht durch eine Hardwaretextur gesichert ist. Die allgemeinen Ideen dazu werden hier nicht erwähnt.
  3. Denken Sie daran, dem Konstruktor setWillNotDraw(false); hinzuzufügen.

Zusätzliche Referenzen:

  1. https://sriramramani.wordpress.com/2012/12/21/shaders/ enthält Informationen zu Shaders.
  2. http://mxr.mozilla.org/mozilla-central/source/mobile/Android/base/ShapedButton.Java verwendet Path, um die Schaltfläche in Firefox für Android zu verwenden.
  3. http://sriramramani.wordpress.com/2012/08/27/constructing-squishy-buttons/ enthält Informationen zum Speichern, Wiederherstellen und Sonderfällen von Canvas für das ICS vor dem ICS.
30
sriramramani

Ich würde Picasso auf jeden Fall empfehlen, wie es andere tun. Dieses bisschen Code für eine meiner Aktivitätsklassen hat mir geholfen. Es verwendete eine Farbe, die ich in color.xml definiert hatte, und ein einfaches Layout (siehe unten).

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

Und die entsprechende Layoutdatei:

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

Hier ist das Ergebnis: 

 image

20
David Geller

Eine RoundedBitmapDrawable aus der v4 Support Library kann auf eine ImageView angewendet werden, um den gewünschten Effekt zu erzielen:

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

Eine einfache Lösung und ohne schwarzen Hintergrund !

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

Verweisen Sie auf den folgenden Code, der genau das tut, was Sie möchten.

https://github.com/vinc3m1/RoundedImageView

Wie Sie sagten, wenn Sie keine benutzerdefinierte Ansicht möchten, versuchen Sie die folgende Idee

erstellen Sie ein 9-Patch-Bild (z. B. einen Fotorahmen) mit abgerundeter Ecke und transparentem Hintergrund

erstellen Sie anschließend Relatives Layout/FrameLayout mit zwei Bildansichten wie folgt 

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

stellen Sie sicher, dass beide Bildansichten mit Ausnahme der Bildquelle dieselben Attribute aufweisen, und stellen Sie außerdem sicher, dass die Bildansicht, deren Quelle myRoundCornerFrame hat, über der anderen Bildansicht (oben) liegen sollte.

3
Jayabal

Probieren Sie einfach Android-Shape-Bildansicht - es sollte Ihnen helfen.

2
jimpanzer

erstellen Sie eine XML-Datei mit dem Namen "roundimage.xml" im Zeichnungsordner "hdpi" und versuchen Sie den folgenden Code. 

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

fügen Sie dann die Datei als Hintergrundbild in Ihren Bildhintergrund ein

Android:background="@drawable/roundimage"

Ich bitte Sie, die Maße und Farben entsprechend Ihren Anforderungen zu ändern.

bitte verwenden Sie diesen 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;
    }
}

verwenden Sie dies, da dies funktioniert.

wenn Sie einen quadratischen Winkel wünschen, verwenden Sie diesen Befehl 

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

Außerdem habe ich ImageView überschrieben, um dies in xml zu definieren. Vielleicht möchten Sie etwas von der Logik hinzufügen, die der Super-Aufruf hier macht, aber ich habe es kommentiert, da es in meinem Fall nicht hilfreich ist.

@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

Um die Antwort von sriramramani (einschließlich des Fixes für schwarzen Hintergrund) zu erweitern, ist hier meine einfache ImageView-Version:

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

Eine Sache, wenn ich diese Zeile entferne:

setWillNotDraw(false);

Alles funktioniert noch. Nicht sicher, ob es benötigt wird?

0
mmd1080

hier, was ich getan habe ... aber mein bg img war rechteck.

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

dann beim Einstellen des Bildes, 

      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

Für diejenigen, die Glide bereits verwenden, können Sie den Effekt mit RequestOptions erzielen:

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