Android display image in image view with rounded corner - android

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;
}

Related

Drawing a bitmap in circle and fill outside color canvas not working

I want to draw image inside circle with bitmap and fill color outside.
I have extended AppCompatImageView and override onDraw method, but it displays white circle inside canvas.
following is my class :
class ImageMagnifier2 extends AppCompatImageView {
public ImageMagnifier2(final Context context) {
super(context);
init();
}
#Override
public boolean dispatchTouchEvent(MotionEvent me) {
// Call onTouchEvent of SimpleGestureFilterLongPress class
return super.dispatchTouchEvent(me);
}
private void init() {
setWillNotDraw(false);
setLayerType(LAYER_TYPE_HARDWARE, null);
zoomPos = new PointF(0, 0);
matrix = new Matrix();
paint = new Paint();
paintBackground = new Paint();
paint.setColor(getResources().getColor(android.R.color.transparent));
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!zooming) {
buildDrawingCache();
} else {
bitmap = getDrawingCache();
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
matrix.reset();
matrix.postScale(2f, 2f, zoomPos.x, zoomPos.y);
paint.getShader().setLocalMatrix(matrix);
paintBackground.setColor(Color.parseColor("#F227aae0"));//F227aae0
paintBackground.setStyle(Paint.Style.FILL);
paintBackground.setAntiAlias(true);
Rect rectangle = new Rect( 0, 0, canvas.getWidth(), canvas.getHeight() );
canvas.drawRect(rectangle,paintBackground);
canvas.drawCircle(zoomPos.x, zoomPos.y, sizeOfMagnifier - 5, paint);
}
}
It working fine when draw bitmap without outside rectangle or canvas fill color. but i need to fill outside color with bitmap.
Thank you for help in advance.
The following is a code the I wrote previously when I had the same issues, You may want to use the following class:
public class CircleImageView extends AppCompatImageView {
private RectF drawableRect = new RectF();
private Matrix shaderMatrix = new Matrix();
private Paint bmpPaint = new Paint();
private Paint backgroundPaint = new Paint();
private Bitmap bmp;
private int bmpWidth, bmpHeight;
private BitmapShader bmpShader;
private float radius;
public CircleImageView(Context context) {
super(context);
setScaleType(ScaleType.CENTER_CROP);
backgroundPaint.setStyle(Paint.Style.FILL);
backgroundPaint.setColor(Color.TRANSPARENT);
init();
}
#Override
protected void onDraw(Canvas canvas) {
if (bmp == null) return;
canvas.drawPaint(backgroundPaint);
canvas.drawCircle(drawableRect.centerX(), drawableRect.centerY(), radius, bmpPaint);
}
private Bitmap getBitmapFromDrawable(Drawable drawable) {
if (drawable == null) return null;
if (drawable instanceof BitmapDrawable) return ((BitmapDrawable) drawable).getBitmap();
try {
Bitmap bitmap;
if (drawable instanceof ColorDrawable) bitmap = Bitmap.createBitmap(5, 5, Bitmap.Config.ARGB_8888);
else 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;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private void initImage() {
bmp = getBitmapFromDrawable(getDrawable());
init();
}
private void init() {
if (getWidth() == 0 && getHeight() == 0) return;
if (bmp == null) {invalidate();return;}
bmpShader = new BitmapShader(bmp, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
bmpPaint.setAntiAlias(true);
bmpPaint.setShader(bmpShader);
bmpHeight = bmp.getHeight();
bmpWidth = bmp.getWidth();
drawableRect.set(new RectF(0,0,getWidth(),getHeight()));
radius = Math.min(drawableRect.height() / 2.0f, drawableRect.width() / 2.0f);
updateMatrix();
invalidate();
}
private void updateMatrix() {
float scale;
float dx = 0;
float dy = 0;
shaderMatrix.set(null);
if (bmpWidth * drawableRect.height() > drawableRect.width() * bmpHeight) {
scale = drawableRect.height() / (float) bmpHeight;
dx = (drawableRect.width() - bmpWidth * scale) * 0.5f;
} else {
scale = drawableRect.width() / (float) bmpWidth;
dy = (drawableRect.height() - bmpHeight * scale) * 0.5f;
}
shaderMatrix.setScale(scale, scale);
shaderMatrix.postTranslate((int) (dx + 0.5f) + drawableRect.left, (int) (dy + 0.5f) + drawableRect.top);
bmpShader.setLocalMatrix(shaderMatrix);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
init();
}
public void setBackgroundColor(#ColorInt int backgroundColor) {
backgroundPaint.setColor(backgroundColor);
invalidate();
}
#Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
initImage();
}
#Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
initImage();
}
#Override
public void setImageResource(#DrawableRes int resId) {
super.setImageResource(resId);
initImage();
}
#Override
public void setImageURI(Uri uri) {
super.setImageURI(uri);
initImage();
}
/* if this answer solved your problem please mark it as accepted by clicking the check mark next to the answer. Thank you */
}

How to have a circular, center-cropped imageView, without creating a new bitmap?

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

CenterCrop is not working in universal image loader : Android

i am currently using Universal Image Loader 1.9.3 and initialize it as,
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder().displayer(new RoundedBitmapDisplayer(100)).cacheOnDisc().build();
ImageLoaderConfiguration.Builder builder = new ImageLoaderConfiguration.Builder(Register.this).defaultDisplayImageOptions(defaultOptions).memoryCache(new WeakMemoryCache());
ImageLoaderConfiguration config = builder.build();
imageLoader2 = ImageLoader.getInstance();
imageLoader2.init(config);
Here i have used RoundedBitmapDisplayer because i want image as round shape and i have set the property of image view in xml file as android:scaleType="centerCrop", so it must have result as center crop image but it didn't give center crop image.. images are stretched even gave center crop....
Yeah, it is mentioned that it always keep the aspect ratio, where changing scaletype property on xml wont work... use a coded crop instead
public static Bitmap toCropcenterfitoriginal(Bitmap srcBmp) {
Bitmap dstBmp = ThumbnailUtils.extractThumbnail(srcBmp,
srcBmp.getWidth() / 2, srcBmp.getWidth() / 3);
;
return dstBmp;
}
you can change the RoundedDrawable in the RoundedBitmapDisplayer with:
public static class RoundedDrawable extends Drawable {
protected final float cornerRadius;
protected final int margin;
protected RectF mRect = new RectF(),
mBitmapRect;
protected final BitmapShader bitmapShader;
protected final Paint paint;
protected Bitmap mBitmap;
public RoundedDrawable(Bitmap bitmap, int cornerRadius, int margin) {
this.cornerRadius = cornerRadius;
this.margin = margin;
mBitmap = bitmap;
bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mBitmapRect = new RectF(margin, margin, bitmap.getWidth() - margin, bitmap.getHeight() - margin);
paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(bitmapShader);
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mRect.set(margin, margin, bounds.width() - margin, bounds.height() - margin);
// Resize the original bitmap to fit the new bound
Matrix shaderMatrix = new Matrix();
// shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL);
int width = bounds.right - bounds.left;
int height = bounds.bottom - bounds.top;
float scale = width * 1.0f / mBitmap.getWidth();
// 如果根据宽度缩放后,高度小于targetHeight
if (scale * mBitmap.getHeight() < height) {
scale = height * 1.0f / mBitmap.getHeight();
}
int outWidth = Math.round(scale * mBitmap.getWidth());
int outHeight = Math.round(scale * mBitmap.getHeight());
shaderMatrix.postScale(scale, scale);
int left = 0;
int top = 0;
if (outWidth == width) {
top = (outHeight - height) * -1 / 2;
}
else {
left = (outWidth - width) * -1 / 2;
}
shaderMatrix.postTranslate(left, top);
bitmapShader.setLocalMatrix(shaderMatrix);
}
#Override
public void draw(Canvas canvas) {
canvas.drawRoundRect(mRect, cornerRadius, cornerRadius, paint);
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
#Override
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
}
#Override
public void setColorFilter(ColorFilter cf) {
paint.setColorFilter(cf);
}
}
then you can find your pic show in CenterCrop and rounded corner.
you can also check my github for detail: https://github.com/417704684/RoundCornerDrawable
This seems to be an open issue in Universal Image Loader. The work around that i can suggest for this is, load the image bitmap and then centercrop and corner round the bitmap as needed. Here is the code sample.
BaseActivity.imageLoader.loadImage(mUrl, mOptions, new ImageLoadingListener()
{
#Override
public void onLoadingStarted(String imageUri, View view) {
}
#Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason)
{
}
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage)
{
if (loadedImage != null)
{
Bitmap croppedBitmap = ThumbnailUtils.extractThumbnail(loadedImage, HIQUtil.dpToPixel(getActivity(), 295), HIQUtil.dpToPixel(getActivity(), 211));
Bitmap roundedCropped = getRoundedCornerBitmap(croppedBitmap, 5);
imageView.setImageBitmap(roundedCropped);
}
}
#Override
public void onLoadingCancelled(String imageUri, View view) {
}
});
To get rounded corner bitmap, you can us this method:
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = pixels;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
Make sure to set
adjustViewBounds ="true"
in your imageview

