How to create drawable circle with below requirement? - android

I'm trying create a circular shaped drawable to put as overlay for profile pictures(circular images)
I wrote the below code for circular drawable overlay,
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="#color/light_blue_bg" />
</shape>
</item>
<item>
<shape android:shape="oval">
<stroke
android:width="2dp"
android:color="#android:color/white" />
<solid android:color="#android:color/transparent" />
</shape>
</item>
</layer-list>
Refer the output in the below screen image,
Known Issues: I'm creating a rectangle with #color/light_blue_color and it has inner oval shape with stroke color and inner solid transparent color, but due to outer rectangle color inner circle transparency not showing picture.
If I remove outer rectangle color real square picture will come out of circular overlay.
Is there any way to give color to outer circular portion alone?
Any help ll be highly appreciated

#Sreedhu Madhu .... you have to customize your imageview and work it on bitmap and canvas to achieve so..
although i suggest you to use one of the library posted by Henning Dodenhof on github and android-arsenal... CircleImageView
on the other side you can take a look how this is done..using this class..
Custom Class for Circular ImageView
the imp methods was setup() and onDraw()

I don't think it is possible by doing it just in XML. But you can mask it out afterwards in code. For an example, see this tutorial.

For rounded (Circled imageView)add this class to your source
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
public class RoundedImageView extends ImageView {
public RoundedImageView(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
}
#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 = getRoundedCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);
}
public static Bitmap getRoundedCroppedBitmap(Bitmap bitmap, int radius) {
Bitmap finalBitmap;
if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
false);
else
finalBitmap = bitmap;
Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
finalBitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
finalBitmap.getHeight());
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(finalBitmap.getWidth() / 2 + 0.7f,
finalBitmap.getHeight() / 2 + 0.7f,
finalBitmap.getWidth() / 2 + 0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(finalBitmap, rect, rect, paint);
return output;
}
}
and then change your ImageView to your package name and class name (RoundedImageView) in your layout file such as
<com.mypackege.RoundedImageView
android:id="#+id/imageView_round"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginTop="15dp"
android:src="#drawable/my_image" />
Hope this will work.

Try something like this, it worked for me!
in your xml place this custom RoundImage:
<com.example.hkh.learningandroid.RoundedImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:src="#drawable/person"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:id="#+id/MyImageView" />
and create new class and name it RoundImageView:
public class RoundedImageView extends ImageView {
public RoundedImageView(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
}
#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 = getRoundedCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);
}
public static Bitmap getRoundedCroppedBitmap(Bitmap bitmap, int radius) {
Bitmap finalBitmap;
if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
false);
else
finalBitmap = bitmap;
Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
finalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
finalBitmap.getHeight());
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(finalBitmap.getWidth() / 2 + 0.7f,
finalBitmap.getHeight() / 2 + 0.7f,
finalBitmap.getWidth() / 2 + 0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(finalBitmap, rect, rect, paint);
return output;
}
}
And run, i hope it will help, it will give the expected rounded image as you wanted

Related

Android code to make imageView round not working

