CircleImageView icon indicating copy to clipboard operation
CircleImageView copied to clipboard

Problems with Lollipop - black image

Open zplesac opened this issue 10 years ago • 53 comments

Hi,

I'm facing a quite interesting problem on Android Lollipop - if I set Bitmap to CircleImageView with setImageBitmap() method, it just shows black image: monosnap 2015-01-05 16-19-32

Image is selected from Gallery app, and I can view it in debug mode (bitmap is not corrupted).

Everything is working OK with default ImageView: monosnap 2015-01-05 16-23-12

This behaviour is random - some images are working correctly, some are not, and it occurs only on Android Lollipop.

Do you have any suggestions? I've checked app logs, everything is working OK - no OutOfMemory exceptions or something similar.

zplesac avatar Jan 05 '15 15:01 zplesac

Hi @zplesac!

Any specific format, dimensions or other things that seem more prone to fail? I know you hinted at the problem being random, but I'm guessing you can reproduce it with the same images? On Jan 5, 2015 4:31 PM, "zplesac" [email protected] wrote:

Hi,

I'm facing a quite interesting problem on Android Lollipop - if I set Bitmap to CircleImageView with setImageBitmap() method, it just shows black image: [image: monosnap 2015-01-05 16-19-32] https://cloud.githubusercontent.com/assets/3542084/5614966/aac92fb8-94f6-11e4-9651-fbf276d8e876.png

Image is selected from Gallery app, and I can view it in debug mode (bitmap is not corrupted).

Everything is working OK with default ImageView: [image: monosnap 2015-01-05 16-23-12] https://cloud.githubusercontent.com/assets/3542084/5615006/2a6d5eb0-94f7-11e4-8808-1da44110194f.png

This behaviour is random - some images are working correctly, some are not, and it occurs only on Android Lollipop.

Do you have any suggestions? I've checked app logs, everything is working OK - no OutOfMemory exceptions or something similar.

— Reply to this email directly or view it on GitHub https://github.com/hdodenhof/CircleImageView/issues/31.

karllindmark avatar Jan 05 '15 22:01 karllindmark

Hi @karllindmark,

I've investigated further, and it seems that problem is occurring only on high-res pictures (i.e. 2448 x 3264 - highest resolution on Nexus 4). If I downgrade camera resolution and quality, everything is working OK.

zplesac avatar Jan 06 '15 10:01 zplesac

Interesting! I'll try to reproduce the issue and look into it.

hdodenhof avatar Jan 14 '15 09:01 hdodenhof

I also have almost the same problem. I do get to see the image in the Circle Imageview but a black square is apperaing behind it. Not on every photo and sometimes it appear and sometimes not.

Works perfect on Android version lower than Lollipop. My device is also Nexus 4.

Thanks.

eshkoliGilad avatar Jan 26 '15 10:01 eshkoliGilad

I also have same problem. when building with api level 21 circle imageview with high resolution png images tends to black out with universal image loader as well as picasso. dhabbo_1bc Same image works when app is build with api level below lollipop. Thanks.

kishanraval avatar Feb 19 '15 14:02 kishanraval

I have still no idea why that happens, but I agree that it seems to be connected to the high resolution. I'll stay on it.

As a quick workaround you could just scale down the Bitmap before passing it to the CircleImageView - or better only load a scaled down version of the Bitmap into memory in the first place.

hdodenhof avatar Feb 25 '15 20:02 hdodenhof

Agreed, that could be quick & dirty solution.

zplesac avatar Feb 25 '15 20:02 zplesac

anyone found a proper solution for this problem?

msaad99 avatar Apr 09 '15 18:04 msaad99

I haven't look into this any more. But I again strongly suggest to only load a scaled-to-fit Bitmap into memory - this not only helps with the problem but is also important for preserving memory.

hdodenhof avatar Apr 28 '15 17:04 hdodenhof

The scaled down version doesn't look so good on nexus 6. I tried that. But its workable so I guess I'll just stick with that.

15100103 avatar Apr 28 '15 19:04 15100103