android split the circle without taking the origin into consideration

I'm trying to split the circle into something of this sort:
http://i.stack.imgur.com/hNg3E.png
I want to color the major arc part of the circle with transparent color and minor arc of the circle with black color. Here is what I have tried, but unable to reach the final goal:
public class SplitCircleDrawable extends Drawable {
private final Bitmap mBitmap;
private final Paint mPaint;
private final Paint mBackGroundPaint,mTransparentPaint;
private final RectF mRectF;
private final int mBitmapWidth;
private final int mBitmapHeight;
private Context mCtx;
public SplitCircleDrawable(Bitmap bitmap, Context mContext) {
mCtx = mContext;
mBitmap=bitmap;
mRectF = new RectF();
mPaint = new Paint();
mBackGroundPaint = new Paint();
mTransparentPaint=new Paint();
mBackGroundPaint.setColor(0x97021829);
mTransparentPaint.setColor(Color.TRANSPARENT);
mBackGroundPaint.setDither(true);
mBackGroundPaint.setAntiAlias(true);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
final BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint.setShader(shader);
// NOTE: we assume bitmap is properly scaled to current density
mBitmapWidth = mBitmap.getWidth();
mBitmapHeight = mBitmap.getHeight();
}
#Override
public void draw(Canvas canvas) {
canvas.drawOval(mRectF, mPaint);
canvas.drawArc(mRectF, 0, 180, false, mBackGroundPaint);
// canvas.drawArc(mRectF, 0, 45, true, mTransparentPaint);
// canvas.drawArc(mRectF, 45, 135, true, mBackGroundPaint);
// canvas.drawArc(mRectF, 135, 180, true, mTransparentPaint);
}
#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();
}
}
Any help on this pls?
You might try to do it with canvas clipPath():
// First we draw draw backgroudn, it should be cropped with path too
canvas.drawOval(mRectF, paintBackground);
// Creating path that will cover small area on the circle,
// it might be triangle or rectancel or what ever.
// Currently it is triangle between top and left rect centers.
path.reset();
path.moveTo(0, 0);
path.lineTo(0, mRectF.width() / 2f);
path.lineTo(mRectF.height() / 2f, 0);
path.close();
// Clipping canvas to path and drawing small area
canvas.save();
canvas.clipPath(path);
canvas.drawOval(mRectF, paintArc);
canvas.restore();

Round ImageView in Android

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.

Categories

Resources