I am trying to make my ImageView round. I have written the following code to make it appear round but somehow it is still showing square ImageView. [Using picasso to fetch image]
Java code:
ImageView iv = (ImageView) addLinkDialog.findViewById(R.id.group_icon_jsoup);
Picasso.with(getBaseContext()).load(GroupImageUrl).into(iv);
iv.setBackgroundResource(R.drawable.icon_img);
ImageView code:
<ImageView
android:id="#+id/group_icon_jsoup"
android:layout_width="75dp"
android:layout_height="75dp"
android:layout_gravity="center"
android:layout_margin="8dp"
android:background="#drawable/icon_img" />
#drawable/icon_img.xml:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/circle"/>
</layer-list>
#drawable/circle.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dp"
android:shape="ring"
android:thicknessRatio="1.9"
android:useLevel="false" >
<solid android:color="#android:color/transparent" />
<stroke
android:width="10dp"
android:color="#android:color/white" />
</shape>
Why not using third party ?
Try this code
Bitmap picture = BitmapFactory.decodeResource(getResources(), R.mipmap.add_image);
ImageView imageView = (ImageView) findViewById(R.id.imgProfilePicture);
imageView.setImageBitmap(getRoundedBitmap(picture));
public Bitmap getRoundedBitmap(Bitmap bitmap){
Bitmap circleBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setShader(shader);
paint.setAntiAlias(true);
Canvas c = new Canvas(circleBitmap);
c.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getWidth() / 2, paint);
return circleBitmap;
}
Your xml file
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/imgProfilePicture"
android:layout_width="110dp"
android:layout_height="110dp"
android:layout_marginBottom="20dp"
app:civ_border_width="3dp"
app:civ_border_color="#color/light_gray" />
and add this in build.gradle
compile 'de.hdodenhof:circleimageview:2.1.0'
Cirular ImageView Done !
Do you want to use only code or you are ok with library too? If you are ok with library may I suggest using this library, helped me a lot. If you don't want to use library, you can use RoundedBitmapDrawable:
RoundedBitmapDrawable drawable =
RoundedBitmapDrawableFactory.create(context.getResources(), bitmap)
drawable.setCircular(true);
Use this drawable in your ImageView.
Major problem will be when you use Picasso to set image again to set to imageView view bounds not to the its background that you create.
If you programmatically set a one it will override your background!
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false">
<shape android:shape="oval">
<solid android:color="#color/colorPrimary"/>
</shape>
</item>
</selector>
You can set this as background of your view.Then try to use view.setBackgroundResource(R.drawable.icon_img); . you will notice the change!
You can go through Add a background image to shape in xml Android
Mask ImageView with round corner background
to check the various ways people tried out here!
But with Picasso you can do this directly with out other 3rd parties.
final ImageView imageView = (ImageView) findViewById(R.id.group_icon_jsoup);
Picasso.with(YourActivity.this).load("http://i.imgur.com/DvpvklR.png")
.resize(100, 100)
.into(imageView, new Callback() {
#Override
public void onSuccess() {
Bitmap imageBitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
RoundedBitmapDrawable imageDrawable = RoundedBitmapDrawableFactory.create(getResources(), imageBitmap);
imageDrawable.setCircular(true);
imageDrawable.setCornerRadius(Math.max(imageBitmap.getWidth(), imageBitmap.getHeight()) / 2.0f);
imageView.setImageDrawable(imageDrawable);
}
#Override
public void onError() {
imageView.setImageResource(R.drawable.amanda);
}
});
Hello #Surjan here is the code which help to create a image in Any shape which you want only you need image of your choice shape with transparent and combination of any other color, following was the example :
protected Bitmap getPinnedImage(Bitmap original, int shapeImage) {
if (original == null) {
original = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_round_shape);
}
Bitmap mask = BitmapFactory.decodeResource(context.getResources(), shapeImage);
original = Bitmap.createScaledBitmap(original, mask.getWidth(), mask.getHeight(), true);
Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Bitmap.Config.ARGB_8888);
Canvas mCanvas = new Canvas(result);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mCanvas.drawBitmap(original, 0, 0, null);
mCanvas.drawBitmap(mask, 0, 0, paint);
paint.setXfermode(null);
return result;
}
Here is the tow parameter first one is your original bitmap and second one is the your shape drawable, like following was the pin shape
now passing after this drawable you can get your image in pin shape no need to access any third party library.
Try this,
ImageView iv = (ImageView) addLinkDialog.findViewById(R.id.group_icon_jsoup);
Picasso.with(getBaseContext()).load(GroupImageUrl).transform(new RoundedTransformation(5,15, Color.parseColor("#27a3cb"))).fit().into(iv);
public class RoundedTransformation implements Transformation {
private int mBorderSize;
private int mCornerRadius = 0;
private int mColor;
public RoundedTransformation(int borderSize, int color) {
this.mBorderSize = borderSize;
this.mColor = color;
}
public RoundedTransformation(int borderSize, int cornerRadius, int color) {
this.mBorderSize = borderSize;
this.mCornerRadius = cornerRadius;
this.mColor = color;
}
#Override
public Bitmap transform(Bitmap source) {
int width = source.getWidth();
int height = source.getHeight();
Bitmap image = Bitmap.createBitmap(width, height, source.getConfig());
Canvas canvas = new Canvas(image);
canvas.drawARGB(0, 0, 0, 0);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Rect rect = new Rect(0, 0, width, height);
if(this.mCornerRadius == 0) {
canvas.drawRect(rect, paint);
}
else {
canvas.drawRoundRect(new RectF(rect),this.mCornerRadius, this.mCornerRadius, paint);
}
paint.setXfermode(new PorterDuffXfermode((PorterDuff.Mode.SRC_IN)));
canvas.drawBitmap(source, rect, rect, paint);
Bitmap output;
if(this.mBorderSize == 0) {
output = image;
}
else {
width = width + this.mBorderSize * 2;
height = height + this.mBorderSize * 2;
output = Bitmap.createBitmap(width, height, source.getConfig());
canvas.setBitmap(output);
canvas.drawARGB(0, 0, 0, 0);
rect = new Rect(0, 0, width, height);
paint.setXfermode(null);
paint.setColor(this.mColor);
paint.setStyle(Paint.Style.FILL);
canvas.drawRoundRect(new RectF(rect), this.mCornerRadius, this.mCornerRadius, paint);
canvas.drawBitmap(image, this.mBorderSize, this.mBorderSize, null);
}
if(source != output) source.recycle();
return output;
}
#Override
public String key() {
return "bitmapBorder(" +
"borderSize=" + this.mBorderSize + ", " +
"cornerRadius=" + this.mCornerRadius + ", " +
"color=" + this.mColor +")";
}
}

