I'm trying to make one rounded corner of ImageView like in the picture below but with bottom right corner. Tried using background shape but it's not working at all. All images loaded by Glide. Should i use something like ViewOutlineProvider? Is there are an efficient way to do this? Thanks!
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<corners
android:radius="2dp"
android:bottomRightRadius="20dp"
android:bottomLeftRadius="0dp"
android:topLeftRadius="0dp"
android:topRightRadius="0dp"/>
</shape>
With jetpack compose you can apply the clip Modifier using a RoundedCornerShape:
Image(painterResource(id = R.drawable.xxx),
contentDescription = "xxxx",
contentScale = ContentScale.Crop,
modifier = Modifier
.size(xx.dp,xx.dp)
.clip(RoundedCornerShape(topStart = 12.dp)),
)
With The Material Components library you can use the ShapeableImageView (introduced with the version 1.2.0-alpha03).
Just use something like:
<com.google.android.material.imageview.ShapeableImageView
android:id="#+id/image_view"
android:scaleType="centerInside"
android:adjustViewBounds="true"
../>
then in your code you can apply the ShapeAppearanceModel with:
ShapeableImageView imageView = findViewById(R.id.image_view);
float radius = getResources().getDimension(R.dimen.default_corner_radius);
imageView.setShapeAppearanceModel(imageView.getShapeAppearanceModel()
.toBuilder()
.setTopRightCorner(CornerFamily.ROUNDED,radius)
.build());
You can also apply in the xml the shapeAppearanceOverlay parameter:
<com.google.android.material.imageview.ShapeableImageView
app:shapeAppearanceOverlay="#style/customRroundedImageView"
app:srcCompat="#drawable/ic_image" />
with:
<style name="customRoundedImageView" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">0dp</item>
<item name="cornerSizeTopRight">8dp</item>
</style>
Also if you want to get rid of writing code in ".java" file. Then you can define style like below and just add it to your ShapeableImageView:
<com.google.android.material.imageview.ShapeableImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ex_image"
app:shapeAppearanceOverlay="#style/roundedImageView"
/>
then:
<style name="roundedImageView" parent="">
<item name="cornerFamilyTopRight">rounded</item>
<item name="cornerSizeTopRight">30dp</item>
</style>
this is your main layout file which uses a custom drawable "round_one.xml"file. just copy and paste this code.
it will hopefully meet your requirements.
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:elevation="#dimen/_10sdp"
android:background="#color/white"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/round_one"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="#dimen/_80sdp"
android:layout_gravity="center"
android:scaleType="fitXY"
android:src="#android:drawable/ic_menu_day" />
<TextView
android:id="#+id/textView22"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:text="title goes here" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:text="Secondary text"
/>
</LinearLayout>
</androidx.cardview.widget.CardView>
round_one.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/gray" />
<corners android:topRightRadius="50dp" />
</shape>
To round only one corner of imageview follow below steps and code:
Add below file to your project RoundCornerImageView.java
package com.skd.stackdemo;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;
public class RoundCornerImageView extends ImageView {
public static final String TAG = "RoundCornerImageView";
private int mResource = 0;
private static final ScaleType[] sScaleTypeArray = {
ScaleType.MATRIX,
ScaleType.FIT_XY,
ScaleType.FIT_START,
ScaleType.FIT_CENTER,
ScaleType.FIT_END,
ScaleType.CENTER,
ScaleType.CENTER_CROP,
ScaleType.CENTER_INSIDE
};
// Set default scale type to FIT_CENTER, which is default scale type of
// original ImageView.
private ScaleType mScaleType = ScaleType.FIT_CENTER;
private float mLeftTopCornerRadius = 0.0f;
private float mRightTopCornerRadius = 0.0f;
private float mLeftBottomCornerRadius = 0.0f;
private float mRightBottomCornerRadius = 0.0f;
private float mBorderWidth = 0.0f;
private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
private ColorStateList mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);
private boolean isOval = false;
private Drawable mDrawable;
private float[] mRadii = new float[] { 0, 0, 0, 0, 0, 0, 0, 0 };
public RoundCornerImageView(Context context) {
super(context);
}
public RoundCornerImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundCornerImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.SelectableRoundedImageView, defStyle, 0);
final int index = a.getInt(R.styleable.SelectableRoundedImageView_android_scaleType, -1);
if (index >= 0) {
setScaleType(sScaleTypeArray[index]);
}
mLeftTopCornerRadius = a.getDimensionPixelSize(
R.styleable.SelectableRoundedImageView_sriv_left_top_corner_radius, 0);
mRightTopCornerRadius = a.getDimensionPixelSize(
R.styleable.SelectableRoundedImageView_sriv_right_top_corner_radius, 0);
mLeftBottomCornerRadius = a.getDimensionPixelSize(
R.styleable.SelectableRoundedImageView_sriv_left_bottom_corner_radius, 0);
mRightBottomCornerRadius = a.getDimensionPixelSize(
R.styleable.SelectableRoundedImageView_sriv_right_bottom_corner_radius, 0);
if (mLeftTopCornerRadius < 0.0f || mRightTopCornerRadius < 0.0f
|| mLeftBottomCornerRadius < 0.0f || mRightBottomCornerRadius < 0.0f) {
throw new IllegalArgumentException("radius values cannot be negative.");
}
mRadii = new float[] {
mLeftTopCornerRadius, mLeftTopCornerRadius,
mRightTopCornerRadius, mRightTopCornerRadius,
mRightBottomCornerRadius, mRightBottomCornerRadius,
mLeftBottomCornerRadius, mLeftBottomCornerRadius };
mBorderWidth = a.getDimensionPixelSize(
R.styleable.SelectableRoundedImageView_sriv_border_width, 0);
if (mBorderWidth < 0) {
throw new IllegalArgumentException("border width cannot be negative.");
}
mBorderColor = a
.getColorStateList(R.styleable.SelectableRoundedImageView_sriv_border_color);
if (mBorderColor == null) {
mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);
}
isOval = a.getBoolean(R.styleable.SelectableRoundedImageView_sriv_oval, false);
a.recycle();
updateDrawable();
}
#Override
protected void drawableStateChanged() {
super.drawableStateChanged();
invalidate();
}
#Override
public ScaleType getScaleType() {
return mScaleType;
}
#Override
public void setScaleType(ScaleType scaleType) {
super.setScaleType(scaleType);
mScaleType = scaleType;
updateDrawable();
}
#Override
public void setImageDrawable(Drawable drawable) {
mResource = 0;
mDrawable = RoundCornerDrawable.fromDrawable(drawable, getResources());
super.setImageDrawable(mDrawable);
updateDrawable();
}
#Override
public void setImageBitmap(Bitmap bm) {
mResource = 0;
mDrawable = RoundCornerDrawable.fromBitmap(bm, getResources());
super.setImageDrawable(mDrawable);
updateDrawable();
}
#Override
public void setImageResource(int resId) {
if (mResource != resId) {
mResource = resId;
mDrawable = resolveResource();
super.setImageDrawable(mDrawable);
updateDrawable();
}
}
#Override
public void setImageURI(Uri uri) {
super.setImageURI(uri);
setImageDrawable(getDrawable());
}
private Drawable resolveResource() {
Resources rsrc = getResources();
if (rsrc == null) {
return null;
}
Drawable d = null;
if (mResource != 0) {
try {
d = rsrc.getDrawable(mResource);
} catch (Resources.NotFoundException e) {
Log.w(TAG, "Unable to find resource: " + mResource, e);
// Don't try again.
mResource = 0;
}
}
return RoundCornerDrawable.fromDrawable(d, getResources());
}
private void updateDrawable() {
if (mDrawable == null) {
return;
}
((RoundCornerDrawable) mDrawable).setScaleType(mScaleType);
((RoundCornerDrawable) mDrawable).setCornerRadii(mRadii);
((RoundCornerDrawable) mDrawable).setBorderWidth(mBorderWidth);
((RoundCornerDrawable) mDrawable).setBorderColor(mBorderColor);
((RoundCornerDrawable) mDrawable).setOval(isOval);
}
public float getCornerRadius() {
return mLeftTopCornerRadius;
}
/**
* Set radii for each corner.
*
* #param leftTop The desired radius for left-top corner in dip.
* #param rightTop The desired desired radius for right-top corner in dip.
* #param leftBottom The desired radius for left-bottom corner in dip.
* #param rightBottom The desired radius for right-bottom corner in dip.
*
*/
public void setCornerRadiiDP(float leftTop, float rightTop, float leftBottom, float rightBottom) {
final float density = getResources().getDisplayMetrics().density;
final float lt = leftTop * density;
final float rt = rightTop * density;
final float lb = leftBottom * density;
final float rb = rightBottom * density;
mRadii = new float[] { lt, lt, rt, rt, rb, rb, lb, lb };
updateDrawable();
}
public float getBorderWidth() {
return mBorderWidth;
}
/**
* Set border width.
*
* #param width
* The desired width in dip.
*/
public void setBorderWidthDP(float width) {
float scaledWidth = getResources().getDisplayMetrics().density * width;
if (mBorderWidth == scaledWidth) {
return;
}
mBorderWidth = scaledWidth;
updateDrawable();
invalidate();
}
public int getBorderColor() {
return mBorderColor.getDefaultColor();
}
public void setBorderColor(int color) {
setBorderColor(ColorStateList.valueOf(color));
}
public ColorStateList getBorderColors() {
return mBorderColor;
}
public void setBorderColor(ColorStateList colors) {
if (mBorderColor.equals(colors)) {
return;
}
mBorderColor = (colors != null) ? colors : ColorStateList
.valueOf(DEFAULT_BORDER_COLOR);
updateDrawable();
if (mBorderWidth > 0) {
invalidate();
}
}
public boolean isOval() {
return isOval;
}
public void setOval(boolean oval) {
isOval = oval;
updateDrawable();
invalidate();
}
static class RoundCornerDrawable extends Drawable {
private static final String TAG = "RoundCornerDrawable";
private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
private RectF mBounds = new RectF();
private RectF mBorderBounds = new RectF();
private final RectF mBitmapRect = new RectF();
private final int mBitmapWidth;
private final int mBitmapHeight;
private final Paint mBitmapPaint;
private final Paint mBorderPaint;
private BitmapShader mBitmapShader;
private float[] mRadii = new float[] { 0, 0, 0, 0, 0, 0, 0, 0 };
private float[] mBorderRadii = new float[] { 0, 0, 0, 0, 0, 0, 0, 0 };
private boolean mOval = false;
private float mBorderWidth = 0;
private ColorStateList mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);
// Set default scale type to FIT_CENTER, which is default scale type of
// original ImageView.
private ScaleType mScaleType = ScaleType.FIT_CENTER;
private Path mPath = new Path();
private Bitmap mBitmap;
private boolean mBoundsConfigured = false;
public RoundCornerDrawable(Bitmap bitmap, Resources r) {
mBitmap = bitmap;
mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
if (bitmap != null) {
mBitmapWidth = bitmap.getScaledWidth(r.getDisplayMetrics());
mBitmapHeight = bitmap.getScaledHeight(r.getDisplayMetrics());
} else {
mBitmapWidth = mBitmapHeight = -1;
}
mBitmapRect.set(0, 0, mBitmapWidth, mBitmapHeight);
mBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBitmapPaint.setStyle(Paint.Style.FILL);
mBitmapPaint.setShader(mBitmapShader);
mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setColor(mBorderColor.getColorForState(getState(), DEFAULT_BORDER_COLOR));
mBorderPaint.setStrokeWidth(mBorderWidth);
}
public static RoundCornerDrawable fromBitmap(Bitmap bitmap, Resources r) {
if (bitmap != null) {
return new RoundCornerDrawable(bitmap, r);
} else {
return null;
}
}
#SuppressLint("LongLogTag")
public static Drawable fromDrawable(Drawable drawable, Resources r) {
if (drawable != null) {
if (drawable instanceof RoundCornerDrawable) {
return drawable;
} else if (drawable instanceof LayerDrawable) {
LayerDrawable ld = (LayerDrawable) drawable;
final int num = ld.getNumberOfLayers();
for (int i = 0; i < num; i++) {
Drawable d = ld.getDrawable(i);
ld.setDrawableByLayerId(ld.getId(i), fromDrawable(d, r));
}
return ld;
}
Bitmap bm = drawableToBitmap(drawable);
if (bm != null) {
return new RoundCornerDrawable(bm, r);
} else {
Log.w(TAG, "Failed to create bitmap from drawable!");
}
}
return drawable;
}
public static Bitmap drawableToBitmap(Drawable drawable) {
if (drawable == null) {
return null;
}
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap;
int width = Math.max(drawable.getIntrinsicWidth(), 2);
int height = Math.max(drawable.getIntrinsicHeight(), 2);
try {
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
} catch (IllegalArgumentException e) {
e.printStackTrace();
bitmap = null;
}
return bitmap;
}
#Override
public boolean isStateful() {
return mBorderColor.isStateful();
}
#Override
protected boolean onStateChange(int[] state) {
int newColor = mBorderColor.getColorForState(state, 0);
if (mBorderPaint.getColor() != newColor) {
mBorderPaint.setColor(newColor);
return true;
} else {
return super.onStateChange(state);
}
}
private void configureBounds(Canvas canvas) {
// I have discovered a truly marvelous explanation of this,
// which this comment space is too narrow to contain. :)
// If you want to understand what's going on here,
// See http://www.joooooooooonhokim.com/?p=289
Rect clipBounds = canvas.getClipBounds();
Matrix canvasMatrix = canvas.getMatrix();
if (ScaleType.CENTER == mScaleType) {
mBounds.set(clipBounds);
} else if (ScaleType.CENTER_CROP == mScaleType) {
applyScaleToRadii(canvasMatrix);
mBounds.set(clipBounds);
} else if (ScaleType.FIT_XY == mScaleType) {
Matrix m = new Matrix();
m.setRectToRect(mBitmapRect, new RectF(clipBounds), Matrix.ScaleToFit.FILL);
mBitmapShader.setLocalMatrix(m);
mBounds.set(clipBounds);
} else if (ScaleType.FIT_START == mScaleType || ScaleType.FIT_END == mScaleType
|| ScaleType.FIT_CENTER == mScaleType || ScaleType.CENTER_INSIDE == mScaleType) {
applyScaleToRadii(canvasMatrix);
mBounds.set(mBitmapRect);
} else if (ScaleType.MATRIX == mScaleType) {
applyScaleToRadii(canvasMatrix);
mBounds.set(mBitmapRect);
}
}
private void applyScaleToRadii(Matrix m) {
float[] values = new float[9];
m.getValues(values);
for (int i = 0; i < mRadii.length; i++) {
mRadii[i] = mRadii[i] / values[0];
}
}
private void adjustCanvasForBorder(Canvas canvas) {
Matrix canvasMatrix = canvas.getMatrix();
final float[] values = new float[9];
canvasMatrix.getValues(values);
final float scaleFactorX = values[0];
final float scaleFactorY = values[4];
final float translateX = values[2];
final float translateY = values[5];
final float newScaleX = mBounds.width()
/ (mBounds.width() + mBorderWidth + mBorderWidth);
final float newScaleY = mBounds.height()
/ (mBounds.height() + mBorderWidth + mBorderWidth);
canvas.scale(newScaleX, newScaleY);
if (ScaleType.FIT_START == mScaleType || ScaleType.FIT_END == mScaleType
|| ScaleType.FIT_XY == mScaleType || ScaleType.FIT_CENTER == mScaleType
|| ScaleType.CENTER_INSIDE == mScaleType || ScaleType.MATRIX == mScaleType) {
canvas.translate(mBorderWidth, mBorderWidth);
} else if (ScaleType.CENTER == mScaleType || ScaleType.CENTER_CROP == mScaleType) {
// First, make translate values to 0
canvas.translate(
-translateX / (newScaleX * scaleFactorX),
-translateY / (newScaleY * scaleFactorY));
// Then, set the final translate values.
canvas.translate(-(mBounds.left - mBorderWidth), -(mBounds.top - mBorderWidth));
}
}
private void adjustBorderWidthAndBorderBounds(Canvas canvas) {
Matrix canvasMatrix = canvas.getMatrix();
final float[] values = new float[9];
canvasMatrix.getValues(values);
final float scaleFactor = values[0];
float viewWidth = mBounds.width() * scaleFactor;
mBorderWidth = (mBorderWidth * mBounds.width()) / (viewWidth - (2 * mBorderWidth));
mBorderPaint.setStrokeWidth(mBorderWidth);
mBorderBounds.set(mBounds);
mBorderBounds.inset(- mBorderWidth / 2, - mBorderWidth / 2);
}
private void setBorderRadii() {
for (int i = 0; i < mRadii.length; i++) {
if (mRadii[i] > 0) {
mBorderRadii[i] = mRadii[i];
mRadii[i] = mRadii[i] - mBorderWidth;
}
}
}
#Override
public void draw(Canvas canvas) {
canvas.save();
if (!mBoundsConfigured) {
configureBounds(canvas);
if (mBorderWidth > 0) {
adjustBorderWidthAndBorderBounds(canvas);
setBorderRadii();
}
mBoundsConfigured = true;
}
if (mOval) {
if (mBorderWidth > 0) {
adjustCanvasForBorder(canvas);
mPath.addOval(mBounds, Path.Direction.CW);
canvas.drawPath(mPath, mBitmapPaint);
mPath.reset();
mPath.addOval(mBorderBounds, Path.Direction.CW);
canvas.drawPath(mPath, mBorderPaint);
} else {
mPath.addOval(mBounds, Path.Direction.CW);
canvas.drawPath(mPath, mBitmapPaint);
}
} else {
if (mBorderWidth > 0) {
adjustCanvasForBorder(canvas);
mPath.addRoundRect(mBounds, mRadii, Path.Direction.CW);
canvas.drawPath(mPath, mBitmapPaint);
mPath.reset();
mPath.addRoundRect(mBorderBounds, mBorderRadii, Path.Direction.CW);
canvas.drawPath(mPath, mBorderPaint);
} else {
mPath.addRoundRect(mBounds, mRadii, Path.Direction.CW);
canvas.drawPath(mPath, mBitmapPaint);
}
}
canvas.restore();
}
public void setCornerRadii(float[] radii) {
if (radii == null)
return;
if (radii.length != 8) {
throw new ArrayIndexOutOfBoundsException("radii[] needs 8 values");
}
for (int i = 0; i < radii.length; i++) {
mRadii[i] = radii[i];
}
}
#Override
public int getOpacity() {
return (mBitmap == null || mBitmap.hasAlpha() || mBitmapPaint.getAlpha() < 255) ? PixelFormat.TRANSLUCENT
: PixelFormat.OPAQUE;
}
#Override
public void setAlpha(int alpha) {
mBitmapPaint.setAlpha(alpha);
invalidateSelf();
}
#Override
public void setColorFilter(ColorFilter cf) {
mBitmapPaint.setColorFilter(cf);
invalidateSelf();
}
#Override
public void setDither(boolean dither) {
mBitmapPaint.setDither(dither);
invalidateSelf();
}
#Override
public void setFilterBitmap(boolean filter) {
mBitmapPaint.setFilterBitmap(filter);
invalidateSelf();
}
#Override
public int getIntrinsicWidth() {
return mBitmapWidth;
}
#Override
public int getIntrinsicHeight() {
return mBitmapHeight;
}
public float getBorderWidth() {
return mBorderWidth;
}
public void setBorderWidth(float width) {
mBorderWidth = width;
mBorderPaint.setStrokeWidth(width);
}
public int getBorderColor() {
return mBorderColor.getDefaultColor();
}
public void setBorderColor(int color) {
setBorderColor(ColorStateList.valueOf(color));
}
public ColorStateList getBorderColors() {
return mBorderColor;
}
/**
* Controls border color of this ImageView.
*
* #param colors
* The desired border color. If it's null, no border will be
* drawn.
*
*/
public void setBorderColor(ColorStateList colors) {
if (colors == null) {
mBorderWidth = 0;
mBorderColor = ColorStateList.valueOf(Color.TRANSPARENT);
mBorderPaint.setColor(Color.TRANSPARENT);
} else {
mBorderColor = colors;
mBorderPaint.setColor(mBorderColor.getColorForState(getState(),
DEFAULT_BORDER_COLOR));
}
}
public boolean isOval() {
return mOval;
}
public void setOval(boolean oval) {
mOval = oval;
}
public ScaleType getScaleType() {
return mScaleType;
}
public void setScaleType(ScaleType scaleType) {
if (scaleType == null) {
return;
}
mScaleType = scaleType;
}
}
}
Add styleable to attr file under res folder
<declare-styleable name="RoundCornerImageView">
<attr name="sriv_left_top_corner_radius" format="dimension" />
<attr name="sriv_right_top_corner_radius" format="dimension" />
<attr name="sriv_left_bottom_corner_radius" format="dimension" />
<attr name="sriv_right_bottom_corner_radius" format="dimension" />
<attr name="sriv_border_width" format="dimension" />
<attr name="sriv_border_color" format="color" />
<attr name="sriv_oval" format="boolean" />
<attr name="android:scaleType" />
</declare-styleable>
Used in XML file:
<com.skd.stackdemo.RoundCornerImageView
android:layout_width="300dp"
android:layout_height="300dp"
android:src="#drawable/android"
android:scaleType="centerCrop"
app:sriv_left_top_corner_radius="0dp"
app:sriv_right_top_corner_radius="20dp"
app:sriv_left_bottom_corner_radius="0dp"
app:sriv_right_bottom_corner_radius="0dp"
app:sriv_oval="false" />
Output for above code is:
For more information please check this github project:SelectableRoundedImageView
I hope it works for you
Related
I created a cornerRadius card view and my codes work well in activity but the problem now is that the cardview does not show the rounded edges and elevation in fragment but it shows in the design codes and in activity. my codes are shown blow:
raounded_corners.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:focusable="true"
android:clickable="true"
android:background="#color/white"
android:layout_height="match_parent">
<com.google.android.material.card.MaterialCardView
android:id="#+id/text_bg"
android:layout_width="110dp"
android:layout_height="110dp"
app:cardBackgroundColor="#color/green_500"
app:cardCornerRadius="50dp"
app:cardElevation="5dp"
android:layout_gravity="center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/image_session"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:src="#drawable/photo_male_7" />
</com.google.android.material.card.MaterialCardView>
</RelativeLayout>
In Fragment
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.raounded_corners,container,false);
return v;
}
raounded_corners.xml layout cornerRadius showing in activity but not showing in fragment
How to fix this.
In Activity
in fragment
If you are trying to make the imageview circular, I propose this approach.Create the custom view and set it in your xml. It works perfectly. If this helps you, an upvote will be appreciated.
Create a custom Circular view like shown below. CircleImageView.java
package com.fishpott.fishpott5.Views;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.widget.ImageView;
import com.fishpott.fishpott5.R;
public class CircleImageView extends AppCompatImageView {
private static final ImageView.ScaleType SCALE_TYPE = ImageView.ScaleType.CENTER_CROP;
private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
private static final int COLORDRAWABLE_DIMENSION = 2;
private static final int DEFAULT_BORDER_WIDTH = 0;
private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
private static final int DEFAULT_FILL_COLOR = Color.TRANSPARENT;
private static final boolean DEFAULT_BORDER_OVERLAY = false;
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 final Paint mFillPaint = new Paint();
private int mBorderColor = DEFAULT_BORDER_COLOR;
private int mBorderWidth = DEFAULT_BORDER_WIDTH;
private int mFillColor = DEFAULT_FILL_COLOR;
private Bitmap mBitmap;
private BitmapShader mBitmapShader;
private int mBitmapWidth;
private int mBitmapHeight;
private float mDrawableRadius;
private float mBorderRadius;
private ColorFilter mColorFilter;
private boolean mReady;
private boolean mSetupPending;
private boolean mBorderOverlay;
private boolean mDisableCircularTransformation;
public CircleImageView(Context context) {
super(context);
init();
}
public CircleImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);
mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_civ_border_width, DEFAULT_BORDER_WIDTH);
mBorderColor = a.getColor(R.styleable.CircleImageView_civ_border_color, DEFAULT_BORDER_COLOR);
mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_civ_border_overlay, DEFAULT_BORDER_OVERLAY);
mFillColor = a.getColor(R.styleable.CircleImageView_civ_fill_color, DEFAULT_FILL_COLOR);
a.recycle();
init();
}
private void init() {
super.setScaleType(SCALE_TYPE);
mReady = true;
if (mSetupPending) {
setup();
mSetupPending = false;
}
}
#Override
public ImageView.ScaleType getScaleType() {
return SCALE_TYPE;
}
#Override
public void setScaleType(ImageView.ScaleType scaleType) {
if (scaleType != SCALE_TYPE) {
throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));
}
}
#Override
public void setAdjustViewBounds(boolean adjustViewBounds) {
if (adjustViewBounds) {
throw new IllegalArgumentException("adjustViewBounds not supported.");
}
}
#Override
protected void onDraw(Canvas canvas) {
if (mDisableCircularTransformation) {
super.onDraw(canvas);
return;
}
if (mBitmap == null) {
return;
}
if (mFillColor != Color.TRANSPARENT) {
canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mFillPaint);
}
canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mBitmapPaint);
if (mBorderWidth > 0) {
canvas.drawCircle(mBorderRect.centerX(), mBorderRect.centerY(), mBorderRadius, mBorderPaint);
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
setup();
}
#Override
public void setPadding(int left, int top, int right, int bottom) {
super.setPadding(left, top, right, bottom);
setup();
}
#Override
public void setPaddingRelative(int start, int top, int end, int bottom) {
super.setPaddingRelative(start, top, end, bottom);
setup();
}
public int getBorderColor() {
return mBorderColor;
}
public void setBorderColor(#ColorInt int borderColor) {
if (borderColor == mBorderColor) {
return;
}
mBorderColor = borderColor;
mBorderPaint.setColor(mBorderColor);
invalidate();
}
/**
* #deprecated Use {#link #setBorderColor(int)} instead
*/
#Deprecated
public void setBorderColorResource(#ColorRes int borderColorRes) {
setBorderColor(getContext().getResources().getColor(borderColorRes));
}
/**
* Return the color drawn behind the circle-shaped drawable.
*
* #return The color drawn behind the drawable
*
* #deprecated Fill color support is going to be removed in the future
*/
#Deprecated
public int getFillColor() {
return mFillColor;
}
/**
* Set a color to be drawn behind the circle-shaped drawable. Note that
* this has no effect if the drawable is opaque or no drawable is set.
*
* #param fillColor The color to be drawn behind the drawable
*
* #deprecated Fill color support is going to be removed in the future
*/
#Deprecated
public void setFillColor(#ColorInt int fillColor) {
if (fillColor == mFillColor) {
return;
}
mFillColor = fillColor;
mFillPaint.setColor(fillColor);
invalidate();
}
/**
* Set a color to be drawn behind the circle-shaped drawable. Note that
* this has no effect if the drawable is opaque or no drawable is set.
*
* #param fillColorRes The color resource to be resolved to a color and
* drawn behind the drawable
*
* #deprecated Fill color support is going to be removed in the future
*/
#Deprecated
public void setFillColorResource(#ColorRes int fillColorRes) {
setFillColor(getContext().getResources().getColor(fillColorRes));
}
public int getBorderWidth() {
return mBorderWidth;
}
public void setBorderWidth(int borderWidth) {
if (borderWidth == mBorderWidth) {
return;
}
mBorderWidth = borderWidth;
setup();
}
public boolean isBorderOverlay() {
return mBorderOverlay;
}
public void setBorderOverlay(boolean borderOverlay) {
if (borderOverlay == mBorderOverlay) {
return;
}
mBorderOverlay = borderOverlay;
setup();
}
public boolean isDisableCircularTransformation() {
return mDisableCircularTransformation;
}
public void setDisableCircularTransformation(boolean disableCircularTransformation) {
if (mDisableCircularTransformation == disableCircularTransformation) {
return;
}
mDisableCircularTransformation = disableCircularTransformation;
initializeBitmap();
}
#Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
initializeBitmap();
}
#Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
initializeBitmap();
}
#Override
public void setImageResource(#DrawableRes int resId) {
super.setImageResource(resId);
initializeBitmap();
}
#Override
public void setImageURI(Uri uri) {
super.setImageURI(uri);
initializeBitmap();
}
#Override
public void setColorFilter(ColorFilter cf) {
if (cf == mColorFilter) {
return;
}
mColorFilter = cf;
applyColorFilter();
invalidate();
}
#Override
public ColorFilter getColorFilter() {
return mColorFilter;
}
private void applyColorFilter() {
if (mBitmapPaint != null) {
mBitmapPaint.setColorFilter(mColorFilter);
}
}
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(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
}
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 initializeBitmap() {
if (mDisableCircularTransformation) {
mBitmap = null;
} else {
mBitmap = getBitmapFromDrawable(getDrawable());
}
setup();
}
private void setup() {
if (!mReady) {
mSetupPending = true;
return;
}
if (getWidth() == 0 && getHeight() == 0) {
return;
}
if (mBitmap == null) {
invalidate();
return;
}
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);
mFillPaint.setStyle(Paint.Style.FILL);
mFillPaint.setAntiAlias(true);
mFillPaint.setColor(mFillColor);
mBitmapHeight = mBitmap.getHeight();
mBitmapWidth = mBitmap.getWidth();
mBorderRect.set(calculateBounds());
mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f);
mDrawableRect.set(mBorderRect);
if (!mBorderOverlay && mBorderWidth > 0) {
mDrawableRect.inset(mBorderWidth - 1.0f, mBorderWidth - 1.0f);
}
mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f);
applyColorFilter();
updateShaderMatrix();
invalidate();
}
private RectF calculateBounds() {
int availableWidth = getWidth() - getPaddingLeft() - getPaddingRight();
int availableHeight = getHeight() - getPaddingTop() - getPaddingBottom();
int sideLength = Math.min(availableWidth, availableHeight);
float left = getPaddingLeft() + (availableWidth - sideLength) / 2f;
float top = getPaddingTop() + (availableHeight - sideLength) / 2f;
return new RectF(left, top, left + sideLength, top + sideLength);
}
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);
}
}
Set the view in your xml
<com.fishpott.fishpott5.Views.CircleImageView
android:id="#+id/activity_setprofilepicture_profilepicture_imageview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="#string/none"
android:src="#drawable/setprofilepicture_activity_imageholder_default_image"
app:civ_border_color="#android:color/transparent"
app:civ_border_width="0dp" />
The reason you see "Views" in my xml call of the CircleImageView is because my CircleImageView.java is in "Views" folder/package.
This code creates a circle picture in Android:
public class CircleImageView extends ImageView {
private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
private static final int COLORDRAWABLE_DIMENSION = 2;
private static final int DEFAULT_BORDER_WIDTH = 0;
private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
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 = DEFAULT_BORDER_COLOR;
private int mBorderWidth = DEFAULT_BORDER_WIDTH;
private Bitmap mBitmap;
private BitmapShader mBitmapShader;
private int mBitmapWidth;
private int mBitmapHeight;
private float mDrawableRadius;
private float mBorderRadius;
private ColorFilter mColorFilter;
private boolean mReady;
private boolean mSetupPending;
public CircleImageView(Context context) {
super(context);
init();
}
public CircleImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);
mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH);
mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR);
a.recycle();
init();
}
private void init() {
super.setScaleType(SCALE_TYPE);
mReady = true;
if (mSetupPending) {
setup();
mSetupPending = false;
}
}
#Override
public ScaleType getScaleType() {
return SCALE_TYPE;
}
#Override
public void setScaleType(ScaleType scaleType) {
if (scaleType != SCALE_TYPE) {
throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));
}
}
#Override
public void setAdjustViewBounds(boolean adjustViewBounds) {
if (adjustViewBounds) {
throw new IllegalArgumentException("adjustViewBounds not supported.");
}
}
#Override
protected void onDraw(Canvas canvas) {
if (getDrawable() == null) {
return;
}
canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint);
if (mBorderWidth != 0) {
canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint);
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
setup();
}
public int getBorderColor() {
return mBorderColor;
}
public void setBorderColor(int borderColor) {
if (borderColor == mBorderColor) {
return;
}
mBorderColor = borderColor;
mBorderPaint.setColor(mBorderColor);
invalidate();
}
public int getBorderWidth() {
return mBorderWidth;
}
public void setBorderWidth(int borderWidth) {
if (borderWidth == mBorderWidth) {
return;
}
mBorderWidth = borderWidth;
setup();
}
#Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
mBitmap = bm;
setup();
}
#Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
mBitmap = getBitmapFromDrawable(drawable);
setup();
}
#Override
public void setImageResource(int resId) {
super.setImageResource(resId);
mBitmap = getBitmapFromDrawable(getDrawable());
setup();
}
#Override
public void setImageURI(Uri uri) {
super.setImageURI(uri);
mBitmap = getBitmapFromDrawable(getDrawable());
setup();
}
#Override
public void setColorFilter(ColorFilter cf) {
if (cf == mColorFilter) {
return;
}
mColorFilter = cf;
mBitmapPaint.setColorFilter(mColorFilter);
invalidate();
}
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(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
}
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} catch (OutOfMemoryError e) {
return null;
}
}
private void setup() {
if (!mReady) {
mSetupPending = true;
return;
}
if (mBitmap == null) {
return;
}
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);
mBitmapHeight = mBitmap.getHeight();
mBitmapWidth = mBitmap.getWidth();
mBorderRect.set(0, 0, getWidth(), getHeight());
mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2);
mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() - mBorderWidth, mBorderRect.height() - mBorderWidth);
mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2);
updateShaderMatrix();
invalidate();
}
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) + mBorderWidth, (int) (dy + 0.5f) + mBorderWidth);
mBitmapShader.setLocalMatrix(mShaderMatrix);
}
My problem in this line:
R.styleable.CircleImageView
R.styleable.CircleImageView_border_width
R.styleable.CircleImageView_border_color
It cannot resolve the symbol CircleImageView, CircleImageView_border_width and CircleImageView_border_color
The import:
package de.hdodenhof.circleimageview;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.util.AttributeSet;
import android.widget.ImageView;
import com.example.user.getion_ecol.R;
Hello You need to create value resource file attrs.xml in res/values folder with following code
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CircleImageView">
<attr name="civ_border_width" format="dimension" />
<attr name="civ_border_color" format="color" />
<attr name="civ_border_overlay" format="boolean" />
<attr name="civ_fill_color" format="color" />
</declare-styleable>
</resources>
It will solve you problem
You have to create a resource file called styleable with those variables and give them the correct values, but if you have found that code on Internet, I guess that the values of those variables are allowed.
When you upgrade your dependencies you need to add styles attrs.xml file in your project/src/main/main/res/values.
Follow the code below and paste it inside attrs.xml file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CircleImageView">
<attr name="civ_border_width" format="dimension" />
<attr name="civ_border_color" format="color" />
<attr name="civ_border_overlay" format="boolean" />
<attr name="civ_fill_color" format="color" />
</declare-styleable>
</resources>
If you already have the attrs.xml file just simply paste which line is missing.
Create the missing resource file if error is still not fixed then add this import
import com.example.<YOUR_APP_NAME>.R;
I am trying to create the circular image view. After searching google I have tried something but its not working.
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
class WheelItemView extends ImageView {
private int _index;
private float _x;
private float _y;
private int _width;
private int _height;
private boolean _drawn;
private float _currentAngle;
private Paint paint;
private Paint paintBorder;
private int borderWidth;
private boolean _hasRotation = false;
private float _dx=0;
private float _dy=0;
private Bitmap image;
private int canvasSize;
public WheelItemView(Context context) {
this(context, null);
}
public WheelItemView(Context context, AttributeSet attrs) {
this(context, attrs, in.eaft.byoo.R.attr.circularImageViewStyle);
// this(context, attrs, 0);
}
public WheelItemView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
paint = new Paint();
paint.setAntiAlias(true);
paintBorder = new Paint();
paintBorder.setAntiAlias(true);
// load the styled attributes and set their properties
TypedArray attributes = context.obtainStyledAttributes(attrs, in.eaft.byoo.R.styleable.CircularImageView, defStyle, 0);
if(attributes.getBoolean(in.eaft.byoo.R.styleable.CircularImageView_border, true)) {
int defaultBorderSize = (int) (4 * getContext().getResources().getDisplayMetrics()
.density + 0.5f);
setBorderWidth(attributes.getDimensionPixelOffset(in.eaft.byoo.R.styleable.
CircularImageView_border_width, defaultBorderSize));
setBorderColor(attributes.getColor(in.eaft.byoo.R.styleable.CircularImageView_border_color,
Color.WHITE));
}
if(attributes.getBoolean(in.eaft.byoo.R.styleable.CircularImageView_shadow, true))
addShadow();
}
private void addShadow() {
setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);
}
private void setBorderColor(int color) {
if(paintBorder != null)
paintBorder.setColor(color);
this.invalidate();
}
private void setBorderWidth(int borderWidth) {
this.borderWidth = borderWidth;
this.requestLayout();
this.invalidate();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
/*_width= measureWidth(widthMeasureSpec);
_height = measureHeight(heightMeasureSpec);*/
setMeasuredDimension(_width, _height);
}
private int measureHeight(int measureSpecHeight) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
// The child can be as large as it wants up to the specified size.
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
result = canvasSize;
}
return (result + 2);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// The parent has determined an exact size for the child.
result = specSize;
} else if (specMode == MeasureSpec.AT_MOST) {
// The child can be as large as it wants up to the specified size.
result = specSize;
} else {
// The parent has not imposed any constraint on the child.
result = canvasSize;
}
return result;
}
#Override
public void setImageBitmap(Bitmap src)
{
_width = src.getWidth();
_height = src.getHeight();
if(_hasRotation) {
calculateDistance();
}
super.setImageBitmap(src);
}
#Override
protected void onDraw(Canvas canvas)
{
//if(_hasRotation) {
/*Drawable d = getDrawable();
if(d!=null && d instanceof BitmapDrawable && ((BitmapDrawable)d).getBitmap()!=null) {
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
canvas.save();
canvas.translate(_dx, _dy);
canvas.rotate(_currentAngle+90, _width/2f, _height/2f);
// canvas.drawText(text, 0, 0, p);
canvas.drawBitmap(((BitmapDrawable)d).getBitmap(),0, 0, p);
canvas.restore();
return;
}*/
System.out.println("get drawable is null : " + (getDrawable() == null));
image = drawableToBitmap(getDrawable());
// init shader
if (image != null) {
canvasSize = canvas.getWidth();
if(canvas.getHeight()<canvasSize)
canvasSize = canvas.getHeight();
BitmapShader shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvasSize,
canvasSize, false),
Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
// circleCenter is the x or y of the view's center
// radius is the radius in pixels of the cirle to be drawn
// paint contains the shader that will texture the shape
int circleCenter = (canvasSize - (borderWidth * 2)) / 2;
canvas.save();
// canvas.translate(_dx, _dy);
canvas.rotate(_currentAngle+90, _width/2f, _height/2f);
canvas.drawCircle(_width-_dx, _height-_dy/2,
borderWidth * 10, paintBorder);
canvas.drawCircle(_width-_dx, _height-_dy/2,
borderWidth * 10, paint);
/*canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth,
((canvasSize - (borderWidth * 2)) / 2) + borderWidth - 4.0f, paintBorder);
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth,
((canvasSize - (borderWidth * 2)) / 2) - 4.0f, paint);*/
canvas.restore();
// }
}
super.onDraw(canvas);
}
private Bitmap drawableToBitmap(Drawable drawable) {
if (drawable == null) {
return null;
} else if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(70,
70, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
private void calculateDistance()
{
_dx = (float) ((Math.sqrt(_width*_width + _height*_height)-_width)/2.0f);
_dy = (float) ((Math.sqrt(_width*_width + _height*_height)-_height)/2.0f);
}
public void setIndex(int index)
{
this._index = index;
}
public int getIndex()
{
return _index;
}
public void setCurrentAngle(float currentAngle)
{
this._currentAngle = currentAngle;
}
public float getCurrentAngle()
{
return _currentAngle;
}
public void setAxisX(float x)
{
this._x = x;
}
public float getAxisX()
{
return _x;
}
public void setAxisY(float y)
{
this._y = y;
}
public float getAxisY()
{
return _y;
}
public void setDrawn(boolean drawn)
{
this._drawn = drawn;
}
public boolean isDrawn()
{
return _drawn;
}
public void setItemWidth(int _width)
{
this._width = _width;
}
public float getItemWidth()
{
return _width;
}
public void setItemHeight(int _height)
{
this._height = _height;
}
public float getItemHeight()
{
return _height;
}
public int getDistanceX()
{
return (int)_dx;
}
public int getDistanceY()
{
return (int)_dy;
}
public void setRotatedItem(Boolean flag)
{
_hasRotation = flag;
if(_hasRotation && (_dx==0 || _dy ==0)) {
calculateDistance();
}
if(!_hasRotation) {
_dx = _dy = 0;
}
}
}
My images are not circular.Instead part of circle is being displayed behind the square image.
can anyone tell me what mistake I have done?
I think ur asking for this
jst create a shape in res>drawable
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<solid android:color="#a7a7a7" />
<stroke android:width="1dp" android:color="#818181" />
</shape>
and use this shape in ur imageview
I've added an ImageView with rounded corners to a ListView. My project is working fine. But not all the images are the same size. My code is below:
holder.img.setImageBitmap(createRoundedBitmap(user.getbi(),20));
private Bitmap createRoundedBitmap(Bitmap getbi, int i) {
if (getbi == null) {
return null;
}
Rect rect = new Rect(0, 0, getbi.getWidth(), getbi.getHeight());
// create output bitmap
Bitmap output = Bitmap.createBitmap(getbi.getWidth(), getbi.getHeight(), Config.ARGB_8888);
// assign canvas with output bitmap
Canvas canvas = new Canvas(output);
canvas.drawARGB(0,0, 0,0);
// initialize paint
Paint paint = new Paint();
paint.setAntiAlias(true);
// draw rounded rect to bitmap
paint.setColor(0xFFFFFFFF);
canvas.drawRoundRect(new RectF(rect), i, i, paint);
// copy original bitmap to rounded area
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(getbi, rect, rect, paint);
return output;
}
So, what should I do to fix the size of this bitmap?
Try this way,hope this will help you to solve your problem.
RoundedImageView.java
public class RoundedImageView extends ImageView {
public static final String TAG = "RoundedImageView";
public static final int DEFAULT_RADIUS = 0;
public static final int DEFAULT_BORDER_WIDTH = 0;
private static final ScaleType[] SCALE_TYPES = {
ScaleType.MATRIX,
ScaleType.FIT_XY,
ScaleType.FIT_START,
ScaleType.FIT_CENTER,
ScaleType.FIT_END,
ScaleType.CENTER,
ScaleType.CENTER_CROP,
ScaleType.CENTER_INSIDE
};
private int mCornerRadius = DEFAULT_RADIUS;
private int mBorderWidth = DEFAULT_BORDER_WIDTH;
private ColorStateList mBorderColor =
ColorStateList.valueOf(RoundedDrawable.DEFAULT_BORDER_COLOR);
private boolean mOval = false;
private boolean mRoundBackground = false;
private int mResource;
private Drawable mDrawable;
private Drawable mBackgroundDrawable;
private ScaleType mScaleType;
public RoundedImageView(Context context) {
super(context);
}
public RoundedImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundedImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundedImageView, defStyle, 0);
int index = a.getInt(R.styleable.RoundedImageView_android_scaleType, 1);
if (index >= 0) {
setScaleType(SCALE_TYPES[index]);
} else {
// default scaletype to FIT_CENTER
setScaleType(ScaleType.FIT_CENTER);
}
mCornerRadius = a.getDimensionPixelSize(R.styleable.RoundedImageView_corner_radius, 360);
mBorderWidth = a.getDimensionPixelSize(R.styleable.RoundedImageView_border_width,2);
// don't allow negative values for radius and border
if (mCornerRadius < 0) {
mCornerRadius = DEFAULT_RADIUS;
}
if (mBorderWidth < 0) {
mBorderWidth = DEFAULT_BORDER_WIDTH;
}
mBorderColor = a.getColorStateList(R.styleable.RoundedImageView_border_color);
if (mBorderColor == null) {
mBorderColor = ColorStateList.valueOf(R.color.blue);
}
mRoundBackground = a.getBoolean(R.styleable.RoundedImageView_round_background, false);
mOval = a.getBoolean(R.styleable.RoundedImageView_is_oval, false);
updateDrawableAttrs();
updateBackgroundDrawableAttrs();
a.recycle();
}
#Override
protected void drawableStateChanged() {
super.drawableStateChanged();
invalidate();
}
/**
* Return the current scale type in use by this ImageView.
*
* #attr ref android.R.styleable#ImageView_scaleType
* #see android.widget.ImageView.ScaleType
*/
#Override
public ScaleType getScaleType() {
return mScaleType;
}
/**
* Controls how the image should be resized or moved to match the size
* of this ImageView.
*
* #param scaleType The desired scaling mode.
* #attr ref android.R.styleable#ImageView_scaleType
*/
#Override
public void setScaleType(ScaleType scaleType) {
if (scaleType == null) {
throw new NullPointerException();
}
if (mScaleType != scaleType) {
mScaleType = scaleType;
switch (scaleType) {
case CENTER:
case CENTER_CROP:
case CENTER_INSIDE:
case FIT_CENTER:
case FIT_START:
case FIT_END:
case FIT_XY:
super.setScaleType(ScaleType.FIT_XY);
break;
default:
super.setScaleType(scaleType);
break;
}
updateDrawableAttrs();
updateBackgroundDrawableAttrs();
invalidate();
}
}
#Override
public void setImageDrawable(Drawable drawable) {
mResource = 0;
mDrawable = RoundedDrawable.fromDrawable(drawable);
updateDrawableAttrs();
super.setImageDrawable(mDrawable);
}
#Override
public void setImageBitmap(Bitmap bm) {
mResource = 0;
mDrawable = RoundedDrawable.fromBitmap(bm);
updateDrawableAttrs();
super.setImageDrawable(mDrawable);
}
#Override
public void setImageResource(int resId) {
if (mResource != resId) {
mResource = resId;
mDrawable = resolveResource();
updateDrawableAttrs();
super.setImageDrawable(mDrawable);
}
}
#Override public void setImageURI(Uri uri) {
super.setImageURI(uri);
setImageDrawable(getDrawable());
}
private Drawable resolveResource() {
Resources rsrc = getResources();
if (rsrc == null) {
return null;
}
Drawable d = null;
if (mResource != 0) {
try {
d = rsrc.getDrawable(mResource);
} catch (Exception e) {
Log.w(TAG, "Unable to find resource: " + mResource, e);
// Don't try again.
mResource = 0;
}
}
return RoundedDrawable.fromDrawable(d);
}
#Override
public void setBackground(Drawable background) {
setBackgroundDrawable(background);
}
private void updateDrawableAttrs() {
updateAttrs(mDrawable, false);
}
private void updateBackgroundDrawableAttrs() {
updateAttrs(mBackgroundDrawable, true);
}
private void updateAttrs(Drawable drawable, boolean background) {
if (drawable == null) {
return;
}
if (drawable instanceof RoundedDrawable) {
((RoundedDrawable) drawable)
.setScaleType(mScaleType)
.setCornerRadius(background && !mRoundBackground ? 0 : mCornerRadius)
.setBorderWidth(background && !mRoundBackground ? 0 : mBorderWidth)
.setBorderColors(mBorderColor)
.setOval(mOval);
} else if (drawable instanceof LayerDrawable) {
// loop through layers to and set drawable attrs
LayerDrawable ld = ((LayerDrawable) drawable);
int layers = ld.getNumberOfLayers();
for (int i = 0; i < layers; i++) {
updateAttrs(ld.getDrawable(i), background);
}
}
}
#Override
#Deprecated
public void setBackgroundDrawable(Drawable background) {
mBackgroundDrawable = RoundedDrawable.fromDrawable(background);
updateBackgroundDrawableAttrs();
super.setBackgroundDrawable(mBackgroundDrawable);
}
public int getCornerRadius() {
return mCornerRadius;
}
public void setCornerRadius(int radius) {
if (mCornerRadius == radius) {
return;
}
mCornerRadius = radius;
updateDrawableAttrs();
updateBackgroundDrawableAttrs();
}
public int getBorderWidth() {
return mBorderWidth;
}
public void setBorderWidth(int width) {
if (mBorderWidth == width) {
return;
}
mBorderWidth = width;
updateDrawableAttrs();
updateBackgroundDrawableAttrs();
invalidate();
}
public int getBorderColor() {
return mBorderColor.getDefaultColor();
}
public void setBorderColor(int color) {
setBorderColors(ColorStateList.valueOf(color));
}
public ColorStateList getBorderColors() {
return mBorderColor;
}
public void setBorderColors(ColorStateList colors) {
if (mBorderColor.equals(colors)) {
return;
}
mBorderColor =
(colors != null) ? colors : ColorStateList.valueOf(RoundedDrawable.DEFAULT_BORDER_COLOR);
updateDrawableAttrs();
updateBackgroundDrawableAttrs();
if (mBorderWidth > 0) {
invalidate();
}
}
public boolean isOval() {
return mOval;
}
public void setOval(boolean oval) {
mOval = oval;
updateDrawableAttrs();
updateBackgroundDrawableAttrs();
invalidate();
}
public boolean isRoundBackground() {
return mRoundBackground;
}
public void setRoundBackground(boolean roundBackground) {
if (mRoundBackground == roundBackground) {
return;
}
mRoundBackground = roundBackground;
updateBackgroundDrawableAttrs();
invalidate();
}
}
RoundedDrawable.java
public class RoundedDrawable extends Drawable {
public static final String TAG = "RoundedDrawable";
public static final int DEFAULT_BORDER_COLOR = Color.BLACK;
private final RectF mBounds = new RectF();
private final RectF mDrawableRect = new RectF();
private final RectF mBitmapRect = new RectF();
private final BitmapShader mBitmapShader;
private final Paint mBitmapPaint;
private final int mBitmapWidth;
private final int mBitmapHeight;
private final RectF mBorderRect = new RectF();
private final Paint mBorderPaint;
private final Matrix mShaderMatrix = new Matrix();
private float mCornerRadius = 0;
private boolean mOval = false;
private float mBorderWidth = 0;
private ColorStateList mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);
private ScaleType mScaleType = ScaleType.FIT_CENTER;
public RoundedDrawable(Bitmap bitmap) {
mBitmapWidth = bitmap.getWidth();
mBitmapHeight = bitmap.getHeight();
mBitmapRect.set(0, 0, mBitmapWidth, mBitmapHeight);
mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mBitmapShader.setLocalMatrix(mShaderMatrix);
mBitmapPaint = new Paint();
mBitmapPaint.setStyle(Paint.Style.FILL);
mBitmapPaint.setAntiAlias(true);
mBitmapPaint.setShader(mBitmapShader);
mBorderPaint = new Paint();
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setAntiAlias(true);
mBorderPaint.setColor(mBorderColor.getColorForState(getState(), DEFAULT_BORDER_COLOR));
mBorderPaint.setStrokeWidth(mBorderWidth);
}
public static RoundedDrawable fromBitmap(Bitmap bitmap) {
if (bitmap != null) {
return new RoundedDrawable(bitmap);
} else {
return null;
}
}
public static Drawable fromDrawable(Drawable drawable) {
if (drawable != null) {
if (drawable instanceof RoundedDrawable) {
// just return if it's already a RoundedDrawable
return drawable;
} else if (drawable instanceof LayerDrawable) {
LayerDrawable ld = (LayerDrawable) drawable;
int num = ld.getNumberOfLayers();
// loop through layers to and change to RoundedDrawables if possible
for (int i = 0; i < num; i++) {
Drawable d = ld.getDrawable(i);
ld.setDrawableByLayerId(ld.getId(i), fromDrawable(d));
}
return ld;
}
// try to get a bitmap from the drawable and
Bitmap bm = drawableToBitmap(drawable);
if (bm != null) {
return new RoundedDrawable(bm);
} else {
Log.w(TAG, "Failed to create bitmap from drawable!");
}
}
return drawable;
}
public static Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap;
int width = Math.max(drawable.getIntrinsicWidth(), 1);
int height = Math.max(drawable.getIntrinsicHeight(), 1);
try {
bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
} catch (Exception e) {
e.printStackTrace();
bitmap = null;
}
return bitmap;
}
#Override
public boolean isStateful() {
return mBorderColor.isStateful();
}
#Override
protected boolean onStateChange(int[] state) {
int newColor = mBorderColor.getColorForState(state, 0);
if (mBorderPaint.getColor() != newColor) {
mBorderPaint.setColor(newColor);
return true;
} else {
return super.onStateChange(state);
}
}
private void updateShaderMatrix() {
float scale;
float dx;
float dy;
switch (mScaleType) {
case CENTER:
mBorderRect.set(mBounds);
mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);
mShaderMatrix.set(null);
mShaderMatrix.setTranslate((int) ((mBorderRect.width() - mBitmapWidth) * 0.5f + 0.5f),
(int) ((mBorderRect.height() - mBitmapHeight) * 0.5f + 0.5f));
break;
case CENTER_CROP:
mBorderRect.set(mBounds);
mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);
mShaderMatrix.set(null);
dx = 0;
dy = 0;
if (mBitmapWidth * mBorderRect.height() > mBorderRect.width() * mBitmapHeight) {
scale = mBorderRect.height() / (float) mBitmapHeight;
dx = (mBorderRect.width() - mBitmapWidth * scale) * 0.5f;
} else {
scale = mBorderRect.width() / (float) mBitmapWidth;
dy = (mBorderRect.height() - mBitmapHeight * scale) * 0.5f;
}
mShaderMatrix.setScale(scale, scale);
mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth,
(int) (dy + 0.5f) + mBorderWidth);
break;
case CENTER_INSIDE:
mShaderMatrix.set(null);
if (mBitmapWidth <= mBounds.width() && mBitmapHeight <= mBounds.height()) {
scale = 1.0f;
} else {
scale = Math.min(mBounds.width() / (float) mBitmapWidth,
mBounds.height() / (float) mBitmapHeight);
}
dx = (int) ((mBounds.width() - mBitmapWidth * scale) * 0.5f + 0.5f);
dy = (int) ((mBounds.height() - mBitmapHeight * scale) * 0.5f + 0.5f);
mShaderMatrix.setScale(scale, scale);
mShaderMatrix.postTranslate(dx, dy);
mBorderRect.set(mBitmapRect);
mShaderMatrix.mapRect(mBorderRect);
mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);
mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect, Matrix.ScaleToFit.FILL);
break;
default:
case FIT_CENTER:
mBorderRect.set(mBitmapRect);
mShaderMatrix.setRectToRect(mBitmapRect, mBounds, Matrix.ScaleToFit.CENTER);
mShaderMatrix.mapRect(mBorderRect);
mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);
mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect, Matrix.ScaleToFit.FILL);
break;
case FIT_END:
mBorderRect.set(mBitmapRect);
mShaderMatrix.setRectToRect(mBitmapRect, mBounds, Matrix.ScaleToFit.END);
mShaderMatrix.mapRect(mBorderRect);
mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);
mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect, Matrix.ScaleToFit.FILL);
break;
case FIT_START:
mBorderRect.set(mBitmapRect);
mShaderMatrix.setRectToRect(mBitmapRect, mBounds, Matrix.ScaleToFit.START);
mShaderMatrix.mapRect(mBorderRect);
mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);
mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect, Matrix.ScaleToFit.FILL);
break;
case FIT_XY:
mBorderRect.set(mBounds);
mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);
mShaderMatrix.set(null);
mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect, Matrix.ScaleToFit.FILL);
break;
}
mDrawableRect.set(mBorderRect);
mBitmapShader.setLocalMatrix(mShaderMatrix);
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mBounds.set(bounds);
updateShaderMatrix();
}
#Override
public void draw(Canvas canvas) {
if (mOval) {
if (mBorderWidth > 0) {
canvas.drawOval(mDrawableRect, mBitmapPaint);
canvas.drawOval(mBorderRect, mBorderPaint);
} else {
canvas.drawOval(mDrawableRect, mBitmapPaint);
}
} else {
if (mBorderWidth > 0) {
canvas.drawRoundRect(mDrawableRect, Math.max(mCornerRadius, 0),
Math.max(mCornerRadius, 0), mBitmapPaint);
canvas.drawRoundRect(mBorderRect, mCornerRadius, mCornerRadius, mBorderPaint);
} else {
canvas.drawRoundRect(mDrawableRect, mCornerRadius, mCornerRadius, mBitmapPaint);
}
}
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
#Override
public void setAlpha(int alpha) {
mBitmapPaint.setAlpha(alpha);
invalidateSelf();
}
#Override
public void setColorFilter(ColorFilter cf) {
mBitmapPaint.setColorFilter(cf);
invalidateSelf();
}
#Override public void setDither(boolean dither) {
mBitmapPaint.setDither(dither);
invalidateSelf();
}
#Override public void setFilterBitmap(boolean filter) {
mBitmapPaint.setFilterBitmap(filter);
invalidateSelf();
}
#Override
public int getIntrinsicWidth() {
return mBitmapWidth;
}
#Override
public int getIntrinsicHeight() {
return mBitmapHeight;
}
public float getCornerRadius() {
return mCornerRadius;
}
public RoundedDrawable setCornerRadius(float radius) {
mCornerRadius = radius;
return this;
}
public float getBorderWidth() {
return mBorderWidth;
}
public RoundedDrawable setBorderWidth(int width) {
mBorderWidth = width;
mBorderPaint.setStrokeWidth(mBorderWidth);
return this;
}
public int getBorderColor() {
return mBorderColor.getDefaultColor();
}
public RoundedDrawable setBorderColor(int color) {
return setBorderColors(ColorStateList.valueOf(color));
}
public ColorStateList getBorderColors() {
return mBorderColor;
}
public RoundedDrawable setBorderColors(ColorStateList colors) {
mBorderColor = colors != null ? colors : ColorStateList.valueOf(0);
mBorderPaint.setColor(mBorderColor.getColorForState(getState(), DEFAULT_BORDER_COLOR));
return this;
}
public boolean isOval() {
return mOval;
}
public RoundedDrawable setOval(boolean oval) {
mOval = oval;
return this;
}
public ScaleType getScaleType() {
return mScaleType;
}
public RoundedDrawable setScaleType(ScaleType scaleType) {
if (scaleType == null) {
scaleType = ScaleType.FIT_XY;
}
if (mScaleType != scaleType) {
mScaleType = scaleType;
updateShaderMatrix();
}
return this;
}
public Bitmap toBitmap() {
return drawableToBitmap(this);
}
}
attrs.xml
<resources>
<declare-styleable name="RoundedImageView">
<attr name="corner_radius" format="dimension" />
<attr name="border_width" format="dimension" />
<attr name="border_color" format="color" />
<attr name="round_background" format="boolean" />
<attr name="is_oval" format="boolean" />
<attr name="android:scaleType" />
</declare-styleable>
<declare-styleable name="CircleLayout">
<attr name="innerRadius" format="dimension" />
<attr name="sliceDivider" format="reference|color" />
<attr name="innerCircle" format="reference|color" />
<attr name="angleOffset" format="float" />
<attr name="angleRange" format="float" />
<attr name="layoutMode">
<enum name="normal" value="1" />
<enum name="pie" value="2" />
</attr>
<attr name="dividerWidth" format="dimension" />
</declare-styleable>
</resources>
How To Use
<YourPackageName.RoundedImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop"/>
Try this.
private Bitmap createRoundedBitmap(Bitmap getbi, int i,int neededWidth,int neededHeight) {
if (getbi == null) {
return null;
}
Rect rect = new Rect(0, 0, neededWidth, neededHeight);
Rect bmRect = new Rect(0, 0, getbi.getWidth(), getbi.getHeight());
// create output bitmap
Bitmap output = Bitmap.createBitmap(neededWidth, neededHeight, Config.ARGB_8888);
// assign canvas with output bitmap
Canvas canvas = new Canvas(output);
canvas.drawARGB(0,0, 0,0);
// initialize paint
Paint paint = new Paint();
paint.setAntiAlias(true);
// draw rounded rect to bitmap
paint.setColor(0xFFFFFFFF);
canvas.drawRoundRect(new RectF(rect), i, i, paint);
// copy original bitmap to rounded area
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(getbi, bmRect , rect, paint);
return output;
}
Usage :
createRoundedBitmap(yourBitmap,5,100,100); // You will get a bitmap 100x100 px
the following link might be useful here
http://murodese.wordpress.com/2010/07/01/rounded-imageviews-in-listviews/
Changing the width and height:
http://tech.pro/tutorial/620/csharp-tutorial-image-editing-saving-cropping-and-resizing
I have created a RoundedImageView control which draws a circular border around an image, clipping the image to within the circle bounds. Currently it has a flat colour border but I would like this to be a gradient effect that repeats around the border or even just a single radial gradient around the border but I would like this to "spin", ie rotate the gradient fill indefinitely to show the user the application hasn't frozen. Can anyone think how to achieve this?
My current layout
<lc.controls.RoundedImageView
android:id="#+id/progressimage"
android:layout_width="150dip"
android:layout_height="150dip"
android:padding="10dip"
android:src="#drawable/ocean"
android:scaleType="centerCrop"
app:border_width="4dip"
app:oval="false"
app:border_color="#color/border_background_colour" />
My rounded imageview if required
public class RoundedImageView extends ImageView {
public static final String TAG = "RoundedImageView";
public static final float DEFAULT_RADIUS = 0f;
public static final float DEFAULT_BORDER_WIDTH = 0f;
private static final ScaleType[] SCALE_TYPES = {
ScaleType.MATRIX,
ScaleType.FIT_XY,
ScaleType.FIT_START,
ScaleType.FIT_CENTER,
ScaleType.FIT_END,
ScaleType.CENTER,
ScaleType.CENTER_CROP,
ScaleType.CENTER_INSIDE
};
private float cornerRadius = DEFAULT_RADIUS;
private float borderWidth = DEFAULT_BORDER_WIDTH;
private ColorStateList borderColor =
ColorStateList.valueOf(RoundedDrawable.DEFAULT_BORDER_COLOR);
private boolean isOval = false;
private boolean mutateBackground = false;
private int mResource;
private Drawable mDrawable;
private Drawable mBackgroundDrawable;
private ScaleType mScaleType;
public RoundedImageView(Context context) {
super(context);
}
public RoundedImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundedImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundedImageView, defStyle, 0);
int index = a.getInt(R.styleable.RoundedImageView_android_scaleType, -1);
if (index >= 0) {
setScaleType(SCALE_TYPES[index]);
} else {
setScaleType(ScaleType.FIT_CENTER);
}
cornerRadius = a.getDimensionPixelSize(R.styleable.RoundedImageView_corner_radius, -1);
borderWidth = a.getDimensionPixelSize(R.styleable.RoundedImageView_border_width, -1);
// don't allow negative values for radius and border
if (cornerRadius < 0) {
cornerRadius = DEFAULT_RADIUS;
}
if (borderWidth < 0) {
borderWidth = DEFAULT_BORDER_WIDTH;
}
borderColor = a.getColorStateList(R.styleable.RoundedImageView_border_color);
if (borderColor == null) {
borderColor = ColorStateList.valueOf(RoundedDrawable.DEFAULT_BORDER_COLOR);
}
mutateBackground = a.getBoolean(R.styleable.RoundedImageView_mutate_background, false);
isOval = a.getBoolean(R.styleable.RoundedImageView_oval, false);
updateDrawableAttrs();
updateBackgroundDrawableAttrs(true);
a.recycle();
}
#Override
protected void drawableStateChanged() {
super.drawableStateChanged();
invalidate();
}
#Override
public ScaleType getScaleType() {
return mScaleType;
}
#Override
public void setScaleType(ScaleType scaleType) {
assert scaleType != null;
if (mScaleType != scaleType) {
mScaleType = scaleType;
switch (scaleType) {
case CENTER:
case CENTER_CROP:
case CENTER_INSIDE:
case FIT_CENTER:
case FIT_START:
case FIT_END:
case FIT_XY:
super.setScaleType(ScaleType.FIT_XY);
break;
default:
super.setScaleType(scaleType);
break;
}
updateDrawableAttrs();
updateBackgroundDrawableAttrs(false);
invalidate();
}
}
#Override
public void setImageDrawable(Drawable drawable) {
mResource = 0;
mDrawable = RoundedDrawable.fromDrawable(drawable);
updateDrawableAttrs();
super.setImageDrawable(mDrawable);
}
#Override
public void setImageBitmap(Bitmap bm) {
mResource = 0;
mDrawable = RoundedDrawable.fromBitmap(bm);
updateDrawableAttrs();
super.setImageDrawable(mDrawable);
}
#Override
public void setImageResource(int resId) {
if (mResource != resId) {
mResource = resId;
mDrawable = resolveResource();
updateDrawableAttrs();
super.setImageDrawable(mDrawable);
}
}
#Override public void setImageURI(Uri uri) {
super.setImageURI(uri);
setImageDrawable(getDrawable());
}
private Drawable resolveResource() {
Resources rsrc = getResources();
if (rsrc == null) { return null; }
Drawable d = null;
if (mResource != 0) {
try {
d = rsrc.getDrawable(mResource);
} catch (Exception e) {
Log.w(TAG, "Unable to find resource: " + mResource, e);
// Don't try again.
mResource = 0;
}
}
return RoundedDrawable.fromDrawable(d);
}
#Override
public void setBackground(Drawable background) {
setBackgroundDrawable(background);
}
private void updateDrawableAttrs() {
updateAttrs(mDrawable);
}
private void updateBackgroundDrawableAttrs(boolean convert) {
if (mutateBackground) {
if (convert) {
mBackgroundDrawable = RoundedDrawable.fromDrawable(mBackgroundDrawable);
}
updateAttrs(mBackgroundDrawable);
}
}
private void updateAttrs(Drawable drawable) {
if (drawable == null) { return; }
cornerRadius = drawable.getIntrinsicWidth();
if (drawable instanceof RoundedDrawable) {
((RoundedDrawable) drawable)
.setScaleType(mScaleType)
.setCornerRadius(cornerRadius)
.setBorderWidth(borderWidth)
.setBorderColor(borderColor)
.setOval(isOval);
} else if (drawable instanceof LayerDrawable) {
// loop through layers to and set drawable attrs
LayerDrawable ld = ((LayerDrawable) drawable);
for (int i = 0, layers = ld.getNumberOfLayers(); i < layers; i++) {
updateAttrs(ld.getDrawable(i));
}
}
}
#Override
#Deprecated
public void setBackgroundDrawable(Drawable background) {
mBackgroundDrawable = background;
updateBackgroundDrawableAttrs(true);
super.setBackgroundDrawable(mBackgroundDrawable);
}
public float getCornerRadius() {
return cornerRadius;
}
public void setCornerRadius(int resId) {
setCornerRadius(getResources().getDimension(resId));
}
public void setCornerRadius(float radius) {
if (cornerRadius == radius) { return; }
cornerRadius = radius;
updateDrawableAttrs();
updateBackgroundDrawableAttrs(false);
}
public float getBorderWidth() {
return borderWidth;
}
public void setBorderWidth(int resId) {
setBorderWidth(getResources().getDimension(resId));
}
public void setBorderWidth(float width) {
if (borderWidth == width) { return; }
borderWidth = width;
updateDrawableAttrs();
updateBackgroundDrawableAttrs(false);
invalidate();
}
public int getBorderColor() {
return borderColor.getDefaultColor();
}
public void setBorderColor(int color) {
setBorderColor(ColorStateList.valueOf(color));
}
public ColorStateList getBorderColors() {
return borderColor;
}
public void setBorderColor(ColorStateList colors) {
if (borderColor.equals(colors)) { return; }
borderColor =
(colors != null) ? colors : ColorStateList.valueOf(RoundedDrawable.DEFAULT_BORDER_COLOR);
updateDrawableAttrs();
updateBackgroundDrawableAttrs(false);
if (borderWidth > 0) {
invalidate();
}
}
public boolean isOval() {
return isOval;
}
public void setOval(boolean oval) {
isOval = oval;
updateDrawableAttrs();
updateBackgroundDrawableAttrs(false);
invalidate();
}
public boolean isMutateBackground() {
return mutateBackground;
}
public void setMutateBackground(boolean mutate) {
if (mutateBackground == mutate) { return; }
mutateBackground = mutate;
updateBackgroundDrawableAttrs(true);
invalidate();
}
}
public class RoundedDrawable extends Drawable {
public static final String TAG = "RoundedDrawable";
public static final int DEFAULT_BORDER_COLOR = Color.BLACK;
private final RectF mBounds = new RectF();
private final RectF mDrawableRect = new RectF();
private final RectF mBitmapRect = new RectF();
private final BitmapShader mBitmapShader;
private final Paint mBitmapPaint;
private final int mBitmapWidth;
private final int mBitmapHeight;
private final RectF mBorderRect = new RectF();
private final Paint mBorderPaint;
private final Matrix mShaderMatrix = new Matrix();
private float mCornerRadius = 0;
private boolean mOval = false;
private float mBorderWidth = 0;
private ColorStateList mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);
private ScaleType mScaleType = ScaleType.FIT_CENTER;
public RoundedDrawable(Bitmap bitmap) {
mBitmapWidth = bitmap.getWidth();
mBitmapHeight = bitmap.getHeight();
mBitmapRect.set(0, 0, mBitmapWidth, mBitmapHeight);
mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mBitmapShader.setLocalMatrix(mShaderMatrix);
mBitmapPaint = new Paint();
mBitmapPaint.setStyle(Paint.Style.FILL);
mBitmapPaint.setAntiAlias(true);
mBitmapPaint.setShader(mBitmapShader);
mBorderPaint = new Paint();
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setAntiAlias(true);
mBorderPaint.setColor(mBorderColor.getColorForState(getState(), DEFAULT_BORDER_COLOR));
mBorderPaint.setStrokeWidth(mBorderWidth);
}
public static RoundedDrawable fromBitmap(Bitmap bitmap) {
if (bitmap != null) {
return new RoundedDrawable(bitmap);
} else {
return null;
}
}
public static Drawable fromDrawable(Drawable drawable) {
if (drawable != null) {
if (drawable instanceof RoundedDrawable) {
// just return if it's already a RoundedDrawable
return drawable;
} else if (drawable instanceof LayerDrawable) {
LayerDrawable ld = (LayerDrawable) drawable;
int num = ld.getNumberOfLayers();
// loop through layers to and change to RoundedDrawables if possible
for (int i = 0; i < num; i++) {
Drawable d = ld.getDrawable(i);
ld.setDrawableByLayerId(ld.getId(i), fromDrawable(d));
}
return ld;
}
// try to get a bitmap from the drawable and
Bitmap bm = drawableToBitmap(drawable);
if (bm != null) {
return new RoundedDrawable(bm);
} else {
Log.w(TAG, "Failed to create bitmap from drawable!");
}
}
return drawable;
}
public static Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap;
int width = Math.max(drawable.getIntrinsicWidth(), 1);
int height = Math.max(drawable.getIntrinsicHeight(), 1);
try {
bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
} catch (Exception e) {
e.printStackTrace();
bitmap = null;
}
return bitmap;
}
#Override
public boolean isStateful() {
return mBorderColor.isStateful();
}
#Override
protected boolean onStateChange(int[] state) {
int newColor = mBorderColor.getColorForState(state, 0);
if (mBorderPaint.getColor() != newColor) {
mBorderPaint.setColor(newColor);
return true;
} else {
return super.onStateChange(state);
}
}
private void updateShaderMatrix() {
float scale;
float dx;
float dy;
switch (mScaleType) {
case CENTER:
mBorderRect.set(mBounds);
mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);
mShaderMatrix.set(null);
mShaderMatrix.setTranslate((int) ((mBorderRect.width() - mBitmapWidth) * 0.5f + 0.5f),
(int) ((mBorderRect.height() - mBitmapHeight) * 0.5f + 0.5f));
break;
case CENTER_CROP:
mBorderRect.set(mBounds);
mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);
mShaderMatrix.set(null);
dx = 0;
dy = 0;
if (mBitmapWidth * mBorderRect.height() > mBorderRect.width() * mBitmapHeight) {
scale = mBorderRect.height() / (float) mBitmapHeight;
dx = (mBorderRect.width() - mBitmapWidth * scale) * 0.5f;
} else {
scale = mBorderRect.width() / (float) mBitmapWidth;
dy = (mBorderRect.height() - mBitmapHeight * scale) * 0.5f;
}
mShaderMatrix.setScale(scale, scale);
mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth,
(int) (dy + 0.5f) + mBorderWidth);
break;
case CENTER_INSIDE:
mShaderMatrix.set(null);
if (mBitmapWidth <= mBounds.width() && mBitmapHeight <= mBounds.height()) {
scale = 1.0f;
} else {
scale = Math.min(mBounds.width() / (float) mBitmapWidth,
mBounds.height() / (float) mBitmapHeight);
}
dx = (int) ((mBounds.width() - mBitmapWidth * scale) * 0.5f + 0.5f);
dy = (int) ((mBounds.height() - mBitmapHeight * scale) * 0.5f + 0.5f);
mShaderMatrix.setScale(scale, scale);
mShaderMatrix.postTranslate(dx, dy);
mBorderRect.set(mBitmapRect);
mShaderMatrix.mapRect(mBorderRect);
mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);
mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect, Matrix.ScaleToFit.FILL);
break;
default:
case FIT_CENTER:
mBorderRect.set(mBitmapRect);
mShaderMatrix.setRectToRect(mBitmapRect, mBounds, Matrix.ScaleToFit.CENTER);
mShaderMatrix.mapRect(mBorderRect);
mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);
mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect, Matrix.ScaleToFit.FILL);
break;
case FIT_END:
mBorderRect.set(mBitmapRect);
mShaderMatrix.setRectToRect(mBitmapRect, mBounds, Matrix.ScaleToFit.END);
mShaderMatrix.mapRect(mBorderRect);
mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);
mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect, Matrix.ScaleToFit.FILL);
break;
case FIT_START:
mBorderRect.set(mBitmapRect);
mShaderMatrix.setRectToRect(mBitmapRect, mBounds, Matrix.ScaleToFit.START);
mShaderMatrix.mapRect(mBorderRect);
mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);
mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect, Matrix.ScaleToFit.FILL);
break;
case FIT_XY:
mBorderRect.set(mBounds);
mBorderRect.inset((mBorderWidth) / 2, (mBorderWidth) / 2);
mShaderMatrix.set(null);
mShaderMatrix.setRectToRect(mBitmapRect, mBorderRect, Matrix.ScaleToFit.FILL);
break;
}
mDrawableRect.set(mBorderRect);
mBitmapShader.setLocalMatrix(mShaderMatrix);
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mBounds.set(bounds);
updateShaderMatrix();
}
#Override
public void draw(Canvas canvas) {
if (mOval) {
if (mBorderWidth > 0) {
canvas.drawOval(mDrawableRect, mBitmapPaint);
canvas.drawOval(mBorderRect, mBorderPaint);
} else {
canvas.drawOval(mDrawableRect, mBitmapPaint);
}
} else {
if (mBorderWidth > 0) {
canvas.drawRoundRect(mDrawableRect, Math.max(mCornerRadius, 0),
Math.max(mCornerRadius, 0), mBitmapPaint);
canvas.drawRoundRect(mBorderRect, mCornerRadius, mCornerRadius, mBorderPaint);
} else {
canvas.drawRoundRect(mDrawableRect, mCornerRadius, mCornerRadius, mBitmapPaint);
}
}
}
#Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
#Override
public void setAlpha(int alpha) {
mBitmapPaint.setAlpha(alpha);
invalidateSelf();
}
#Override
public void setColorFilter(ColorFilter cf) {
mBitmapPaint.setColorFilter(cf);
invalidateSelf();
}
#Override public void setDither(boolean dither) {
mBitmapPaint.setDither(dither);
invalidateSelf();
}
#Override public void setFilterBitmap(boolean filter) {
mBitmapPaint.setFilterBitmap(filter);
invalidateSelf();
}
#Override
public int getIntrinsicWidth() {
return mBitmapWidth;
}
#Override
public int getIntrinsicHeight() {
return mBitmapHeight;
}
public float getCornerRadius() {
return mCornerRadius;
}
public RoundedDrawable setCornerRadius(float radius) {
mCornerRadius = radius;
return this;
}
public float getBorderWidth() {
return mBorderWidth;
}
public RoundedDrawable setBorderWidth(float width) {
mBorderWidth = width;
mBorderPaint.setStrokeWidth(mBorderWidth);
return this;
}
public int getBorderColor() {
return mBorderColor.getDefaultColor();
}
public RoundedDrawable setBorderColor(int color) {
return setBorderColor(ColorStateList.valueOf(color));
}
public ColorStateList getBorderColors() {
return mBorderColor;
}
public RoundedDrawable setBorderColor(ColorStateList colors) {
mBorderColor = colors != null ? colors : ColorStateList.valueOf(0);
mBorderPaint.setColor(mBorderColor.getColorForState(getState(), DEFAULT_BORDER_COLOR));
return this;
}
public boolean isOval() {
return mOval;
}
public RoundedDrawable setOval(boolean oval) {
mOval = oval;
return this;
}
public ScaleType getScaleType() {
return mScaleType;
}
public RoundedDrawable setScaleType(ScaleType scaleType) {
if (scaleType == null) {
scaleType = ScaleType.FIT_CENTER;
}
if (mScaleType != scaleType) {
mScaleType = scaleType;
updateShaderMatrix();
}
return this;
}
public Bitmap toBitmap() {
return drawableToBitmap(this);
}
}
I would approach it in a bit different way...
I will explain how I would do it if I was going to use the class that you've already created (RoundedImageView), but I advise you to remodel it a bit so it's more efficient.
I haven't gone through your whole code, so I'll just assume few things which you can correct if you believe that my help was not enough.
I assume that your class makes the source image a bit smaller so the border is really AROUND the source, and not ON-TOP of the border of source. So for example if the layout width is 50dp and the width of border is 5dp, then the radius of source image is 20dp (and not 25dp with 5dp being covered by the border).
The first thing you should do is make your class display transparent color instead of flat color (as a border).
The second thing is placing under the RoundedImageView an indeterminate progress bar which has the same size (width and height) as your rounded image.
Create a drawable of your progress bar that can look more-less like this:
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="360" >
<shape
android:shape="oval"
android:useLevel="false" >
<gradient
android:centerColor="#000000"
android:endColor="#e5e5e5"
android:startColor="#000000"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
In the progress' bar xml set:
android:indeterminateDrawable="#drawable/your_drawable"
android:indeterminateOnly="true"
EDIT:
If the things you want to overlay on top of each other are the same size and you don't want to use any sort of placing in a different place of another view, you should use FrameLayout. If this placing is needed you can easily use RelativeLayout.
with FrameLayout this overlay effect you can achieve like this:
<FrameLayout
android:layout_width="150dip"
android:layout_height="150dip"
android:padding="10dip" >
<ProgressBar
android:layout_width="match_parent"
android:layout_height="match_parent"
android:indeterminateDrawable="#drawable/your_drawable"
android:indeterminateOnly="true" />
<lc.controls.RoundedImageView
android:id="#+id/progressimage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/ocean"
app:border_color="#android:color/transparent"
app:border_width="4dip"
app:oval="false" />
</FrameLayout>
you might need to work on the padding... test it out.
EDIT 2:
About the remodelling of your class.
I see two really easy approaches. In both of them you use the padding value to set the border width.
Use a normal ImageView with round source image.
Use a custom ImageView that draws the round part of your image in the rectangle that considers the padding value.