I am working on an Android application in which I am doing rounded image view. It is working fine with some images, but for the images like 160x120 resolution it shows an oval shaped.
My code for the custom imageview is given below:
public class RoundImage extends Drawable {
private final Bitmap mBitmap;
private final Paint mPaint;
private final RectF mRectF;
private final int mBitmapWidth;
private final int mBitmapHeight;
public RoundImage(Bitmap bitmap) {
mBitmap = bitmap;
mRectF = new RectF();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
final BitmapShader shader = new BitmapShader(bitmap,
Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint.setShader(shader);
mBitmapWidth = mBitmap.getWidth();
mBitmapHeight = mBitmap.getHeight();
}
#Override
public void draw(Canvas canvas) {
canvas.drawOval(mRectF, mPaint);
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mRectF.set(bounds);
}
#Override
public void setAlpha(int alpha) {
if (mPaint.getAlpha() != alpha) {
mPaint.setAlpha(alpha);
invalidateSelf();
}
}
#Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
#Override
public int getIntrinsicWidth() {
return mBitmapWidth;
}
#Override
public int getIntrinsicHeight() {
return mBitmapHeight;
}
public void setAntiAlias(boolean aa) {
mPaint.setAntiAlias(aa);
invalidateSelf();
}
#Override
public void setFilterBitmap(boolean filter) {
mPaint.setFilterBitmap(filter);
invalidateSelf();
}
#Override
public void setDither(boolean dither) {
mPaint.setDither(dither);
invalidateSelf();
}
public Bitmap getBitmap() {
return mBitmap;
}
}
// My main Activity Class
public class MainActivity extends Activity {
ImageView imageView1, imageView2;
RoundImage roundedImage, roundedImage1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView1 = (ImageView) findViewById(R.id.imageView1);
Bitmap bm = BitmapFactory.decodeResource(getResources(),R.drawable.tt);
roundedImage = new RoundImage(bm);
imageView1.setImageDrawable(roundedImage);
}
}
// My xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/White"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="100dp"
android:layout_height="100dp"
android:scaleType="centerCrop"
android:layout_gravity="center"
android:background="#color/Brown"
android:src="#drawable/image" />
</LinearLayout>
Add this gradle in your android project
compile 'com.mikhaellopez:circularimageview:3.0.2'
and added this line in your xml file (layout files)
<com.mikhaellopez.circularimageview.CircularImageView
android:layout_width="250dp"
android:layout_height="250dp"
android:src="#drawable/image"
app:civ_border_color="#EEEEEE"
app:civ_border_width="4dp"
app:civ_shadow="true"
app:civ_shadow_radius="10"
app:civ_shadow_color="#8BC34A"/>
In your java code
CircularImageView circularImageView = (CircularImageView)findViewById(R.id.yourCircularImageView);
// Set Border
circularImageView.setBorderColor(getResources().getColor(R.color.GrayLight));
circularImageView.setBorderWidth(10);
// Add Shadow with default param
circularImageView.addShadow();
// or with custom param
circularImageView.setShadowRadius(15);
circularImageView.setShadowColor(Color.RED);
From here
First of all use Picasso image loading library, for that you have to add one dependency like in build.gradle:
compile 'com.squareup.picasso:picasso:2.5.2'
than create a seperate class called "CircleTransform" for displaying image into round shape and implements interface "Transformation"
than add following conde into it.
#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";
}
After that you can set image into imageview like this :
Picasso.with(this)
.load(R.drawable.tt)
.transform(new CircleTransform())
.into(imageView1);
That's it. i hope it helps.
Related
i want to display an image with rounded corned, So i use this function
> public class RoundedImage extends Drawable {
private final Bitmap mBitmap;
private final Paint mPaint;
private final RectF mRectF;
private final int mBitmapWidth;
private final int mBitmapHeight;
public RoundedImage(Bitmap bitmap) {
mBitmap = bitmap;
mRectF = new RectF();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
final BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint.setShader(shader);
mBitmapWidth = mBitmap.getWidth();
mBitmapHeight = mBitmap.getHeight();
}
#Override
public void draw(Canvas canvas) {
canvas.drawRoundRect(mRectF, 10, 10, mPaint);
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mRectF.set(bounds);
}
#Override
public void setAlpha(int alpha) {
if (mPaint.getAlpha() != alpha) {
mPaint.setAlpha(alpha);
invalidateSelf();
}
}
#Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
#Override
public int getIntrinsicWidth() {
return mBitmapWidth;
}
#Override
public int getIntrinsicHeight() {
return mBitmapHeight;
}
public void setAntiAlias(boolean aa) {
mPaint.setAntiAlias(aa);
invalidateSelf();
}
#Override
public void setFilterBitmap(boolean filter) {
mPaint.setFilterBitmap(filter);
invalidateSelf();
}
#Override
public void setDither(boolean dither) {
mPaint.setDither(dither);
invalidateSelf();
}
public Bitmap getBitmap() {
return mBitmap;
}
}
the problem, when i make the scaled type of the image view fitXY, i can'see just a part of the image with the rounded corner.
but when i use an other scaled type i have poblems with the rounded corner.
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;
}
Note: I know there are a lot of questions and repositories about this, but none seems to fit what I try to achieve.
Background
Given a bitmap of any aspect-ratio, I wish to set it as the content of an ImageView (using a drawable only, without extending the ImageView), so that the content will be center-cropped, and yet in the shape of a circle.
All of this, with minimal memory usage, because the images could be quite large sometimes. I do not want to create a whole new Bitmap just for this. The content is already there...
The problem
All solutions I've found lack one of the things I've written: some do not center-crop, some assume the image is square-shaped, some create a new bitmap from the given bitmap...
What I've tried
Other than trying various repositories, I've tried this tutorial, and I tried to fix it for the case of non-square aspect ratios, but I've failed.
Here's its code, in case the website will get closed:
public class RoundImage extends Drawable {
private final Bitmap mBitmap;
private final Paint mPaint;
private final RectF mRectF;
private final int mBitmapWidth;
private final int mBitmapHeight;
public RoundImage(Bitmap bitmap) {
mBitmap = bitmap;
mRectF = new RectF();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
final BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint.setShader(shader);
mBitmapWidth = mBitmap.getWidth();
mBitmapHeight = mBitmap.getHeight();
}
#Override
public void draw(Canvas canvas) {
canvas.drawOval(mRectF, mPaint);
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mRectF.set(bounds);
}
#Override
public void setAlpha(int alpha) {
if (mPaint.getAlpha() != alpha) {
mPaint.setAlpha(alpha);
invalidateSelf();
}
}
#Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
#Override
public int getIntrinsicWidth() {
return mBitmapWidth;
}
#Override
public int getIntrinsicHeight() {
return mBitmapHeight;
}
public void setAntiAlias(boolean aa) {
mPaint.setAntiAlias(aa);
invalidateSelf();
}
#Override
public void setFilterBitmap(boolean filter) {
mPaint.setFilterBitmap(filter);
invalidateSelf();
}
#Override
public void setDither(boolean dither) {
mPaint.setDither(dither);
invalidateSelf();
}
public Bitmap getBitmap() {
return mBitmap;
}
}
A very good solution I've found (here) does exactly what I need, except it uses it all in the ImageView itself, instead of creating a drawable. This means that I can't set it, for example, as the background of a view.
The question
How can I achieve this?
EDIT: this is the current code, and as I wanted to add border, it also has this code for it:
public class SimpleRoundedDrawable extends BitmapDrawable {
private final Path p = new Path();
private final Paint mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
public SimpleRoundedDrawable(final Resources res, final Bitmap bitmap) {
super(res, bitmap);
mBorderPaint.setStyle(Paint.Style.STROKE);
}
public SimpleRoundedDrawable setBorder(float borderWidth, #ColorInt int borderColor) {
mBorderPaint.setStrokeWidth(borderWidth);
mBorderPaint.setColor(borderColor);
invalidateSelf();
return this;
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
p.rewind();
p.addCircle(bounds.width() / 2,
bounds.height() / 2,
Math.min(bounds.width(), bounds.height()) / 2,
Path.Direction.CW);
}
#Override
public void draw(Canvas canvas) {
canvas.clipPath(p);
super.draw(canvas);
final float width = getBounds().width(), height = getBounds().height();
canvas.drawCircle(width / 2, height / 2, Math.min(width, height) / 2, mBorderPaint);
}
}
I hope this is how things should really work.
EDIT: It seems that the solution works only from specific Android version, as it doesn't work on Android 4.2.2. Instead, it shows a squared image.
EDIT: it seems that the above solution is also much less efficient than using BitmapShader (Link here). It would be really great to know how to use it within a drawable instead of within a customized ImageView
--
Here's the current modified version of the below solutions. I hope it will be handy for some people:
public class SimpleRoundedDrawable extends Drawable {
final Paint mMaskPaint = new Paint(Paint.ANTI_ALIAS_FLAG), mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
Bitmap mBitmap;
int mSide;
float mRadius;
public SimpleRoundedDrawable() {
this(null);
}
public SimpleRoundedDrawable(Bitmap bitmap) {
this(bitmap, 0, 0);
}
public SimpleRoundedDrawable(Bitmap bitmap, float width, #ColorInt int color) {
mBorderPaint.setStyle(Paint.Style.STROKE);
mBitmap = bitmap;
mSide = mBitmap == null ? 0 : Math.min(bitmap.getWidth(), bitmap.getHeight());
mBorderPaint.setStrokeWidth(width);
mBorderPaint.setColor(color);
}
public SimpleRoundedDrawable setBitmap(final Bitmap bitmap) {
mBitmap = bitmap;
mSide = Math.min(bitmap.getWidth(), bitmap.getHeight());
invalidateSelf();
return this;
}
public SimpleRoundedDrawable setBorder(float width, #ColorInt int color) {
mBorderPaint.setStrokeWidth(width);
mBorderPaint.setColor(color);
invalidateSelf();
return this;
}
#Override
protected void onBoundsChange(Rect bounds) {
if (mBitmap == null)
return;
Matrix matrix = new Matrix();
RectF src = new RectF(0, 0, mSide, mSide);
src.offset((mBitmap.getWidth() - mSide) / 2f, (mBitmap.getHeight() - mSide) / 2f);
RectF dst = new RectF(bounds);
final float strokeWidth = mBorderPaint.getStrokeWidth();
if (strokeWidth > 0)
dst.inset(strokeWidth, strokeWidth);
matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER);
Shader shader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
shader.setLocalMatrix(matrix);
mMaskPaint.setShader(shader);
matrix.mapRect(src);
mRadius = src.width() / 2f;
}
#Override
public void draw(Canvas canvas) {
Rect b = getBounds();
if (mBitmap != null)
canvas.drawCircle(b.exactCenterX(), b.exactCenterY(), mRadius, mMaskPaint);
final float strokeWidth = mBorderPaint.getStrokeWidth();
if (strokeWidth > 0)
canvas.drawCircle(b.exactCenterX(), b.exactCenterY(), mRadius + strokeWidth / 2, mBorderPaint);
}
#Override
public void setAlpha(int alpha) {
mMaskPaint.setAlpha(alpha);
invalidateSelf();
}
#Override
public void setColorFilter(ColorFilter cf) {
mMaskPaint.setColorFilter(cf);
invalidateSelf();
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
If I'm following you correctly, your Drawable class would be like so:
public class CroppedDrawable extends BitmapDrawable {
private Path p = new Path();
public CroppedDrawable(Bitmap b) {
super(b);
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
p.rewind();
p.addCircle(bounds.width() / 2,
bounds.height() / 2,
Math.min(bounds.width(), bounds.height()) / 2,
Path.Direction.CW);
}
#Override
public void draw(Canvas canvas) {
canvas.clipPath(p);
super.draw(canvas);
}
}
An example usage would be:
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.mila);
CroppedDrawable cd = new CroppedDrawable(bitmap);
imageView.setImageDrawable(cd);
Which, with your previous sample image, would give something like this:
try this minimalist custom Drawable and modify it to meet your needs:
class D extends Drawable {
Bitmap bitmap;
Paint maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
Paint borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
int side;
float radius;
public D(Bitmap wrappedBitmap) {
bitmap = wrappedBitmap;
borderPaint.setStyle(Paint.Style.STROKE);
borderPaint.setStrokeWidth(16);
borderPaint.setColor(0xcc220088);
side = Math.min(bitmap.getWidth(), bitmap.getHeight());
}
#Override
protected void onBoundsChange(Rect bounds) {
Matrix matrix = new Matrix();
RectF src = new RectF(0, 0, side, side);
src.offset((bitmap.getWidth() - side) / 2f, (bitmap.getHeight() - side) / 2f);
RectF dst = new RectF(bounds);
dst.inset(borderPaint.getStrokeWidth(), borderPaint.getStrokeWidth());
matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER);
Shader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
shader.setLocalMatrix(matrix);
maskPaint.setShader(shader);
matrix.mapRect(src);
radius = src.width() / 2f;
}
#Override
public void draw(Canvas canvas) {
Rect b = getBounds();
canvas.drawCircle(b.exactCenterX(), b.exactCenterY(), radius, maskPaint);
canvas.drawCircle(b.exactCenterX(), b.exactCenterY(), radius + borderPaint.getStrokeWidth() / 2, borderPaint);
}
#Override public void setAlpha(int alpha) {}
#Override public void setColorFilter(ColorFilter cf) {}
#Override public int getOpacity() {return PixelFormat.TRANSLUCENT;}
}
As it seems, using "clipPath" isn't efficient and needs to have hardware-acceleration disabled on 4.3 and below.
A better solution is to use something like on this library, using BitmapShader :
https://github.com/hdodenhof/CircleImageView
which is based on :
http://www.curious-creature.com/2012/12/11/android-recipe-1-image-with-rounded-corners/
The relevant code is:
BitmapShader shader;
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);
RectF rect = new RectF(0.0f, 0.0f, width, height);
// rect contains the bounds of the shape
// radius is the radius in pixels of the rounded corners
// paint contains the shader that will texture the shape
canvas.drawRoundRect(rect, radius, radius, paint);
I still wish to know how to do it all in a drawable, if the input is a bitmap.
A quick draft of a CircleImageDrawable based on my CircleImageView library. This does not create a new Bitmap, uses a BitmapShader to achieve the desired effect and center-crops the image.
public class CircleImageDrawable extends Drawable {
private final RectF mBounds = new RectF();
private final RectF mDrawableRect = new RectF();
private final RectF mBorderRect = new RectF();
private final Matrix mShaderMatrix = new Matrix();
private final Paint mBitmapPaint = new Paint();
private final Paint mBorderPaint = new Paint();
private int mBorderColor = Color.BLACK;
private int mBorderWidth = 0;
private Bitmap mBitmap;
private BitmapShader mBitmapShader;
private int mBitmapWidth;
private int mBitmapHeight;
private float mDrawableRadius;
private float mBorderRadius;
public CircleImageDrawable(Bitmap bitmap) {
mBitmap = bitmap;
mBitmapHeight = mBitmap.getHeight();
mBitmapWidth = mBitmap.getWidth();
}
#Override
public void draw(Canvas canvas) {
canvas.drawCircle(mBounds.width() / 2.0f, mBounds.height() / 2.0f, mDrawableRadius, mBitmapPaint);
if (mBorderWidth != 0) {
canvas.drawCircle(mBounds.width() / 2.0f, mBounds.height() / 2.0f, mBorderRadius, mBorderPaint);
}
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mBounds.set(bounds);
setup();
}
private void setup() {
mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mBitmapPaint.setAntiAlias(true);
mBitmapPaint.setShader(mBitmapShader);
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setAntiAlias(true);
mBorderPaint.setColor(mBorderColor);
mBorderPaint.setStrokeWidth(mBorderWidth);
mBorderRect.set(mBounds);
mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f);
mDrawableRect.set(mBorderRect);
mDrawableRect.inset(mBorderWidth, mBorderWidth);
mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f);
updateShaderMatrix();
invalidateSelf();
}
private void updateShaderMatrix() {
float scale;
float dx = 0;
float dy = 0;
mShaderMatrix.set(null);
if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
scale = mDrawableRect.height() / (float) mBitmapHeight;
dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
} else {
scale = mDrawableRect.width() / (float) mBitmapWidth;
dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
}
mShaderMatrix.setScale(scale, scale);
mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);
mBitmapShader.setLocalMatrix(mShaderMatrix);
}
#Override
public void setAlpha(int alpha) {
mBitmapPaint.setAlpha(alpha);
invalidateSelf();
}
#Override
public void setColorFilter(ColorFilter colorFilter) {
mBitmapPaint.setColorFilter(colorFilter);
invalidateSelf();
}
#Override
public int getOpacity() {
return 0;
}
}
There is already a built-in way to accomplish this and it's 1 line of code (ThumbnailUtils.extractThumbnail())
int dimension = getSquareCropDimensionForBitmap(bitmap);
bitmap = ThumbnailUtils.extractThumbnail(bitmap, dimension, dimension);
...
//I added this method because people keep asking how
//to calculate the dimensions of the bitmap...see comments below
public int getSquareCropDimensionForBitmap(Bitmap bitmap)
{
//If the bitmap is wider than it is tall
//use the height as the square crop dimension
if (bitmap.getWidth() >= bitmap.getHeight())
{
dimension = bitmap.getHeight();
}
//If the bitmap is taller than it is wide
//use the width as the square crop dimension
else
{
dimension = bitmap.getWidth();
}
}
If you want the bitmap object to be recycled, you can pass options that make it so:
bitmap = ThumbnailUtils.extractThumbnail(bitmap, dimension, dimension, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
Below is the link for the documentation:
ThumbnailUtils Documentation
I am using RoundedImageView by vinc3m1 and I am trying to create an image that has a bitmap in it.
I want the ImageView to be rounded but not the bitmap I place into it, like in this pic:
However, this is the result I am getting:
I use padding on the RoundedImageView to achieve this, the View is in a View which contains it and a label; I use the padding in code like this:
int dpPadding = Utils.dpToPx(25);
view.getImage().setPadding(dpPadding,dpPadding,dpPadding,dpPadding);
and I see the padding, but I don't want the image inside to have the rounded corners, only the background.
Though it might not be the best way, can any one help?
Scale down your image and add a border to it (to fill the space left by the scaling).
You can do it using Bitmap.createScaledBitmap.
To add the border to it, you can create a "white" image with the original size and then combine the two images by overlaying them.
Then save it and use it in your RoundedImageView.
You can use this...
public class RoundImage extends Drawable {
private final Bitmap mBitmap;
private final Paint mPaint;
private final RectF mRectF;
private final int mBitmapWidth;
private final int mBitmapHeight;
public RoundImage(Bitmap bitmap) {
mBitmap = bitmap;
mRectF = new RectF();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
final BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
mPaint.setShader(shader);
mBitmapWidth = (int) 240;
mBitmapHeight = (int) 240;
}
#Override
public void draw(Canvas canvas) {
canvas.drawOval(mRectF, mPaint);
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mRectF.set(bounds);
}
#Override
public void setAlpha(int alpha) {
if (mPaint.getAlpha() != alpha) {
mPaint.setAlpha(alpha);
invalidateSelf();
}
}
#Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
#Override
public int getIntrinsicWidth() {
return mBitmapWidth;
}
#Override
public int getIntrinsicHeight() {
return mBitmapHeight;
}
public void setAntiAlias(boolean aa) {
mPaint.setAntiAlias(aa);
invalidateSelf();
}
#Override
public void setFilterBitmap(boolean filter) {
mPaint.setFilterBitmap(filter);
invalidateSelf();
}
#Override
public void setDither(boolean dither) {
mPaint.setDither(dither);
invalidateSelf();
}
public Bitmap getBitmap() {
return mBitmap;
}
enter code here
}
// Use like this
imageview.setBackgroundDrawable(new RoundImage(bitmapimage));
i use this method to add some padding to my image :
.RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.makeramen.roundedimageview.RoundedImageView
android:layout_width="90dp"
android:layout_height="90dp"
android:scaleType="fitCenter"
android:src="#color/transparent"
app:riv_border_color="#color/colorWhite"
app:riv_border_width="2dip"
app:riv_corner_radius="25dp"
app:riv_oval="true" />
<ImageView
android:id="#+id/listimage"
android:layout_width="90dp"
android:layout_height="90dp"
android:padding="16dp"
android:src="#drawable/search" />
</RelativeLayout>`
I am looking at using the Picasso library to download an image from URL and pass this into circle image view, but since picasso requires that you pass in an actual imageView I have come to a standstill on how to do it
I am using the picasso library from here http://square.github.io/picasso/
and the circle image view class from here https://github.com/hdodenhof/CircleImageView
Here is the start of my code to get the image
private void getData() {
userName.setText(prefs.getString("userName",""));
jobTitle.setText(prefs.getString("profile",""));
userLocation.setText(prefs.getString("location",""));
// ??????
// Picasso.with(context).load(image link here).into(imageview here);
//CircleImageView img = new CircleImageView(this);
//img.setImageResource();
//img.setImageBitmap();
//img.setImageDrawable();
//img.setImageURI();
}
Edit:
here is the xml for the circleImageView
<michael.CircleImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#drawable/shadow"
android:layout_gravity="center"
android:layout_marginTop="16dp"
app:border_width="2dp"
app:border_color="#274978"
android:id="#+id/circleImageView"
I don't think you require CircleImageView library
You can implement Circular Transformation check the below gist
https://gist.github.com/julianshen/5829333
then
Picasso.with(activity).load(image link here)
.transform(new CircleTransform()).into(ImageView);
Use This
Activity Class
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String imageUrl = "https://www.baby-connect.com/images/baby2.gif";
CircleImageView imageView = (CircleImageView) findViewById(R.id.image);
Picasso.with(getApplicationContext()).load(imageUrl)
.placeholder(R.drawable.images).error(R.drawable.ic_launcher)
.into(imageView);
}
}
Layout File
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/image"
android:layout_width="160dp"
android:layout_height="160dp"
android:layout_centerInParent="true"
android:src="#drawable/images"
app:border_color="#ffffff"
app:border_width="2dp" />
This is Working fine.
Use this code to create Circular Imageview ....
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"));
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;
}
}
Take the ID of CircleImageView first :
CircleImageView mCircleImageView = (CircleImageView)findViewById(R.id.circleImageView);
And pass the ID to Picasso library :
Picasso.with(mContext).load(Uri.parse(link)).placeholder(drawable).into(mCircleImageView);
This worked for me.
I have created a target class that uses native Android's RoundedBitmapDrawable class to make image round (removes the need to add a circle transform class to code), see solution below:
public class RoundedImageBitmapTarget implements Target {
private final Context context;
private final ImageView view;
public RoundedImageBitmapTarget(Context context, ImageView view) {
this.context = context;
this.view = view;
}
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
setBitmap(bitmap);
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
setBitmap(((BitmapDrawable) errorDrawable).getBitmap());
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
setBitmap(((BitmapDrawable) placeHolderDrawable).getBitmap());
}
public void setBitmap(Bitmap bitmap) {
view.setImageDrawable(getRoundBitmap(context, bitmap));
}
public static RoundedBitmapDrawable getRoundBitmap(Context context, Bitmap bitmap) {
Resources res = context.getResources();
RoundedBitmapDrawable round = RoundedBitmapDrawableFactory.create(res, bitmap);
round.setCircular(true);
round.setTargetDensity(context.getResources().getDisplayMetrics());
return round;
}
public static void load(Context context, ImageView view, String url, int size, #DrawableRes int placeholder) {
RoundedImageBitmapTarget target;
Picasso.with(context).load(url)
.resize(0, size)
.placeholder(placeholder)
.error(placeholder)
.into(target = new RoundedImageBitmapTarget(context, view));
view.setTag(target);
}
}
I want a square image to be converted to circular image and displayed in the imageview. Image 1 is the required output, image two is the sqaure source image and image3 is the current output from the code pasted below. Code for cropping square image and than converting into circular image is pasted below. Please have a look at it and correct it.
private Bitmap cutCenterSquare(Bitmap bitmap) {
Bitmap origialBitmap = bitmap;
Bitmap cutBitmap = Bitmap.createBitmap(origialBitmap.getWidth() / 2,
origialBitmap.getHeight() / 2, Config.ARGB_8888);
Canvas canvas = new Canvas(cutBitmap);
Rect desRect = new Rect(0,0,(int)(imageview.getWidth()*0.94-imageview.getWidth()*0.06),(int)(imageview.getHeight()*0.725-imageview.getHeight()*0.16));
Rect srcRect = new Rect((int)(imageview.getWidth()*0.06),(int)(imageview.getHeight()*0.16),
(int)(imageview.getWidth()*0.94),
(int)(imageview.getHeight()*0.725));
canvas.drawBitmap(origialBitmap, srcRect, desRect, null);
return cutBitmap;
}
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(), Bitmap.Config.ARGB_8888);
final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight());
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
paint.setColor(Color.parseColor("#646464"));
Canvas c = new Canvas(output);
c.drawARGB(0, 0, 0, 0);
c.drawCircle(sbmp.getWidth() / 2+0.7f, sbmp.getHeight() / 2+0.7f, sbmp.getWidth() / 2+0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
c.drawBitmap(sbmp, rect, rect, paint);
return output;
}
<ImageView
android:id="#+id/profile_image"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_gravity="center"
android:layout_marginBottom="8dp"
android:layout_marginTop="24dp"
android:background="#drawable/background_circle"
android:contentDescription=""
android:scaleType="centerCrop"/>
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="#646464"/>
<size
android:width="1dp"
android:height="1dp"/>
</shape>
Pay attention to your code. You are using 2 bitmaps in memory.
There is a very interesting post about image with rounded corners: http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/
It is written by Romain Guy (ex android team at Google).
You can write a circular bitmap with a similar code:
public class CircleDrawable extends Drawable {
private final BitmapShader mBitmapShader;
private final Paint mPaint;
private Paint mWhitePaint;
int circleCenterX;
int circleCenterY;
int mRadus;
private boolean mUseStroke = false;
private int mStrokePadding = 0;
public CircleDrawable(Bitmap bitmap) {
mBitmapShader = new BitmapShader(bitmap,
Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setShader(mBitmapShader);
}
public CircleDrawable(Bitmap bitmap, boolean mUseStroke) {
this(bitmap);
if (mUseStroke) {
this.mUseStroke = true;
mStrokePadding = 4;
mWhitePaint = new Paint();
mWhitePaint.setStyle(Paint.Style.FILL_AND_STROKE);
mWhitePaint.setStrokeWidth(0.75f);
mWhitePaint.setColor(Color.WHITE);
}
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
circleCenterX = bounds.width() / 2;
circleCenterY = bounds.height() / 2;
if (bounds.width() >= bounds.height())
mRadus = bounds.width() / 2;
else
mRadus = bounds.height() / 2;
}
#Override
public void draw(Canvas canvas) {
if (mUseStroke) {
canvas.drawCircle(circleCenterX, circleCenterY, mRadus, mWhitePaint);
}
canvas.drawCircle(circleCenterX, circleCenterY, mRadus - mStrokePadding, 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);
}
public boolean ismUseStroke() {
return mUseStroke;
}
public void setmUseStroke(boolean mUseStroke) {
this.mUseStroke = mUseStroke;
}
}
To use it:
CircleDrawable circle = new CircleDrawable(bitmap,true);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
imageView.setBackground(circle);
else
imageView.setBackgroundDrawable(circle);
You can take a look into this project in github. It provides a way to set an image in XML and programmatically, and displays a resizable circular crop window on top of the image. Calling the method getCroppedCircleImage() will then return the Circle Bitmap marked by the circular crop window.
Maybe this could come in handy.
CIrcleImageCropper
Sathya