How to add a border around RoundedImageView custom ImageView implementation - android

I need a detail explanation of how it's being done. I want the class below to be modified with the code.
I want to add a white border/stroke around a rounded image view implementation. I don't want to do it in XML. I want it to be done programmatically by modifying this class. I am not sure how to get it done. Everything I have tried so far creates something like a square border, So I need your help.
The addWhiteBorder function was what I was trying to use but it doesn't seem to work well.
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);
}
private Bitmap addWhiteBorder(Bitmap bmp, int borderSize) {
Bitmap bmpWithBorder = Bitmap.createBitmap(bmp.getWidth() + borderSize * 2, bmp.getHeight() + borderSize * 2, bmp.getConfig());
Canvas canvas = new Canvas(bmpWithBorder);
canvas.drawColor(Color.RED);
canvas.drawBitmap(bmp, borderSize, borderSize, null);
return bmpWithBorder;
}
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);
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(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(sbmp, rect, rect, paint);
return output;
}
}

Just use simple XML drawable as a background of your imageView.
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android>
<stroke android:width="1dp" android:color="#000000" />
</shape>
EDIT: Okay now I read "I don't want to do it in XML." Nevermind then.

Use this code:
public class RoundedImageView extends ImageView {
public RoundedImageView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public RoundedImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundedImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
Bitmap b = ((BitmapDrawable)drawable).getBitmap() ;
Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
int w = getWidth(), h = getHeight();
Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0,0, null);
}
public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
Bitmap sbmp;
if(bmp.getWidth() != radius || bmp.getHeight() != radius)
sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false);
else
sbmp = bmp;
Bitmap output = Bitmap.createBitmap(sbmp.getWidth(),
sbmp.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xffa19774;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight());
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
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;
}
}
you can modify it according to your needs
Hope this helps.