@15100103 What's are the dimensions of your image and the CircleImageView?

hdodenhof avatar Apr 28 '15 19:04 hdodenhof

i have the same problem, on android 5.0

gubaojian avatar Jul 08 '15 03:07 gubaojian

Oh, yes I find the The solution, you can open the 'hardwareAccelerated' on android 5.0.

accikum avatar Jul 24 '15 06:07 accikum

The Solution is here my friends: I have same problem : and I Find solution.

Solution: Set image following way if you are selecting image form gallery or camera. Do not use any library to set image or display image. use native way to display image. Thirdparty lib raise this problem... try it you can get solution. :)

Like image_profile.setImageURI(Uri.fromFile(new File("Your image local file path")));

testride2013 avatar Aug 07 '15 06:08 testride2013

I still have the same problem, I am using Picasso to load every pictures. The dimension of my picture is 300x300.

I have CircleImageView and Picasso update to the lastest version.

P.S : Used in an RecyclerView Adapter.

davroux avatar Sep 05 '15 00:09 davroux

public class CircleImageView extends ImageView {

private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;

private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
private static final int COLORDRAWABLE_DIMENSION = 2;

private static final int DEFAULT_BORDER_WIDTH = 0;
private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
private static final boolean DEFAULT_BORDER_OVERLAY = false;

private final RectF mDrawableRect = new RectF();
private final RectF mBorderRect = new RectF();

private final Matrix mShaderMatrix = new Matrix();
private final Paint mBitmapPaint = new Paint();
private final Paint mBorderPaint = new Paint();

private int mBorderColor = DEFAULT_BORDER_COLOR;
private int mBorderWidth = DEFAULT_BORDER_WIDTH;

private Bitmap mBitmap;
private BitmapShader mBitmapShader;
private int mBitmapWidth;
private int mBitmapHeight;

private float mDrawableRadius;
private float mBorderRadius;

private ColorFilter mColorFilter;

private boolean mReady;
private boolean mSetupPending;
private boolean mBorderOverlay;

public CircleImageView(Context context) {
    super(context);

    init();
}

public CircleImageView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    TypedArray a = context.obtainStyledAttributes(attrs,
            R.styleable.CircleImageView, defStyle, 0);

    mBorderWidth = a.getDimensionPixelSize(
            R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH);
    mBorderColor = a.getColor(R.styleable.CircleImageView_border_color,
            DEFAULT_BORDER_COLOR);
    mBorderOverlay = a.getBoolean(
            R.styleable.CircleImageView_border_overlay,
            DEFAULT_BORDER_OVERLAY);

    a.recycle();

    init();
}

private void init() {
    super.setScaleType(SCALE_TYPE);
    mReady = true;

    if (mSetupPending) {
        setup();
        mSetupPending = false;
    }
}

@Override
public ScaleType getScaleType() {
    return SCALE_TYPE;
}

@Override
public void setScaleType(ScaleType scaleType) {
    if (scaleType != SCALE_TYPE) {
        throw new IllegalArgumentException(String.format(
                "ScaleType %s not supported.", scaleType));
    }
}

@Override
public void setAdjustViewBounds(boolean adjustViewBounds) {
    if (adjustViewBounds) {
        throw new IllegalArgumentException(
                "adjustViewBounds not supported.");
    }
}

@Override
protected void onDraw(Canvas canvas) {
    if (getDrawable() == null) {
        return;
    }

    canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius,
            mBitmapPaint);
    if (mBorderWidth != 0) {
        canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius,
                mBorderPaint);
    }
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    setup();
}

public int getBorderColor() {
    return mBorderColor;
}

public void setBorderColor(int borderColor) {
    if (borderColor == mBorderColor) {
        return;
    }

    mBorderColor = borderColor;
    mBorderPaint.setColor(mBorderColor);
    invalidate();
}

public void setBorderColorResource(@ColorRes int borderColorRes) {
    setBorderColor(getContext().getResources().getColor(borderColorRes));
}

public int getBorderWidth() {
    return mBorderWidth;
}