Out of memory error while loading image in CircularImageView

I am trying to load an image in CircularImageView but it is giving me outOfMemory error.
I am using following code for CircularImageView:
CircularImageView.java
public class CircularImageView extends ImageView {
public CircularImageView(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
}
#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 = getRoundedCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);
}
public static Bitmap getRoundedCroppedBitmap(Bitmap bitmap, int radius) {
Bitmap
finalBitmap;
if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
false);
else
finalBitmap = bitmap;
Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
finalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
finalBitmap.getHeight());
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(finalBitmap.getWidth() / 2 + 0.7f,
finalBitmap.getHeight() / 2 + 0.7f,
finalBitmap.getWidth() / 2 + 0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(finalBitmap, rect, rect, paint);
return output;
}
}
I using it in the design as given below:
<com.almabay.almachat.circularImageView.CircularImageView
android:id="#+id/img_group"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_alignParentLeft="true" />
I am getting image from server and trying to display it in the list view using Adapter.Following code is being used here:
Picasso.with(context).load(image_url).error(R.drawable.default_avatar).into(viewHolder.imgGroup);
Here image_url is the URL of the image to be loaded in circular image view.ViewHolder.imgGroup is the circularImageView.
Please help me to fix the issue.
I see you are using Picasso for image loading why not use picasso image transformations. it's very simple to implement :-
ImageView im = (ImageView) findViewById(R.id.img1);
Picasso.with(MainActivity2.this).load(R.drawable.kitten)
.transform(new CropCircleTransformation()).into(im);
and it looks like this
You just need to add transformation class
import com.squareup.picasso.Transformation;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
public class CropCircleTransformation implements Transformation {
#Override public Bitmap transform(Bitmap source) {
int size = Math.min(source.getWidth(), source.getHeight());
int width = (source.getWidth() - size) / 2;
int height = (source.getHeight() - size) / 2;
Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader =
new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
if (width != 0 || height != 0) {
// source isn't square, move viewport to center
Matrix matrix = new Matrix();
matrix.setTranslate(-width, -height);
shader.setLocalMatrix(matrix);
}
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
source.recycle();
return bitmap;
}
#Override public String key() {
return "CropCircleTransformation()";
}
}
More transformations can we find here https://github.com/wasabeef/picasso-transformations
Normally I'd tell you that the error could be anywhere and you're probably leaking. But you're making 2 new bitmaps in onDraw? And all 3 are in memory? Not only is that hideously wasteful, but your performance will suck- you should even avoid using new in onDraw, much less allocating bitmaps.
Throw this out and rewrite it completely. You should avoid working on a drawable here (especially since you're assuming its a bitmap anyway which is a bad idea), you should take in a filename or resource id of the bitmap and read it in/scale it with 1 createBitmap command by using BitmapOptions. You should do this when the bitmap is set and save the result, do NOT scale in onDraw which is called all the time. You can avoid the 3rd bitmap by using a circular clipping path instead of using porter duff modes and a second canvas. You can do all this with just 1 bitmap, and should.

Make ImageView with Round Corner Using picasso

I know there are lots of link available to make ImageView Round Corner.
But I'm Using Picasso Library for Image Loading..
I refer the link to get result.
But the Problem is that I'm Using it in ListView and for the LIstView's first item ImageView its working perfectly fine but for the remaining once transformation is not working.
I am using this transformation:
https://gist.github.com/julianshen/5829333
Picasso.with(activity).load(url).transform(new CircleTransform()).into(imageView);
You can use RoundedCornersTransformation class of picasso-transformations library.
Example :
final int radius = 5;
final int margin = 5;
final Transformation transformation = new RoundedCornersTransformation(radius, margin);
Picasso.with(activity).load(url).transform(transformation).into(imageView);
You can use this class to make rounded corners rectangle image view with Picasso, use it like this
Picasso.with(activity).load(url).transform(new RoundedCornersTransform(this)).into(imageView);
Here is the class RoundedCornersTransform.
package com.demo.picasso;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import com.squareup.picasso.Transformation;
public class RoundedCornersTransform 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";
}
}
i used RoundedCornersTransformationclass of picasso-transformationslibrary. I had custom adapter with view holder pattern in my listview. I added below dependency in my build.gradle:
dependencies {
compile 'jp.wasabeef:picasso-transformations:2.1.0'
}
And in my customArrayAdapter.java,i added:
Picasso.with(getContext()).load(path).transform(new RoundedCornersTransformation(10,10)).resize(175,300).into(viewHolder.ivImage);
This would both resize and give rounded corners to you images.
Like said here. You can use MaskTransformationclass of picasso-transformations library.
Example :
final Transformation transformation = new MaskTransformation(getContext(), R.drawable.rounded_convers_transformation);
Picasso.with(activity).load(url).transform(transformation).into(imageView);
res/drawable/rounded_convers_transformation.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="5dp"/>
<solid android:color="#color/black"/>
</shape>
UPDATE: But notice that you should also .resize(w,h) the image, because if image will be large the round will not be determinatable
Kotlin version of RoundCornerTransform based on #stevyhacker 's answer.
Support rectangle instead of square image.
No extra 3rd party library needed.
=============================================
import android.graphics.*
import com.squareup.picasso.Transformation
class RoundCornersTransform(private val radiusInPx: Float) : Transformation {
override fun transform(source: Bitmap): Bitmap {
val bitmap = Bitmap.createBitmap(source.width, source.height, source.config)
val canvas = Canvas(bitmap)
val paint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.DITHER_FLAG)
val shader = BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
paint.shader = shader
val rect = RectF(0.0f, 0.0f, source.width.toFloat(), source.height.toFloat())
canvas.drawRoundRect(rect, radiusInPx, radiusInPx, paint)
source.recycle()
return bitmap
}
override fun key(): String {
return "round_corners"
}
}
Usage:
Picasso.get()
.load(imageUrl)
.memoryPolicy(MemoryPolicy.NO_CACHE)
.placeholder(R.drawable.image_placeholder)
.transform(RoundCornersTransform(32.0f))
.into(imageView, callback)
Following #stevyhacker's answer and this related one, I came up with this:
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import com.squareup.picasso.Transformation;
public class RoundedCornersTransform implements Transformation {
private static Bitmap createRoundedRectBitmap(Bitmap bitmap,
float topLeftCorner, float topRightCorner,
float bottomRightCorner, float bottomLeftCorner) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = Color.WHITE;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
Path path = new Path();
float[] radii = new float[]{
topLeftCorner, bottomLeftCorner,
topRightCorner, topRightCorner,
bottomRightCorner, bottomRightCorner,
bottomLeftCorner, bottomLeftCorner
};
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
path.addRoundRect(rectF, radii, Path.Direction.CW);
canvas.drawPath(path, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
#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();
}
float r = size / 4f;
Bitmap roundedBitmap = createRoundedRectBitmap(squaredBitmap, r, r, r, r);
squaredBitmap.recycle();
return roundedBitmap;
}
#Override
public String key() {
return "rounded_corners";
}
}
Use it like this:
Picasso.with(context).load(url).transform(new RoundedCornersTransform()).into(imageView);
Probably needs some enhancements though, so watch out!