Hi guys I had the same trouble But i managed with something like this.
I am sharing may be it will help.
public static LayerDrawable borderImageCircleBorder(Drawable draw, Activity activity) {
int xCordinate = returnImageDrawableSize(draw);
ShapeDrawable biggerCircle = new ShapeDrawable(new OvalShape());
biggerCircle.setIntrinsicHeight(xCordinate);
biggerCircle.setIntrinsicWidth(xCordinate);
biggerCircle.setBounds(new Rect(0, 0, xCordinate, xCordinate));
biggerCircle.getPaint().setColor(Color.WHITE);
biggerCircle.setPadding(4, 4, 4, 4);
ShapeDrawable smallerCircle = new ShapeDrawable(new OvalShape());
smallerCircle.setIntrinsicHeight(xCordinate);
smallerCircle.setIntrinsicWidth(xCordinate);
smallerCircle.setBounds(new Rect(0, 0, xCordinate, xCordinate));
smallerCircle.getPaint().setColor(Color.LTGRAY);
smallerCircle.setPadding(2, 2, 2, 2);
Drawable dd = getRoundedCornerBitmap(draw, activity);
Drawable[] d = { smallerCircle, biggerCircle, dd };
LayerDrawable composite = new LayerDrawable(d);
return composite;
}
public static int returnImageDrawableSize(Drawable image) {
Bitmap original = ((BitmapDrawable) image).getBitmap();
Bitmap bitmap = original;
//Log.i("original", "ht" + bitmap.getHeight() + ",wt=" + bitmap.getWidth());
int cropSizeWrtWidth, croppWrtHeight, xCoordinate, devideBy = 2;
cropSizeWrtWidth = bitmap.getWidth() / devideBy - bitmap.getHeight() / devideBy;
croppWrtHeight = bitmap.getHeight() / devideBy - bitmap.getWidth() / devideBy;
xCoordinate = cropSizeWrtWidth > 0 ? cropSizeWrtWidth : croppWrtHeight;
float cordinates = bitmap.getWidth() / 2;
// Find out ratio until we get a square bitmap
while (bitmap.getHeight() > bitmap.getWidth() && xCoordinate + bitmap.getWidth() > bitmap.getWidth()) {
devideBy += 1;
xCoordinate = bitmap.getHeight() / devideBy - bitmap.getWidth() / devideBy;
if (xCoordinate + bitmap.getWidth() <= bitmap.getWidth())
break;
}
return xCoordinate;
}
public static Drawable getRoundedCornerBitmap(Drawable image, Activity activity) {
Bitmap original = ((BitmapDrawable) image).getBitmap();
;
Bitmap bitmap = original;
//Log.i("original", "ht" + bitmap.getHeight() + ",wt=" + bitmap.getWidth());
int cropSizeWrtWidth, croppWrtHeight, xCoordinate, devideBy = 2;
cropSizeWrtWidth = bitmap.getWidth() / devideBy - bitmap.getHeight() / devideBy;
croppWrtHeight = bitmap.getHeight() / devideBy - bitmap.getWidth() / devideBy;
xCoordinate = cropSizeWrtWidth > 0 ? cropSizeWrtWidth : croppWrtHeight;
float cordinates = bitmap.getWidth() / 2;
// Find out ratio until we get a square bitmap
while (bitmap.getHeight() > bitmap.getWidth() && xCoordinate + bitmap.getWidth() > bitmap.getWidth()) {
devideBy += 1;
xCoordinate = bitmap.getHeight() / devideBy - bitmap.getWidth() / devideBy;
if (xCoordinate + bitmap.getWidth() <= bitmap.getWidth())
break;
}
if (bitmap.getWidth() >= bitmap.getHeight()) {
cordinates = bitmap.getHeight() / 2;
bitmap = Bitmap.createBitmap(bitmap, xCoordinate, 0, bitmap.getHeight(), bitmap.getHeight());
} else {
bitmap = Bitmap.createBitmap(bitmap, xCoordinate, 0, bitmap.getWidth(), bitmap.getWidth());
}
//Log.i("bitmap after crop", "ht" + bitmap.getHeight() + ",wt=" + bitmap.getWidth());
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
int color = 0xff424242;
Paint paint = new Paint();
paint.setColor(color);
paint.setAntiAlias(true);
Canvas canvas = new Canvas(output);
canvas.drawARGB(0, 0, 0, 0);
//Log.i("coordinates", "?????????" + cordinates);
canvas.drawCircle(cordinates, cordinates, cordinates, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
canvas.drawBitmap(bitmap, rect, rect, paint);
// output =
// ShadowView.getCircleWhiteBorderBitmap(original,output,convertDpToPixel(12,activity));
Drawable d = new BitmapDrawable(activity.getResources(), output);
return d;
}
Let me knw if u face any problem

Related

Anchor ImageView inside Collapsing Toolbar

Well I have implemented imageview to Collapsing toolbar using the answer provided by Sanjeet Ajnabee on Anchor ImageView to Collapsing Toolbar . The implementation worked fine but now what i want is to add the edit button inside the profile picture so that i can browse the gallery from that button. please help.
This is my code
public class FloatingActionImageView extends FloatingActionButton {
public FloatingActionImageView(Context context) {
super(context);
}
public FloatingActionImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FloatingActionImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
Bitmap sBmp;
if (bmp.getWidth() != radius || bmp.getHeight() != radius) {
float smallest = Math.min(bmp.getWidth(), bmp.getHeight());
float factor = smallest / radius;
sBmp = Bitmap.createScaledBitmap(bmp, (int) (bmp.getWidth() / factor), (int) (bmp.getHeight() / factor), false);
} else {
sBmp = bmp;
}
Bitmap output = Bitmap.createBitmap(radius, radius,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, radius + 5, radius + 5);
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(radius / 2,
radius / 2, radius / 2, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(sBmp, rect, rect, paint);
return output;
}
#Override
protected void onDraw(#NonNull Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
Bitmap b = ((BitmapDrawable) drawable).getBitmap();
Bitmap bitmap = null;
if (b != null) {
bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
} else {
BitmapDrawable bitmapDrawable = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
bitmapDrawable = ((BitmapDrawable) getResources().getDrawable(R.drawable.ic_hospital, null));
} else {
bitmapDrawable = ((BitmapDrawable) getResources().getDrawable(R.drawable.ic_hospital));
}
if (bitmapDrawable != null) {
bitmap = bitmapDrawable.getBitmap();
}
}
int w = getWidth();
Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);
}
}
And this is my layout
<com.example.cripes.rsnepal.FloatingActionImageView
android:layout_height="100dp"
android:layout_width="100dp"
app:layout_anchor="#id/appbarProfile"
app:layout_anchorGravity="bottom|end"
android:src="#drawable/ic_hospital"
android:layout_margin="#dimen/fab_margin"
android:clickable="true" />

Android: Circular Drawable