public void setBorderWidth(int borderWidth) {
    if (borderWidth == mBorderWidth) {
        return;
    }

    mBorderWidth = borderWidth;
    setup();
}

public boolean isBorderOverlay() {
    return mBorderOverlay;
}

public void setBorderOverlay(boolean borderOverlay) {
    if (borderOverlay == mBorderOverlay) {
        return;
    }

    mBorderOverlay = borderOverlay;
    setup();
}

@Override
public void setImageBitmap(Bitmap bm) {
    super.setImageBitmap(bm);
    mBitmap = bm;
    setup();
}

@Override
public void setImageDrawable(Drawable drawable) {
    super.setImageDrawable(drawable);
    mBitmap = getBitmapFromDrawable(drawable);
    setup();
}

@Override
public void setImageResource(@DrawableRes int resId) {
    super.setImageResource(resId);
    mBitmap = getBitmapFromDrawable(getDrawable());
    setup();
}

@Override
public void setImageURI(Uri uri) {
    super.setImageURI(uri);
    mBitmap = getBitmapFromDrawable(getDrawable());
    setup();
}

@Override
public void setColorFilter(ColorFilter cf) {
    if (cf == mColorFilter) {
        return;
    }

    mColorFilter = cf;
    mBitmapPaint.setColorFilter(mColorFilter);
    invalidate();
}

private Bitmap getBitmapFromDrawable(Drawable drawable) {
    if (drawable == null) {
        return null;
    }

    if (drawable instanceof BitmapDrawable) {
        return ((BitmapDrawable) drawable).getBitmap();
    }

    try {
        Bitmap bitmap;

        if (drawable instanceof ColorDrawable) {
            bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION,
                    COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
        } else {
            bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
                    drawable.getIntrinsicHeight(), BITMAP_CONFIG);
        }

        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);
        return bitmap;
    } catch (OutOfMemoryError e) {
        return null;
    }
}

private void setup() {
    if (!mReady) {
        mSetupPending = true;
        return;
    }

    if (mBitmap == null) {
        return;
    }

    mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP,
            Shader.TileMode.CLAMP);

    mBitmapPaint.setAntiAlias(true);
    mBitmapPaint.setShader(mBitmapShader);

    mBorderPaint.setStyle(Paint.Style.STROKE);
    mBorderPaint.setAntiAlias(true);
    mBorderPaint.setColor(mBorderColor);
    mBorderPaint.setStrokeWidth(mBorderWidth);

    mBitmapHeight = mBitmap.getHeight();
    mBitmapWidth = mBitmap.getWidth();

    mBorderRect.set(0, 0, getWidth(), getHeight());
    mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2,
            (mBorderRect.width() - mBorderWidth) / 2);

    mDrawableRect.set(mBorderRect);
    if (!mBorderOverlay) {
        mDrawableRect.inset(mBorderWidth, mBorderWidth);
    }
    mDrawableRadius = Math.min(mDrawableRect.height() / 2,
            mDrawableRect.width() / 2);

    updateShaderMatrix();
    invalidate();
}

private void updateShaderMatrix() {
    float scale;
    float dx = 0;
    float dy = 0;

    mShaderMatrix.set(null);

    if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width()
            * mBitmapHeight) {
        scale = mDrawableRect.height() / (float) mBitmapHeight;
        dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
    } else {
        scale = mDrawableRect.width() / (float) mBitmapWidth;
        dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
    }

    mShaderMatrix.setScale(scale, scale);
    mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left,
            (int) (dy + 0.5f) + mDrawableRect.top);

    mBitmapShader.setLocalMatrix(mShaderMatrix);
}

}

testride2013 avatar Sep 09 '15 12:09 testride2013

Same problem, does anyone know how to fix?? I use versions 2.0.0 and images 300x300px

michelelacorte avatar Oct 06 '15 22:10 michelelacorte

I have same problem with

compile 'de.hdodenhof:circleimageview:1.3.0'

on HTC One, Android 5.0.2:

screenshot_2015-10-14-18-03-32