Bitmap in ImageView with rounded corners

I have an ImageView and I want to make it with rounded corners.
I use this:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#null"/>
<stroke android:width="1dp"
android:color="#ff000000"/>
<corners android:radius="62px"/>
</shape>
And set this code as background of my imageview.
It works, but the src image that I put on the ImageView is going out of the borders and doesn't adapt itself into the new shape.
How can I solve the problem?
try this one :
public class CustomImageView extends ImageView {
public static float radius = 18.0f;
public CustomImageView(Context context) {
super(context);
}
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
//float radius = 36.0f;
Path clipPath = new Path();
RectF rect = new RectF(0, 0, this.getWidth(), this.getHeight());
clipPath.addRoundRect(rect, radius, radius, Path.Direction.CW);
canvas.clipPath(clipPath);
super.onDraw(canvas);
}
}
and
<your.pack.name.CustomImageView
android:id="#+id/selectIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:scaleType="centerCrop" />
CustomImageView iconImage = (CustomImageView )findViewById(R.id.selectIcon);
iconImage.setImageBitmap(bitmap);
or,
ImageView iv= new CustomImageView(this);
iv.setImageResource(R.drawable.pic);
It's strange that nobody here has mentioned RoundedBitmapDrawable from Android Support Library v4. For me it is the simplest way to get rounded corners without borders. Here is example of usage:
RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources(), bitmap);
final float roundPx = (float) bitmap.getWidth() * 0.06f;
roundedBitmapDrawable.setCornerRadius(roundPx);
Make one function which make rounded to your bitmap using canvas.
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;
}
for more info:> here
The accepted answer uses path clipping, but it doesn't support anti-aliasing. See Romain Guy's comments on his post. "path clipping does not support antialiasing and you get jagged edges."
http://www.curious-creature.com/2012/12/11/android-recipe-1-image-with-rounded-corners/
There is one good library(vinc3m1’s RoundedImageView) that supoorts rounded corners on ImageView, but it only supports the same radiuses on every corners. So I made one that you can set different radiuses on each corners.
It doesn't rely on path clipping, nor redrawing. It only draws one time with canvas.drawPath() method. So I finally got result that I wanted like below.
See : https://github.com/pungrue26/SelectableRoundedImageView
For me, the below method does the magic. :)
This method accepts a bitmap object and returns it back with rounded corners. roundPx is the number of rounded pixels you want:
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
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 = 12;
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;
}
...or you could use this library instead of ImageView without any further coding.
If you need make Bitmap with different corner radii and I recommend follow code:
private static Bitmap createRoundedRectBitmap(#NonNull Bitmap bitmap,
float topLeftCorner, float topRightCorner,
float bottomRightCorner, float bottomLeftCorner) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = Color.WHITE;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
Path path = new Path();
float[] radii = new float[]{
topLeftCorner, bottomLeftCorner,
topRightCorner, topRightCorner,
bottomRightCorner, bottomRightCorner,
bottomLeftCorner, bottomLeftCorner
};
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
path.addRoundRect(rectF, radii, Path.Direction.CW);
canvas.drawPath(path, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
If you need border also then:
1. You can use a rounded box image with a transparent body and white from outside. For Example:
and use this with target image like below:
<FrameLayout
android:layout_width="100px"
android:layout_height="100px" >
<ImageView
android:id="#+id/targetImage"
android:layout_width="100px"
android:layout_height="100px"
android:src="#drawable/app_icon"
android:layout_gravity="center" />
<ImageView
android:id="#+id/boxImage"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitXY"
android:src="#drawable/box" />
Adding CardView as parent layout of ImageView also be a good solution.
It can be done with background drawable, like explain in many posts including this one, but it also needs to set clipping.
Here a full example:
The code:
AppCompatImageView iconView = findViewById(R.id.thumbnail);
iconView.setClipToOutline(true);
The layout:
<android.support.v7.widget.AppCompatImageView
android:id="#+id/thumbnail"
android:layout_width="80dp"
android:layout_height="80dp"
android:contentDescription="#string/thumbnail"
android:scaleType="centerInside"
android:background="#drawable/round_view" <!--here set the drawable as background -->
tools:src="#mipmap/ic_user" />
The drawable:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="10dp" />
</shape>
/**
* Creates new circular bitmap based on original one.
* #param newCornerRadius is optional
*/
fun Bitmap.toCircular(context: Context, newCornerRadius: Float? = null): RoundedBitmapDrawable {
return RoundedBitmapDrawableFactory.create(context.resources, this).apply {
isCircular = true
newCornerRadius?.let {
cornerRadius = it
}
}
}
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) {
super.onDraw(canvas);
Bitmap rounder = Bitmap.createBitmap(getWidth(),getHeight(),Bitmap.Config.ARGB_8888);
Canvas canvasRound = new Canvas(rounder);
Paint xferPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
xferPaint.setColor(Color.BLACK);
final int rx = this.getWidth(); //our x radius
final int ry = this.getHeight(); //our y radius
canvasRound.drawRoundRect(new RectF(0,0,rx,ry), rx, ry, xferPaint);
xferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawBitmap(rounder, 0, 0, xferPaint);
}
}
Kotlin version
fun Bitmap.roundCorner(pixels: Int): Bitmap {
val output: Bitmap = Bitmap.createBitmap(
width, height, Bitmap.Config.ARGB_8888
)
val canvas = Canvas(output)
val color = -0xbdbdbe
val paint = Paint()
val rect = Rect(0, 0, width, height)
val rectF = RectF(rect)
val roundPx = pixels.toFloat()
paint.isAntiAlias = true
canvas.drawARGB(0, 0, 0, 0)
paint.color = color
canvas.drawRoundRect(rectF, roundPx, roundPx, paint)
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
canvas.drawBitmap(this, rect, rect, paint)
return output
}
call by:
sourceBitmap.roundCorner(60)
The method to make rounded corners for imageview in android is not rocket science guys! just use a png with required curves with the same color as your background and set the overlay to FITXY.!
public void drawRoundImage(boolean isEditPicEnable){
if(originalImageBitmap != null){
setBackgroundResource(R.drawable.ic_account_user_outer_circle_blue);
if (isEditPicEnable) {
setBackgroundResource(R.drawable.ic_account_user_outer_circle_white);
Bitmap mask = BitmapFactory.decodeResource(getResources(), R.drawable.ic_account_white_mask);
Bitmap mask1 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_account_pencil_bg);
originalImageBitmap = Bitmap.createScaledBitmap(originalImageBitmap, mask.getWidth(), mask.getHeight(), true);
Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Bitmap.Config.ARGB_8888);
Canvas mCanvas = new Canvas(result);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mCanvas.drawBitmap(originalImageBitmap, 0, 0, null);
mCanvas.drawBitmap(mask, 0, 0, paint);
mCanvas.drawBitmap(mask1, 0, 0, null);
Bitmap mask2 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_account_pencil);
mCanvas.drawBitmap(mask2, 0, 0, null);
setImageBitmap(result);
setScaleType(ScaleType.FIT_XY);
} else {
Bitmap mask = BitmapFactory.decodeResource(getResources(),R.drawable.ic_account_white_mask);
originalImageBitmap = Bitmap.createScaledBitmap(originalImageBitmap, mask.getWidth(),mask.getHeight(), true);
Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(),Bitmap.Config.ARGB_8888);
Canvas mCanvas = new Canvas(result);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mCanvas.drawBitmap(originalImageBitmap, 0, 0, null);
mCanvas.drawBitmap(mask, 0, 0, paint);
paint.setXfermode(null);
setImageBitmap(result);
setScaleType(ScaleType.FIT_XY);
}
}else{
setBackgroundResource(R.drawable.ic_account_user_outer_circle_blue);
setImageResource(R.drawable.my_ac_default_profile_pic);
}
}

