I want to know an Image inside a Circle Mask as follows.
The user usually selected the image from the gallery or shoots one using the camera. Considering that the image is either Landscape or Portrait and not square. is there a way to display a center cropped image after choosing the image?
<com.mikhaellopez.circularimageview.CircularImageView
android:id="#+id/ivCreateCompanyImage"
android:layout_width="#dimen/big_logo_width_height"
android:layout_height="#dimen/big_logo_width_height"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="#dimen/ten_dp"
android:layout_marginTop="#dimen/thirty_dp"
android:src="#drawable/add_image"
android:scaleType="centerCrop"
android:background="#drawable/logo_button_selector"
app:border_color="#color/transparent"
app:border_width="5"
app:shadow="false" />
Java code
public void onActivityResult(int requestCode, int resultCode,
Intent data)
{
if(resultCode != RESULT_OK)
return;
else if (requestCode == SELECT_FILE)
{
// this gives the Uri of the selected image
Uri selectedImageUri = data.getData();
try {
InputStream stream = getActivity().getContentResolver().openInputStream(selectedImageUri);
byte[] bytes = getBytes(stream);
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
int height_width = (int) getResources().getDimension(R.dimen.big_logo_width_height);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap,height_width,height_width,true);
ivCreateCompanyImage.setImageBitmap(scaledBitmap);
}
catch(Exception ex)
{
}
//ivCreateCompanyImage.setImageURI(selectedImageUri);
}
else if( requestCode == CAPTURE_FROM_CAMERA)
{
File f = new File(Environment.getExternalStorageDirectory().toString());
for (File temp : f.listFiles())
{
if (temp.getName().equals("temp.jpg"))
{
f = temp;
ivCreateCompanyImage.setImageURI(Uri.fromFile(f));
break;
}
}
}
super.onActivityResult(requestCode, resultCode, data);
}
You can do this very simply (I've done this exact thing and its live on millions of devices right now) using Picasso and a Circular Image Transformation.
Here's a gist of the exact code I use in production.
This code is working for me
<com.abc.commons.helper.CircularImageView
android:id="#+id/capture_pic"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:background="#drawable/payer_profile_image"
android:scaleType="centerCrop"
app:shadow="true" />
Create seperate java class name as CircularImageView.java and paste the entire below code
and just give the reference of this class in your xml imgevoew tag and after that it will take care everything automatically
package com.xyz.commons.helper;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
/**
* This class is used to set style of image
* means this class will help to set the image in circular form
* #author santoshk
*
*/
#SuppressLint("DrawAllocation")
public class CircularImageView extends ImageView {
private int borderWidth;
private int canvasSize;
private Bitmap image;
private Paint paint;
private Paint paintBorder;
public CircularImageView(final Context context) {
this(context, null);
}
public CircularImageView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.circularImageViewStyle);
}
#SuppressLint("Recycle")
public CircularImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// init paint
paint = new Paint();
paint.setAntiAlias(true);
paintBorder = new Paint();
paintBorder.setAntiAlias(true);
// load the styled attributes and set their properties
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.CircularImageView, defStyle, 0);
if(attributes.getBoolean(R.styleable.CircularImageView_border, true)) {
int defaultBorderSize = (int) (4 * getContext().getResources().getDisplayMetrics().density + 0.5f);
setBorderWidth(attributes.getDimensionPixelOffset(R.styleable.CircularImageView_border_width, defaultBorderSize));
setBorderColor(attributes.getColor(R.styleable.CircularImageView_border_color, Color.WHITE));
}
if(attributes.getBoolean(R.styleable.CircularImageView_shadow, false))
addShadow();
}
/**
* This method is used to set the width of border
* #param borderWidth
*/
public void setBorderWidth(int borderWidth) {
this.borderWidth = borderWidth;
this.requestLayout();
this.invalidate();
}
/**
* This method is used to set the color of border
* #param borderColor
*/
public void setBorderColor(int borderColor) {
if (paintBorder != null)
paintBorder.setColor(borderColor);
this.invalidate();
}
/**
* This method is used to set the shadow
*/
public void addShadow() {
setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);
}
#SuppressLint("DrawAllocation")
#Override
public void onDraw(Canvas canvas) {
// load the bitmap
image = drawableToBitmap(getDrawable());
// init shader
if (image != null) {
canvasSize = canvas.getWidth();
if(canvas.getHeight()<canvasSize)
canvasSize = canvas.getHeight();
BitmapShader shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvasSize, canvasSize, false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
// circleCenter is the x or y of the view's center
// radius is the radius in pixels of the cirle to be drawn
// paint contains the shader that will texture the shape
int circleCenter = (canvasSize - (borderWidth * 2)) / 2;
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) + borderWidth - 4.0f, paintBorder);
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) - 4.0f, paint);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
setMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// The parent has determined an exact size for the child.
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
// The child can be as large as it wants up to the specified size.
result = specSize;
} else {
// The parent has not imposed any constraint on the child.
result = canvasSize;
}
return result;
}
private int measureHeight(int measureSpecHeight) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
result = specSize;
} else {
result = canvasSize;
}
return (result + 2);
}
public Bitmap drawableToBitmap(Drawable drawable) {
if (drawable == null) {
return null;
} else if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
}
Related
I have an Cirle imageview. I am setting the image to the ImageView from the camera and gallery. The problem is that when I set the image from the camera, the image looks too streched inside the circle image view.
Iam Resizing the image in order to avoid any memory leaks.
here is what i do:
CircleImageView.cs
public class CircleImageView : ImageView
{
private int borderWidth;
private int canvasSize;
private Bitmap image;
private Paint paint;
private Paint paintBorder;
public CircleImageView(Context context)
: this(context, null)
{
}
public CircleImageView(Context context, IAttributeSet attrs)
: this(context, attrs, Resource.Attribute.circularImageViewStyle)
{
}
public CircleImageView(Context context, IAttributeSet attrs, int defStyle)
: base(context, attrs, defStyle)
{
// init paint
paint = new Paint();
paint.AntiAlias = true;
paintBorder = new Paint();
paintBorder.AntiAlias = true;
// load the styled attributes and set their properties
TypedArray attributes = context.ObtainStyledAttributes(attrs, Resource.Styleable.CircularImageView, defStyle, 0);
if (attributes.GetBoolean(Resource.Styleable.CircularImageView_border, true))
{
int defaultBorderSize = (int)(4 * context.Resources.DisplayMetrics.Density+ 0.5f);
BorderWidth = attributes.GetDimensionPixelOffset(Resource.Styleable.CircularImageView_border_width, defaultBorderSize);
BorderColor = attributes.GetColor(Resource.Styleable.CircularImageView_border_color, Color.White);
}
if (attributes.GetBoolean(Resource.Styleable.CircularImageView_shadow, false))
{
addShadow();
}
}
public void addShadow()
{
SetLayerType(LayerType.Software, paintBorder);
paintBorder.SetShadowLayer(4.0f, 2.0f, 2.0f, Color.ParseColor("#82C341"));
}
public virtual int BorderWidth
{
set
{
this.borderWidth = 10;
this.RequestLayout();
this.Invalidate();
}
}
public virtual int BorderColor
{
set
{
if (paintBorder != null)
{
paintBorder.Color = Color.Gray;
}
this.Invalidate();
}
}
protected override void OnDraw(Canvas canvas)
{
// load the bitmap
image = drawableToBitmap(Drawable);
// init shader
if (image != null)
{
canvasSize = canvas.Width;
if (canvas.Height < canvasSize)
{
canvasSize = canvas.Height;
}
BitmapShader shader = new BitmapShader(Bitmap.CreateScaledBitmap(image, canvasSize, canvasSize, false), Shader.TileMode.Clamp, Shader.TileMode.Clamp);
paint.SetShader(shader);
// circleCenter is the x or y of the view's center
// radius is the radius in pixels of the cirle to be drawn
// paint contains the shader that will texture the shape
int circleCenter = (canvasSize - (borderWidth * 2)) / 2;
canvas.DrawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) + borderWidth - 4.0f, paintBorder);
canvas.DrawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) - 4.0f, paint);
}
}
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
SetMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec)
{
int result = 0;
var specMode = MeasureSpec.GetMode(measureSpec);
var specSize = MeasureSpec.GetSize(measureSpec);
if (specMode == MeasureSpecMode.Exactly)
{
// The parent has determined an exact size for the child.
result = specSize;
}
else if (specMode == MeasureSpecMode.AtMost)
{
// The child can be as large as it wants up to the specified size.
result = specSize;
}
else
{
// The parent has not imposed any constraint on the child.
result = canvasSize;
}
return result;
}
private int measureHeight(int measureSpecHeight)
{
int result = 0;
var specMode = MeasureSpec.GetMode(measureSpecHeight);
int specSize = MeasureSpec.GetSize(measureSpecHeight);
if (specMode == MeasureSpecMode.Exactly)
{
// We were told how big to be
result = specSize;
}
else if (specMode == MeasureSpecMode.AtMost)
{
// The child can be as large as it wants up to the specified size.
result = specSize;
}
else
{
// Measure the text (beware: ascent is a negative number)
result = canvasSize;
}
return (result + 2);
}
public virtual Bitmap drawableToBitmap(Drawable drawable)
{
if (drawable == null)
{
return null;
}
else if (drawable is BitmapDrawable)
{
return ((BitmapDrawable)drawable).Bitmap;
}
Bitmap bitmap = Bitmap.CreateBitmap(drawable.IntrinsicWidth, drawable.IntrinsicHeight, Bitmap.Config.Argb8888);
Canvas canvas = new Canvas(bitmap);
drawable.SetBounds(0, 0, canvas.Width, canvas.Height);
drawable.Draw(canvas);
return bitmap;
}
}
BitmapHelper.cs
public static Bitmap LoadAndResizeBitmap(this string fileName, int width, int height)
{
// First we get the the dimensions of the file on disk
BitmapFactory.Options options = new BitmapFactory.Options { InJustDecodeBounds = true };
BitmapFactory.DecodeFile(fileName, options);
// Next we calculate the ratio that we need to resize the image by
// in order to fit the requested dimensions.
int outHeight = options.OutHeight;
int outWidth = options.OutWidth;
int inSampleSize = 1;
if (outHeight > height || outWidth > width)
{
inSampleSize = outWidth > outHeight
? outHeight / height
: outWidth / width;
}
// Now we will load the image and have BitmapFactory resize it for us.
options.InSampleSize = inSampleSize;
options.InJustDecodeBounds = false;
Bitmap resizedBitmap = BitmapFactory.DecodeFile(fileName, options);
return resizedBitmap;
}
mylayout.xml
<Utilities.CircleImageView
android:layout_width="180dp"
android:layout_height="180dp"
android:id="#+id/imgProfileCircleImage"
android:src="#drawable/rapidicon"
custom:border="true"
custom:border_color="#d5d5d5"
custom:border_width="4dp"
custom:shadow="true"
android:layout_gravity="center"
android:minHeight="80dp"
android:minWidth="80dp" />
MainActivity
int imgheight = Resources.DisplayMetrics.HeightPixels;
int circleImgWidth = imgProfileCircleImage.Height;
AppHelper._bitmap = AppHelper._file.Path.LoadAndResizeBitmap(circleImgWidth, imgheight);
How do I set the image so that it looks perfectly fit to the imageview?
Try using Picasso or Glide to solve this issue easily
http://square.github.io/picasso/
I am working on android application in which i am using Bitmap, but the problem is that sometimes it shows me an error of out of memory and my application get crashed. I am using bitmaps along with BitmapShadder, my code is given below where my application shows this error.
public class CircularImageView extends ImageView {
private int borderWidth = 0;
private int viewWidth;
private int viewHeight;
private Bitmap image;
private Paint paint;
private Paint paintBorder;
private BitmapShader shader;
public CircularImageView(Context context) {
super(context);
setup();
}
public CircularImageView(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
public CircularImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setup();
}
private void setup() {
// init paint
paint = new Paint();
paint.setAntiAlias(true);
paintBorder = new Paint();
setBorderColor(Color.WHITE);
paintBorder.setAntiAlias(true);
this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
// paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);
}
public void setBorderWidth(int borderWidth) {
this.borderWidth = borderWidth;
this.invalidate();
}
public void setBorderColor(int borderColor) {
if (paintBorder != null)
paintBorder.setColor(borderColor);
this.invalidate();
}
private void loadBitmap() {
BitmapDrawable bitmapDrawable = (BitmapDrawable) this.getDrawable();
if (bitmapDrawable != null)
image = bitmapDrawable.getBitmap();
}
// #SuppressLint("DrawAllocation")
#Override
public void onDraw(Canvas canvas) {
// load the bitmap
loadBitmap();
// init shader
if (image != null) {
// Out Of Memory Error Comes Here....
shader = new BitmapShader(Bitmap.createScaledBitmap(image,canvas.getWidth(), canvas.getHeight(), false),Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
int circleCenter = viewWidth / 2;
// circleCenter is the x or y of the view's center
// radius is the radius in pixels of the cirle to be drawn
// paint contains the shader that will texture the shape
canvas.drawCircle(circleCenter + borderWidth, circleCenter
+ borderWidth, circleCenter + borderWidth - 4.0f,
paintBorder);
canvas.drawCircle(circleCenter + borderWidth, circleCenter
+ borderWidth, circleCenter - 4.0f, paint);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec, widthMeasureSpec);
viewWidth = width - (borderWidth * 2);
viewHeight = height - (borderWidth * 2);
setMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = viewWidth;
}
return result;
}
private int measureHeight(int measureSpecHeight, int measureSpecWidth) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = viewHeight;
}
return (result + 2);
}
}
Try this in your manifest application tag.
android:largeHeap="true"
I need to get circle images from rectangular/square images taken from network. In my application I get images with Volley's NetworkImageView. I found that fantastic library https://github.com/hdodenhof/CircleImageView but I don't understand how I can use it with NetworkImageView.
Can someone help me?
Check this Class
public class CirculaireNetworkImageView extends NetworkImageView {
private int borderWidth;
private int canvasSize;
private Bitmap image;
private Paint paint;
private Paint paintBorder;
public CirculaireNetworkImageView(final Context context) {
this(context, null);
}
public CirculaireNetworkImageView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.actionButtonStyle);
}
public CirculaireNetworkImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
paint = new Paint();
paint.setAntiAlias(true);
paintBorder = new Paint();
paintBorder.setAntiAlias(true);
}
public void setBorderWidth(int borderWidth) {
this.borderWidth = borderWidth;
this.requestLayout();
this.invalidate();
}
public void setBorderColor(int borderColor) {
if (paintBorder != null)
paintBorder.setColor(borderColor);
this.invalidate();
}
public void addShadow() {
setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);
}
#SuppressLint("DrawAllocation")
#Override
public void onDraw(Canvas canvas) {
// load the bitmap
image = drawableToBitmap(getDrawable());
// init shader
if (image != null) {
canvasSize = canvas.getWidth();
if(canvas.getHeight()<canvasSize)
canvasSize = canvas.getHeight();
BitmapShader shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvasSize, canvasSize, false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
// circleCenter is the x or y of the view's center
// radius is the radius in pixels of the cirle to be drawn
// paint contains the shader that will texture the shape
int circleCenter = (canvasSize - (borderWidth * 2)) / 2;
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) + borderWidth - 4.0f, paintBorder);
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) - 4.0f, paint);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
setMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// The parent has determined an exact size for the child.
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
// The child can be as large as it wants up to the specified size.
result = specSize;
} else {
// The parent has not imposed any constraint on the child.
result = canvasSize;
}
return result;
}
private int measureHeight(int measureSpecHeight) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
// The child can be as large as it wants up to the specified size.
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = canvasSize;
}
return (result + 2);
}
public Bitmap drawableToBitmap(Drawable drawable) {
if (drawable == null) {
return null;
} else if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
}
Check the source code of the NetworkImageView here. Modify it to extend your "CircleImageView" instead of the normal ImageView and you are done.
I am trying to use the support lib v4's RoundedBitmapDrawable in order to display Rounded bitmaps loaded asynchronously in ImageViews, either circled or rounded rectangles.
However, it looks like RoundedBitmapDrawable does not mesh very well with LayerDrawable :
If I try something like :
if (previousDrawable != null) {
final Drawable[] layers = new Drawable[2];
layers[0] = previousDrawable;
layers[1] = roundedDrawable;
TransitionDrawable drawable = new TransitionDrawable(layers);
view.setImageDrawable(drawable);
drawable.startTransition(3000);
} else {
view.setImageDrawable(roundedDrawable);
}
The TransitionDrawable launches but it does not respect the RoundedBitmapDrawable is not correctly displayed : its dimensions seems to shift somehow, if I set it to be a circle with :
RoundedBitmapDrawable roundedDrawable = RoundedBitmapDrawableFactory
.create(getResources(), bitmap);
roundedDrawable.setCornerRadius(bitmap.getHeight() / 2);
roundedDrawable.setAntiAlias(true);
It is displayed correctly if I use ImageView.setImageDrawable(), but it results in a rounded rectangle if a TransitionDrawable displays it.
Does anybody has any idea why this display problem happen ?
Set
roundedDrawable.setCircular(true);
then it works fine
Use Universal Image loader to fix your issue
https://github.com/nostra13/Android-Universal-Image-Loader
This is my solution to create a rounded image:
package com.campusapp;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
public class CircularImageView extends ImageView {
private int borderWidth;
private int canvasSize;
private Bitmap image;
private Paint paint;
private Paint paintBorder;
public CircularImageView(final Context context) {
this(context, null);
}
public CircularImageView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.circularImageViewStyle);
}
public CircularImageView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
// init paint
paint = new Paint();
paint.setAntiAlias(true);
paintBorder = new Paint();
paintBorder.setAntiAlias(true);
// load the styled attributes and set their properties
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.CircularImageView, defStyle, 0);
if(attributes.getBoolean(R.styleable.CircularImageView_border, true))
{
int defaultBorderSize = (int) (4 * getContext().getResources().getDisplayMetrics().density + 0.5f);
setBorderWidth(attributes.getDimensionPixelOffset(R.styleable.CircularImageView_border_width, defaultBorderSize));
setBorderColor(attributes.getColor(R.styleable.CircularImageView_border_color, Color.WHITE));
}
if(attributes.getBoolean(R.styleable.CircularImageView_shadow, false))
addShadow();
}
public void setBorderWidth(int borderWidth)
{
this.borderWidth = borderWidth;
this.requestLayout();
this.invalidate();
}
public void setBorderColor(int borderColor)
{
if (paintBorder != null)
paintBorder.setColor(borderColor);
this.invalidate();
}
public void addShadow()
{
setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);
}
#Override
public void onDraw(Canvas canvas)
{
// load the bitmap
image = drawableToBitmap(getDrawable());
// init shader
if (image != null)
{
canvasSize = canvas.getWidth();
if(canvas.getHeight()<canvasSize)
canvasSize = canvas.getHeight();
BitmapShader shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvasSize, canvasSize, false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
// circleCenter is the x or y of the view's center
// radius is the radius in pixels of the cirle to be drawn
// paint contains the shader that will texture the shape
int circleCenter = (canvasSize - (borderWidth * 2)) / 2;
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) + borderWidth - 4.0f, paintBorder);
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) - 4.0f, paint);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
setMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec)
{
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY)
{
// The parent has determined an exact size for the child.
result = specSize;
}
else if (specMode == MeasureSpec.AT_MOST)
{
// The child can be as large as it wants up to the specified size.
result = specSize;
}
else
{
// The parent has not imposed any constraint on the child.
result = canvasSize;
}
return result;
}
private int measureHeight(int measureSpecHeight)
{
int result = 0;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY)
{
// We were told how big to be
result = specSize;
}
else if (specMode == MeasureSpec.AT_MOST)
{
// The child can be as large as it wants up to the specified size.
result = specSize;
}
else
{
// Measure the text (beware: ascent is a negative number)
result = canvasSize;
}
return (result + 2);
}
public Bitmap drawableToBitmap(Drawable drawable)
{
if (drawable == null)
{
return null;
}
else if (drawable instanceof BitmapDrawable)
{
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
}
After creating the class, replace your ImageView with the code below:
<com.yourpkg.CircularImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:src="#drawable/your_image"
app:border_color="#EEEEEE"
app:border_width="4dp"
app:shadow="true" />
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;
}
or you can see this also
I am using circularimageView to display the picture of a person. Here's the class.
public class CircularImageView extends ImageView {
private int borderWidth = 4;
private int viewWidth;
private int viewHeight;
private Bitmap image;
private Paint paint;
private Paint paintBorder;
private BitmapShader shader;
public CircularImageView(Context context) {
super(context);
setup();
}
public CircularImageView(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
public CircularImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setup();
}
private void setup() {
// init paint
paint = new Paint();
paintBorder = new Paint();
paint.setAntiAlias(true);
setBorderColor(Color.WHITE);
paintBorder.setAntiAlias(true);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
}
else
{
}
paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);
}
public void setBorderWidth(int borderWidth) {
this.borderWidth = borderWidth;
this.invalidate();
}
public void setBorderColor(int borderColor) {
if (paintBorder != null)
paintBorder.setColor(borderColor);
this.invalidate();
}
private void loadBitmap() {
BitmapDrawable bitmapDrawable = (BitmapDrawable) this.getDrawable();
if (bitmapDrawable != null)
image = bitmapDrawable.getBitmap();
}
#SuppressLint("DrawAllocation")
#Override
public void onDraw(Canvas canvas) {
// load the bitmap
loadBitmap();
// init shader
if (image != null) {
shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvas.getWidth(), canvas.getHeight(), false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
int circleCenter = viewWidth / 2;
// circleCenter is the x or y of the view's center
// radius is the radius in pixels of the cirle to be drawn
// paint contains the shader that will texture the shape
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter + borderWidth - 4.0f, paintBorder);
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter - 4.0f, paint);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec, widthMeasureSpec);
viewWidth = width - (borderWidth * 2);
viewHeight = height - (borderWidth * 2);
setMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = viewWidth;
}
return result;
}
private int measureHeight(int measureSpecHeight, int measureSpecWidth) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = viewHeight;
}
return (result + 2);
}
}
It works fine in anything > API 10 but in other cases the image gets stretched out and only the top left part of the image is visible and is pixelated. I tried Resizing the bitmap of the picture but it did not help.
Here is the bitmap initialization
PackageManager m = getActivity().getPackageManager();
String s = getActivity().getPackageName();
PackageInfo p = null;
try {
p = m.getPackageInfo(s, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
s = p.applicationInfo.dataDir;
//String root = Environment.getExternalStorageDirectory().toString();
s += "/player_photos/" + player.getPlayerId() + ".png";
Bitmap bMap = BitmapFactory.decodeFile(s);
Resources res = getResources();
BitmapDrawable icon = new BitmapDrawable(res, bMap);
playerDP.setImageDrawable(icon);
}