I tried To make imageview with rounded corners. But i am facing some issues. I cannot make the round corners for all 4 sides. I tried this code
Imageviewclass.class
Picasso.with(con).load(itemsArrayList.get(position).get("item_image")).transform(new Resizeimageview()).into(holder.img);
ResizeImageview.class
public class Resizeimageview implements Transformation {
#Override
public Bitmap transform(Bitmap source) {
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
source.recycle();
}
Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size / 8f;
canvas.drawRoundRect(new RectF(0, 0, source.getWidth(), source.getHeight()), r, r, paint);
squaredBitmap.recycle();
return bitmap;
}
#Override
public String key() {
return "rounded_corners";
}
}
Try replacing this line
canvas.drawRoundRect(new RectF(0, 0, source.getWidth(), source.getHeight()), r, r, paint);
with this
canvas.drawRoundRect(new RectF(0, 0, size, size), r, r, paint);
Try this :
Download the Universal Image Loader from the given link :
https://github.com/nostra13/Android-Universal-Image-Loader/wiki/Quick-Setup
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
context).build();
// Initialize ImageLoader with configuration.
ImageLoader.getInstance().init(config);
DisplayImageOptions options = new DisplayImageOptions.Builder().displayer(new RoundedBitmapDisplayer(250)).cacheOnDisc().build();
ImageLoader.getInstance().displayImage(itemsArrayList.get(position).get("item_image"), holder.img, options);
Using,
Picasso.with(activity).load(url).transform(new CircleTransform(22,12)).into(imageView); we can have rounded corners for loading image.But there is no rounded corners for placeholder nor error image?
Link which I reffered Make ImageView with Round Corner Using picasso
Picasso.with(getApplicationContext()).load(url).placeholder(setCircularImage(R.drawable.profile_sample)).error(setCircularImage(R.drawable.profile_sample)).transform(new CircleTransform()).into(ivMenuProfile);
add setCircularImage method with place holder for make placehoder in to circle view
private RoundedBitmapDrawable setCircularImage(int id) {
Resources res = getApplicationContext().getResources();
Bitmap src = BitmapFactory.decodeResource(res, id);
RoundedBitmapDrawable roundedBitmapDrawable =
RoundedBitmapDrawableFactory.create(res, src);
roundedBitmapDrawable.setCornerRadius(Math.max(src.getWidth(), src.getHeight()) / 2.0f);
return roundedBitmapDrawable;
}
add CircleTransform() with transform for change shape in to circle for load Url Image.
public class CircleTransform implements Transformation {
#Override
public Bitmap transform(Bitmap source) {
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
source.recycle();
}
Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size/2f;
canvas.drawCircle(r, r, r, paint);
squaredBitmap.recycle();
return bitmap;
}
#Override
public String key() {
return "circle";
}
}
This is not possible with Picasso. See the answers here.
I made this Custom Drawable that should clip any Drawable in circle. But with my implementation, the drawable passed is being the output in the original form not in the circular form.
public class CircularDrawable extends Drawable {
Paint mPaint,xfermodePaint;
Drawable mDrawable;
int[] vinylCenter = new int[2];
int radius;
Bitmap src;
PorterDuffXfermode xfermode;
Rect rect;
Canvas testCanvas;
public CircularDrawable(Drawable drawable) {
mDrawable = drawable;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(0xffffffff);
mPaint.setStyle(Paint.Style.FILL);
xfermodePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
xfermode=new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
xfermodePaint.setXfermode(xfermode);
testCanvas=new Canvas();
}
#Override
public void setBounds(Rect bounds) {
super.setBounds(bounds);
mDrawable.setBounds(bounds);
}
#Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
mDrawable.setBounds(left, top, right, bottom);
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
vinylCenter[0] = bounds.width() / 2;
vinylCenter[1] = bounds.height() / 2;
radius = (bounds.right - bounds.left) / 2;
src = Bitmap.createBitmap(bounds.width(), bounds.height(), Bitmap.Config.ARGB_8888);
testCanvas.setBitmap(src);
}
#Override
public void draw(Canvas canvas) {
canvas.save();
canvas.drawARGB(0, 0, 0, 0);
canvas.drawCircle(vinylCenter[0],vinylCenter[1],radius,mPaint);
mDrawable.draw(testCanvas);
canvas.drawBitmap(src,0f,0f,xfermodePaint);
}
#Override
public void setAlpha(int alpha) {/*ignored*/}
#Override
public void setColorFilter(ColorFilter colorFilter) {/*ignored*/}
#Override
public int getOpacity() {
/*ignored*/
return 0;
}
}
What is my mistake?
Also I am using a SquareImageview to display this drawable that just makes the view square in onMeasure.
This question is not meant for Circular imageview.
You already have optimized implementation for circular drawable in Support library v4:
Google reference
/**
* A Drawable that wraps a bitmap and can be drawn with rounded corners. You can create a
* RoundedBitmapDrawable from a file path, an input stream, or from a
* {#link android.graphics.Bitmap} object.
* <p>
* Also see the {#link android.graphics.Bitmap} class, which handles the management and
* transformation of raw bitmap graphics, and should be used when drawing to a
* {#link android.graphics.Canvas}.
* </p>
*/
public abstract class RoundedBitmapDrawable extends Drawable ....
The canvas doesnt have alpha channel on by default when using Porter/Duff xfermode mode (As per my experience with my this in android). That is the reason the whole image(src) is being the output. Porter/Duff xfermode acts based on Alpha Channel.
In many implementation of Circular Drawable 2 Canvas are taken, out of which one is given RGB image bitmap and other is given only alpha channel bitmap with circular mask. Porter/Duff xfermodeis applied and the result is drawn on the main canvas.
My mistake is that I am not specifying the draw function's canvas that alpha channel is to be considered on using the layer on the canvas for xfermode.
The draw function will become
#Override
public void draw(Canvas canvas) {
int sc = canvas.saveLayer(null, null,
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
);
canvas.drawCircle(vinylCenter[0],vinylCenter[1],radius,mPaint);
mDrawable.draw(testCanvas);
canvas.drawBitmap(src,0f,0f,xfermodePaint);
canvas.restoreToCount(sc);
}
Saving the Layer to indicate alpha channel with the flag and then using the xfermode. Finally restoring it to its save count.
So basically I use this method to get rounded corner images
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.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(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
but like you pointed out sometimes it does not work, well it does work, but what happens most of the time is your imageview might have its scaletype set to centerCrop and other types, what I do is I first compress my image height to the same height and width as my imageview so that the entire image will fit in the imageview and no scaling will take place or I just calculate how much of the corner height to make rounded using this function based on the height
private int calculatePercentage(int percentage, int target)
{
int k = (int)(target*(percentage/100.0f));
return k;
}
so I use my code like: new Bitmap(getRoundedCornerBitmap(bmp, calculatePercentage(5, bmp.getHeight()))); where 5 is 5 of the image height this gives me same curves for all images be it some images are bigger than others
`
For rounded imageview you can use this code
public class RoundedImageView extends ImageView {
public RoundedImageView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public RoundedImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundedImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
Bitmap b = ((BitmapDrawable) drawable).getBitmap();
Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
int w = getWidth();//, h = getHeight();
Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);
}
public static Bitmap getCroppedBitmap(Bitmap bmp, int radius)
{
Bitmap sbmp;
if (bmp.getWidth() != radius || bmp.getHeight() != radius)
sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false);
else
sbmp = bmp;
Bitmap output = Bitmap.createBitmap(sbmp.getWidth(), sbmp.getHeight(),Config.ARGB_8888);
Canvas canvas = new Canvas(output);
// final int color = 0xffa19774;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight());
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
// paint.setColor(Color.parseColor("#BAB399"));
paint.setColor(Color.parseColor("#FF0000"));
canvas.drawCircle(sbmp.getWidth() / 2 + 0.7f, sbmp.getHeight() / 2 + 0.7f, sbmp.getWidth() / 2 + 0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(sbmp, rect, rect, paint);
return output;
}
}
For circular imageview use the below code
public class RoundedImageView extends ImageView {
public RoundedImageView(Context context) {
super(context);
}
public RoundedImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundedImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
BitmapDrawable drawable = (BitmapDrawable) getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
Bitmap fullSizeBitmap = drawable.getBitmap();
int scaledWidth = getMeasuredWidth();
int scaledHeight = getMeasuredHeight();
/*
* scaledWidth = scaledWidth/2; scaledHeight = scaledHeight/2;
*/
Bitmap mScaledBitmap;
if (scaledWidth == fullSizeBitmap.getWidth()
&& scaledHeight == fullSizeBitmap.getHeight()) {
mScaledBitmap = fullSizeBitmap;
} else {
mScaledBitmap = Bitmap.createScaledBitmap(fullSizeBitmap,
scaledWidth, scaledHeight, true /* filter */);
}
// Bitmap roundBitmap = getRoundedCornerBitmap(mScaledBitmap);
// Bitmap roundBitmap = getRoundedCornerBitmap(getContext(),
// mScaledBitmap, 10, scaledWidth, scaledHeight, false, false,
// false, false);
// canvas.drawBitmap(roundBitmap, 0, 0, null);
Bitmap circleBitmap = getCircledBitmap(mScaledBitmap);
canvas.drawBitmap(circleBitmap, 0, 0, null);
}
public 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;
}
Bitmap getCircledBitmap(Bitmap bitmap) {
Bitmap result = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
int color = Color.BLUE;
Paint paint = new Paint();
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
// canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
bitmap.getHeight() / 2, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return result;
}
}
Try disabling hardware acceleration if you are using PorterDuffXfermode:
In manifest for whole activity:
<activity android:hardwareAccelerated="false" />
Or on a specific view on which you are using xfermode:
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
This question already has an answer here:
How to create a circular ImageView in Android? [duplicate]
(1 answer)
Closed 7 years ago.
I know there are a lot of examples on this question but l still couldn't finish following them, Is there an easy way how to make circle ImageView on android studio?
You not need to use any external libraries for make ImageView circle. Use this class for make your ImageView circle.
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
public class CircleImage {
Context context;
public RoundImage(Context context) {
this.context = context;
}
public Bitmap transform(Bitmap source) {
try {
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap
.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
// source.recycle();
}
Bitmap bitmap = Bitmap.createBitmap(size, size,
squaredBitmap.getConfig());
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader = new BitmapShader(squaredBitmap,
BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
// canvas.drawArc(rectf, -90, 360, false, lightRed);
// squaredBitmap.recycle();
return bitmap;
} catch (Exception e) {
// TODO: handle exception
}
return BitmapFactory.decodeResource(context.getResources(),
R.drawable.ic_launcher);
}
}
And use your ImageView in Java file
your_imageview.setImageBitmap(new RoundImage(
getApplicationContext()).transform(your_image_bitmap));
You can use external libraries Circle Image View
Use below code to make Bitmap to Circle Bitmap for ImageView :
public static Bitmap getRoundedRectBitmap(Bitmap bitmap, int pixels) {
Bitmap result = null;
try {
result = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
int color = 0xff424242;
Paint paint = new Paint();
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int pl = 1;
int pr = 1;
int pt = 1;
int pb = 1;
int usableWidth = w - (pl + pr);
int usableHeight = h - (pt + pb);
int radius = Math.min(usableWidth, usableHeight) / 2;
int cx = pl + (usableWidth / 2);
int cy = pt + (usableHeight / 2);
canvas.drawCircle(cx, cy, radius, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
} catch (NullPointerException e) {
} catch (OutOfMemoryError o) {
}
return result;
}
I'm using Picasso :
Picasso.with(mContext)
.load(url)
.placeholder(fallback)
.error(fallback)
.transform(new CircleTransform(userStatus))
.into(this);
And Transformation to apply stroke and roundness to the image:
public class CircleTransform implements Transformation {
private int userStatus = UserProfile.STATUS_TYPE_NONE;
public CircleTransform(int userStatus) {
this.userStatus = userStatus;
}
#Override
public Bitmap transform(Bitmap source) {
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
source.recycle();
}
Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
if (UserProfile.STATUS_TYPE_NONE != userStatus) {
Paint paintStroke = new Paint();
paintStroke.setAntiAlias(true);
if (UserProfile.STATUS_TYPE_BRONZE == userStatus)
paintStroke.setColor(Colors.bronzeColor);
else if (UserProfile.STATUS_TYPE_SILVER == userStatus)
paintStroke.setColor(Colors.silverColor);
else if (UserProfile.STATUS_TYPE_GOLD == userStatus)
paintStroke.setColor(Colors.goldColor);
else if (UserProfile.STATUS_TYPE_PLATINUM == userStatus)
paintStroke.setColor(Colors.platinumColor);
else if (UserProfile.STATUS_TYPE_DIAMOND == userStatus)
paintStroke.setColor(Colors.diamondColor);
paintStroke.setStyle(Paint.Style.STROKE);
float stroke = size * CIRCLE_SIZE_IN_PERCENT;
paintStroke.setStrokeWidth(stroke);
canvas.drawCircle(r, r, r - (stroke / 2), paintStroke);
}
squaredBitmap.recycle();
return bitmap;
}
#Override
public String key() {
return "circle";
}
}
the problem is that the public Bitmap transform(Bitmap source) is not getting called each time the image is loaded.
The userStatus variable changes the behavior of the transformation and thus must be included in the cache key. Otherwise Picasso thinks that any circle transformation can be replaced with another.
#Override
public String key() {
return "circle" + userStatus;
}
Ok I found the solution, the transformation key stays the same and it dose not apply a new one with the same key, so I changed
#Override
public String key() {
return "circle";
}
to:
#Override
public String key() {
return "circle" + value;
}
value - should be unique parameter defining the instance of the ImageView. I hope it helps someone :)