Crop square image to circle - Programmatically

i was searching for past one day and i was not successful .
i get the image from API , and i download it to a bitmap file using the following code .
private Bitmap DownloadImage(String URL)
{
Bitmap bitmap = null;
InputStream in = null;
try
{
in = OpenHttpConnection(URL);
bitmap = BitmapFactory.decodeStream(in);
in.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
return bitmap;
}
private InputStream OpenHttpConnection(String urlString) throws IOException
{
InputStream in = null;
int response = -1;
URL url = new URL(urlString);
URLConnection conn = url.openConnection();
if (!(conn instanceof HttpURLConnection))
throw new IOException("Not an HTTP connection");
try
{
HttpURLConnection httpConn = (HttpURLConnection) conn;
httpConn.setAllowUserInteraction(false);
httpConn.setInstanceFollowRedirects(true);
httpConn.setRequestMethod("GET");
httpConn.connect();
response = httpConn.getResponseCode();
if (response == HttpURLConnection.HTTP_OK)
{
in = httpConn.getInputStream();
}
}
catch (Exception ex)
{
throw new IOException("Error connecting");
}
return in;
}
And i get the image as a square and i want to crop the four corners and make it to circular image . Is there any possible way to achieve ?
Any related answers are welcomed . Thanks in advance .
Once the bitmap is retrieved RoundedBitmapDrawableFactory can be used to generate a RoundedBitmapDrawable from the v4 Support Library. That Drawable can then be applied to an ImageView or directly drawn to a Canvas.
// Create the RoundedBitmapDrawable.
RoundedBitmapDrawable roundDrawable = RoundedBitmapDrawableFactory.create(getResources(), bitmap);
roundDrawable.setCircular(true);
// Apply it to an ImageView.
ImageView imageView = (ImageView)findViewById(R.id.imageView);
imageView.setImageDrawable(roundDrawable);
// Alternatively, draw it to an canvas (e.g. in onDraw where a Canvas is available).
// setBounds since there's no View handling size and positioning.
roundDrawable.setBounds(left, top, right, bottom);
roundDrawable.draw(canvas);
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
DrawingView dv = new DrawingView(this);
setContentView(dv);
}
class DrawingView extends View {
Bitmap bitmap;
public DrawingView(Context context) {
super(context);
bitmap = BitmapFactory.decodeResource(context.getResources(),
R.drawable.glossy_overlay);
}
#Override
public void onDraw(Canvas canvas) {
Paint paint = new Paint();
// paint.setColor(Color.CYAN);
canvas.drawBitmap(getclip(), 30, 20, paint);
}
public Bitmap getclip() {
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());
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
// paint.setColor(color);
canvas.drawCircle(bitmap.getWidth() / 2,
bitmap.getHeight() / 2, bitmap.getWidth() / 2, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
}
}
use the function below to draw a circle on bitmap and then set the circled bitmap to imageView
public static Bitmap getClip(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
canvas.drawCircle(bitmap.getWidth() / 2f, bitmap.getHeight() / 2f,
bitmap.getWidth() / 2f, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
Note: Dividing numbers must be float
Roman Nurik propose a very direct use of shaders to do things like that, with a custom drawable.
I change the code a bit to make an oval image and tested myself. The effect and performance are really good:
public class StreamDrawable extends Drawable {
private static final boolean USE_VIGNETTE = true;
private final RectF mRect = new RectF();
private final BitmapShader mBitmapShader;
private final Paint mPaint;
private final int mMargin;
public StreamDrawable(Bitmap bitmap, int margin) {
mBitmapShader = new BitmapShader(bitmap,
Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setShader(mBitmapShader);
mMargin = margin;
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mRect.set(mMargin, mMargin, bounds.width() - mMargin, bounds.height() - mMargin);
if (USE_VIGNETTE) {
RadialGradient vignette = new RadialGradient(
mRect.centerX(), mRect.centerY() * 1.0f / 0.7f, mRect.centerX() * 1.3f,
new int[] { 0, 0, 0x7f000000 }, new float[] { 0.0f, 0.7f, 1.0f },
Shader.TileMode.CLAMP);
Matrix oval = new Matrix();
oval.setScale(1.0f, 0.7f);
vignette.setLocalMatrix(oval);
mPaint.setShader(
new ComposeShader(mBitmapShader, vignette, PorterDuff.Mode.SRC_OVER));
}
}
#Override
public void draw(Canvas canvas) {
canvas.drawOval(mRect, mPaint);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
#Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
#Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
}
}
This can be simply done in xml, Please see my answer here:
https://stackoverflow.com/a/18287979/665930
<RelativeLayout
android:id="#+id/icon_layout"
android:layout_width="#dimen/icon_mask"
android:layout_height="#dimen/icon_mask"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
<ImageView
android:id="#+id/icon"
android:layout_width="#dimen/icon"
android:layout_height="#dimen/icon"
android:layout_centerInParent="true"
android:scaleType="fitXY" >
</ImageView>
<ImageView
android:id="#+id/icon_mask"
android:layout_width="#dimen/icon_mask"
android:layout_height="#dimen/icon_mask"
android:layout_centerInParent="true"
android:background="#drawable/circle"
android:scaleType="fitXY" >
</ImageView>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" >
<gradient android:startColor="#00FFFFFF" android:endColor="#00FFFFFF"
android:angle="270"/>
<stroke android:width="10dp" android:color="#FFAAAAAA"/>
I tried the solutions above but none worked well for me. This is because my phone camera don't take square image but just rectangle images. So, I make some changes in the #actsai solution to always take the minor dimension and then crop the image in a circle:
public static Bitmap getBitmapClip(Bitmap bitmap) {
int maxLenth = bitmap.getWidth() <= bitmap.getHeight() ? bitmap.getWidth() : bitmap.getHeight();
Bitmap output = Bitmap.createBitmap(maxLenth,
maxLenth, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, maxLenth, maxLenth);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
canvas.drawCircle(maxLenth / 2, maxLenth / 2,
maxLenth / 2, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
I used the following scale property to fill my ImageView with the new bitmap:
<ImageView
android:id="#+id/iv_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:scaleType="fitXY" />
After hunting lot of answers I came up with this small hack which exploits FrameLayout(overlays child views as a stack) and stroke attribute of oval-shape. This can be done simply in XML without much hassle and third party libraries.
Create new Layout resource file "circle_image.xml" under res/layout directory.
Add a new FrameLayout as the root view in the circle_image.xml.
Create an ImageView (base/background) to hold your Image or Icon which you want to crop as the first child in the FrameLayout.
Create an ImageView (mask/foreground) to hold the shape(oval made into circle with size attribute having same height and width) that masks the background image as the second/last child inside the FrameLayout.
Note:
our idea here is to exclude the area around the circle and display the contents of the image that is visible inside the circle)
Create new Drawable resource file "circle_mask.xml" under res/drawable directory.
Add new shape with android:shape="oval" in the circle_mask.xml.
Add size tag for the shape to specify height and width which must be equal(to make it a circle) and should match that of its parent FrameLayout.
Add solid tag for the shape to specify the transparency inside the circle.
10.Add stroke tag for the shape so that there will be a ring of particular width(android:width) with the color specified by the android:color attribute.
Note:
a. The color(stroke color) specified in the stoke tag is the MaskColor/BackgroundColor around our cropped image. since I wanted this color to be same as that of my base view which was a cardView. I used the same color "white".
b. The width (stroke width) is set to a huge value such that it is too thick with enough space for our cropped image in the centre.
c. The ImageView(top mask layer) created in Step-4 is also exploited by specifying a huge dimension that is much larger than its parent FrameLayout making it expand outside the FrameLayout dimensions. This fills up the area which we are interested in masking with the color of large stroke width ring.
circle_image.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/icon_layout"
android:layout_width="64dp"
android:layout_height="64dp">
<ImageView
android:id="#+id/iv_profile_pic"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/ic_launcher_background"
android:contentDescription="TODO"/>
<ImageView
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_gravity="center"
android:background="#drawable/circle"
android:scaleType="fitXY" >
</ImageView>
</FrameLayout>
circle_mask.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size android:width="64dp"
android:height="64dp"/>
<solid android:color="#android:color/transparent"/>
<stroke
android:width="18dp"
android:color="#android:color/white" />
</shape>

Categories

Resources