I set the image by:

    mPhotoImageView.setImageResource(R.drawable.photo);

or in the layout file:

       <de.hdodenhof.circleimageview.CircleImageView
            android:id="@+id/photo"
            android:layout_width="96dp"
            android:layout_height="96dp"
            android:src="@drawable/photo"
            app:border_width="2dp"
            app:border_color="#FFF"
            />

The xhdpi file photo.png is 17 Kbyte and 240x240:

photo

afarber avatar Oct 14 '15 17:10 afarber

Got this at 5.1.1 in listview :( image size 177х158 ezgif com-video-to-gif People, how you deal with this bug? What you mean when saying "scale to fit". Give me a sample please!

F0RIS avatar Nov 16 '15 18:11 F0RIS

I think I found a solution in lollipop.

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

This disable hardware acceleration.

You can use this to circleimageview's parent view, profile_img_container.

Don't use this to circleimageview directly. It willl show you black outer circle.

<LinearLayout
  android:id="@+id/profile_img_container"
  android:orientation="horizontal"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:gravity="center"
  android:paddingTop="20dp"
  android:paddingBottom="20dp"
  android:fitsSystemWindows="true"
  app:layout_collapseMode="parallax">

          <de.hdodenhof.circleimageview.CircleImageView
             xmlns:app="http://schemas.android.com/apk/res-auto"
             android:id="@+id/profile_image"
             android:layout_width="96dp"
             android:layout_height="96dp"
             android:src="@drawable/profile002"
             android:layout_marginTop="20dp"
             app:civ_border_width="1dp"
             app:civ_border_color="#44000000"
             android:fitsSystemWindows="true"
             app:layout_collapseMode="parallax"/>

</LinearLayout>

soulawaker avatar Nov 17 '15 15:11 soulawaker

@soulawaker Fuck yeah))) Finally working solution!!!!! Thank you so much!! Why enybody didn't wrote this before :(i am already wrote my own simple custom circle view, and it would be pity don't use it.

F0RIS avatar Nov 18 '15 14:11 F0RIS

I'm happy to hear that. Good luck to you, Anton. :) 2015. 11. 18. 오후 11:02에 "Anton" [email protected]님이 작성:

@soulawaker https://github.com/soulawaker Fuck yeah))) Finally working solution!!!!! Thank you so much!! Why enybody didn't wrote this before :(i am already wrote my own simple custom circle view, and it would be pity don't use it.

— Reply to this email directly or view it on GitHub https://github.com/hdodenhof/CircleImageView/issues/31#issuecomment-157721755 .

soulawaker avatar Nov 20 '15 16:11 soulawaker

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

awesome solutions , this is working in my lollipop code ,

Thanks a lot

sanjaymanvani avatar Jan 13 '16 06:01 sanjaymanvani

Solution:

Wrap the CircleImageView with a layout LinearLayout or FrameLayout, set the LAYER TYPE propperty to software. That's all.

walalm avatar Jan 14 '16 22:01 walalm

Use setLayerType (int layerType, Paint paint) Refer : http://developer.android.com/reference/android/view/View.html#setLayerType(int, android.graphics.Paint) for more details

ashishjohn1908 avatar Feb 03 '16 12:02 ashishjohn1908

谢谢! android:layerType="software"

xuie0000 avatar Mar 22 '16 03:03 xuie0000

Hi All, Facing the same problem. If i add this android:layerType to the view in the xml itself. Is that works. Thank you.

santhoshadugani avatar Mar 23 '16 11:03 santhoshadugani

myView.setLayerType(View.LAYER_TYPE_SOFTWARE,NULL); this is work for my problem ,thx,but I have another problem that items have black background

kong-jing avatar Apr 27 '16 02:04 kong-jing

android:layerType="software" works perfectly

lxinghe avatar Apr 28 '16 07:04 lxinghe

Could you guys stop replying about android:layerType="software" or setLayerType(View.LAYER_TYPE_SOFTWARE,NULL)?

Because that would be just a workaround, which costs your app performance.

afarber avatar Apr 28 '16 07:04 afarber