I made this Custom Drawable that should clip any Drawable in circle. But with my implementation, the drawable passed is being the output in the original form not in the circular form.
public class CircularDrawable extends Drawable {
Paint mPaint,xfermodePaint;
Drawable mDrawable;
int[] vinylCenter = new int[2];
int radius;
Bitmap src;
PorterDuffXfermode xfermode;
Rect rect;
Canvas testCanvas;
public CircularDrawable(Drawable drawable) {
mDrawable = drawable;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(0xffffffff);
mPaint.setStyle(Paint.Style.FILL);
xfermodePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
xfermode=new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
xfermodePaint.setXfermode(xfermode);
testCanvas=new Canvas();
}
#Override
public void setBounds(Rect bounds) {
super.setBounds(bounds);
mDrawable.setBounds(bounds);
}
#Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
mDrawable.setBounds(left, top, right, bottom);
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
vinylCenter[0] = bounds.width() / 2;
vinylCenter[1] = bounds.height() / 2;
radius = (bounds.right - bounds.left) / 2;
src = Bitmap.createBitmap(bounds.width(), bounds.height(), Bitmap.Config.ARGB_8888);
testCanvas.setBitmap(src);
}
#Override
public void draw(Canvas canvas) {
canvas.save();
canvas.drawARGB(0, 0, 0, 0);
canvas.drawCircle(vinylCenter[0],vinylCenter[1],radius,mPaint);
mDrawable.draw(testCanvas);
canvas.drawBitmap(src,0f,0f,xfermodePaint);
}
#Override
public void setAlpha(int alpha) {/*ignored*/}
#Override
public void setColorFilter(ColorFilter colorFilter) {/*ignored*/}
#Override
public int getOpacity() {
/*ignored*/
return 0;
}
}
What is my mistake?
Also I am using a SquareImageview to display this drawable that just makes the view square in onMeasure.
This question is not meant for Circular imageview.
You already have optimized implementation for circular drawable in Support library v4:
Google reference
/**
* A Drawable that wraps a bitmap and can be drawn with rounded corners. You can create a
* RoundedBitmapDrawable from a file path, an input stream, or from a
* {#link android.graphics.Bitmap} object.
* <p>
* Also see the {#link android.graphics.Bitmap} class, which handles the management and
* transformation of raw bitmap graphics, and should be used when drawing to a
* {#link android.graphics.Canvas}.
* </p>
*/
public abstract class RoundedBitmapDrawable extends Drawable ....
The canvas doesnt have alpha channel on by default when using Porter/Duff xfermode mode (As per my experience with my this in android). That is the reason the whole image(src) is being the output. Porter/Duff xfermode acts based on Alpha Channel.
In many implementation of Circular Drawable 2 Canvas are taken, out of which one is given RGB image bitmap and other is given only alpha channel bitmap with circular mask. Porter/Duff xfermodeis applied and the result is drawn on the main canvas.
My mistake is that I am not specifying the draw function's canvas that alpha channel is to be considered on using the layer on the canvas for xfermode.
The draw function will become
#Override
public void draw(Canvas canvas) {
int sc = canvas.saveLayer(null, null,
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
);
canvas.drawCircle(vinylCenter[0],vinylCenter[1],radius,mPaint);
mDrawable.draw(testCanvas);
canvas.drawBitmap(src,0f,0f,xfermodePaint);
canvas.restoreToCount(sc);
}
Saving the Layer to indicate alpha channel with the flag and then using the xfermode. Finally restoring it to its save count.
So basically I use this method to get rounded corner images
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = pixels;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
but like you pointed out sometimes it does not work, well it does work, but what happens most of the time is your imageview might have its scaletype set to centerCrop and other types, what I do is I first compress my image height to the same height and width as my imageview so that the entire image will fit in the imageview and no scaling will take place or I just calculate how much of the corner height to make rounded using this function based on the height
private int calculatePercentage(int percentage, int target)
{
int k = (int)(target*(percentage/100.0f));
return k;
}
so I use my code like: new Bitmap(getRoundedCornerBitmap(bmp, calculatePercentage(5, bmp.getHeight()))); where 5 is 5 of the image height this gives me same curves for all images be it some images are bigger than others
`
For rounded imageview you can use this code
public class RoundedImageView extends ImageView {
public RoundedImageView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public RoundedImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundedImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
Bitmap b = ((BitmapDrawable) drawable).getBitmap();
Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
int w = getWidth();//, h = getHeight();
Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);
}
public static Bitmap getCroppedBitmap(Bitmap bmp, int radius)
{
Bitmap sbmp;
if (bmp.getWidth() != radius || bmp.getHeight() != radius)
sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false);
else
sbmp = bmp;
Bitmap output = Bitmap.createBitmap(sbmp.getWidth(), sbmp.getHeight(),Config.ARGB_8888);
Canvas canvas = new Canvas(output);
// final int color = 0xffa19774;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight());
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
// paint.setColor(Color.parseColor("#BAB399"));
paint.setColor(Color.parseColor("#FF0000"));
canvas.drawCircle(sbmp.getWidth() / 2 + 0.7f, sbmp.getHeight() / 2 + 0.7f, sbmp.getWidth() / 2 + 0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(sbmp, rect, rect, paint);
return output;
}
}
For circular imageview use the below code
public class RoundedImageView extends ImageView {
public RoundedImageView(Context context) {
super(context);
}
public RoundedImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundedImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
BitmapDrawable drawable = (BitmapDrawable) getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
Bitmap fullSizeBitmap = drawable.getBitmap();
int scaledWidth = getMeasuredWidth();
int scaledHeight = getMeasuredHeight();
/*
* scaledWidth = scaledWidth/2; scaledHeight = scaledHeight/2;
*/
Bitmap mScaledBitmap;
if (scaledWidth == fullSizeBitmap.getWidth()
&& scaledHeight == fullSizeBitmap.getHeight()) {
mScaledBitmap = fullSizeBitmap;
} else {
mScaledBitmap = Bitmap.createScaledBitmap(fullSizeBitmap,
scaledWidth, scaledHeight, true /* filter */);
}
// Bitmap roundBitmap = getRoundedCornerBitmap(mScaledBitmap);
// Bitmap roundBitmap = getRoundedCornerBitmap(getContext(),
// mScaledBitmap, 10, scaledWidth, scaledHeight, false, false,
// false, false);
// canvas.drawBitmap(roundBitmap, 0, 0, null);
Bitmap circleBitmap = getCircledBitmap(mScaledBitmap);
canvas.drawBitmap(circleBitmap, 0, 0, null);
}
public Bitmap getRoundedCornerBitmap(Context context, Bitmap input,
int pixels, int w, int h, boolean squareTL, boolean squareTR,
boolean squareBL, boolean squareBR) {
Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final float densityMultiplier = context.getResources()
.getDisplayMetrics().density;
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, w, h);
final RectF rectF = new RectF(rect);
// make sure that our rounded corner is scaled appropriately
final float roundPx = pixels * densityMultiplier;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
// draw rectangles over the corners we want to be square
if (squareTL) {
canvas.drawRect(0, 0, w / 2, h / 2, paint);
}
if (squareTR) {
canvas.drawRect(w / 2, 0, w, h / 2, paint);
}
if (squareBL) {
canvas.drawRect(0, h / 2, w / 2, h, paint);
}
if (squareBR) {
canvas.drawRect(w / 2, h / 2, w, h, paint);
}
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(input, 0, 0, paint);
return output;
}
Bitmap getCircledBitmap(Bitmap bitmap) {
Bitmap result = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
int color = Color.BLUE;
Paint paint = new Paint();
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
// canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
bitmap.getHeight() / 2, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return result;
}
}
Try disabling hardware acceleration if you are using PorterDuffXfermode:
In manifest for whole activity:
<activity android:hardwareAccelerated="false" />
Or on a specific view on which you are using xfermode:
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

Adding white border and shadow to Custom Android ImageView

I know this question has been asked before but I have struggled to come up with a solution.
I have a custom ImageView with complete rounded corners which is done programmatically.
I have something like this
But I want to get to something like this:
Here is my custom ImageView class.
#SuppressLint("NewApi")
public class MLRoundedImageView extends ImageView {
private Context context;
public MLRoundedImageView(Context context) {
super(context);
this.context = context;
}
public MLRoundedImageView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
public MLRoundedImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
}
#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);
}
#SuppressLint("NewApi")
public Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
Bitmap sbmp;
if (bmp.getWidth() != radius || bmp.getHeight() != radius) {
float smallest = Math.min(bmp.getWidth(), bmp.getHeight());
float factor = smallest / radius;
sbmp = Bitmap.createScaledBitmap(bmp, (int)(bmp.getWidth() / factor), (int)(bmp.getHeight() / factor), false);
} else {
sbmp = bmp;
}
Bitmap output = Bitmap.createBitmap(radius, radius,
Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xffa19774;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, radius, radius);
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(radius / 2 + 0.7f,
radius / 2 + 0.7f, radius / 2 + 0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(sbmp, rect, rect, paint);
return output;
}
}
I know there is just a few extra I need to add i don't want to recreate the entire class as my project is heavily depended on it.
Thanks in advance!
Use layer list:
http://developer.android.com/guide/topics/resources/drawable-resource.html#LayerList
Basically create a white circle with the dimension you want and use layer list to create it under the picture

How to convert ImageView into Rounded Shape?

I am using following code for converting ImageView into rounded iage, but gettin error at "Mode.SRC_IN" . Need help. Thank you in advance.
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;
}
Use this class:
public class RoundedImageView extends ImageView {
private Paint objPaint = new Paint();
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();
Log.i("TAG", "Bitmap Width:" + w);
Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
objPaint.setAntiAlias(true);
objPaint.setDither(true);
canvas.drawBitmap(roundBitmap, 0, 0, objPaint);
}
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;
}
}
now in xml file:
<path to your class
android:id="#+id/iv_leaderboard_profile_icon"
android:layout_width="#dimen/lederboard_image_size"
android:layout_height="#dimen/lederboard_image_size"
android:src="#drawable/ic_launcher" />
here
path= com.example.view.RoundedImageView
something like that.
hope you understand, thank you.
Romain guy has an excellent blog post about achieving rounded corners on ImageViews here
For PorterDuffXfermode, you have to write import android.graphics.PorterDuffXfermode;
For Config.ARGB_8888, you have to write import android.graphics.Bitmap.Config;
Otherwise Direct press CTRL + SHIFT + O to organize imports.
A new class is introduced in android.support.v4. Which provides you the circled image which any customization.
RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(mContext.getResources(), bitmap);
roundedBitmapDrawable.setCornerRadius(pixels);
imageView.setImageDrawable(roundedBitmapDrawable);
I would recommend to make use of it.

Image getting stretched when displayed in rounded imageview

Below is my RoundedImageView class that extends 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);
// roundBitmap= ImageUtils.setCircularInnerGlow(roundBitmap, 0xFFBAB399, 4, 1);
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;
}
And my xml code is:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="horizontal" >
<com.example.scaletypedemo.RoundedImageView
android:layout_marginLeft="30dp"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:scaleType="centerCrop"
android:src="#drawable/a"
android:adjustViewBounds="true" />
<ImageView
android:layout_marginLeft="50dp"
android:layout_width="100dp"
android:layout_height="100dp"
android:scaleType="centerCrop"
android:src="#drawable/a" />
</LinearLayout>
</RelativeLayout>
So, the problem is, if I use ImageView the image displayed is not getting stretched but if I use the same image and display it in RoundedImageView and keeping all the properties same; the image is getting stretched as shown in the below screenshot:
Please help preventing the stretching of the image displayed in RoundedImageView...........I am badly stuck at this point.
Edit: After applying Zhenghong's solution, it resolved the stretching issue but then it is not showing the complete round.
Thanks in advance!!!
You should resize your bitmap by its width/height rate.
----EDITED----
This will be a more flexible way to do it.
#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();
int radius = w < h ? w : h;
Bitmap roundBitmap = getCroppedBitmap(bitmap, radius, w, h);
// roundBitmap= ImageUtils.setCircularInnerGlow(roundBitmap, 0xFFBAB399,
// 4, 1);
canvas.drawBitmap(roundBitmap, 0, 0, null);
}
public static Bitmap getCroppedBitmap(Bitmap bmp, int radius, int w, int h) {
Bitmap sbmp;
if (bmp.getWidth() != radius || bmp.getHeight() != radius) {
float _w_rate = 1.0f * radius / bmp.getWidth();
float _h_rate = 1.0f * radius / bmp.getHeight();
float _rate = _w_rate < _h_rate ? _h_rate : _w_rate;
sbmp = Bitmap.createScaledBitmap(bmp, (int)(bmp.getWidth() * _rate), (int)(bmp.getHeight() * _rate), 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(w / 2, h / 2, (w < h ? w : h) / 2, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(sbmp, rect, rect, paint);
return output;
}
Another alternative is to create a transparent PNG for the border (a hollowed out circle in a square) and place it as the background of a view directly above, and with the same dimensions, of the ImageView.
Something like this:
EDIT:
Seems white on white images are porblematic :) (trust me, there's an image there...)
So I uplaoded 2 more:

Categories

Resources