In Android, an ImageView is a rectangle by default. How can I make it a rounded rectangle (clip off all 4 corners of my Bitmap to be rounded rectangles) in the ImageView?
Why not do clipping in draw()
?
Here is my solution:
Code:
public class RoundRelativeLayout extends RelativeLayout {
private final float radius;
public RoundRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray attrArray = context.obtainStyledAttributes(attrs,
R.styleable.RoundRelativeLayout);
radius = attrArray.getDimension(
R.styleable.RoundRelativeLayout_radius, 0);
}
private boolean isPathValid;
private final Path path = new Path();
private Path getRoundRectPath() {
if (isPathValid) {
return path;
}
path.reset();
int width = getWidth();
int height = getHeight();
RectF bounds = new RectF(0, 0, width, height);
path.addRoundRect(bounds, radius, radius, Direction.CCW);
isPathValid = true;
return path;
}
@Override
protected void dispatchDraw(Canvas canvas) {
canvas.clipPath(getRoundRectPath());
super.dispatchDraw(canvas);
}
@Override
public void draw(Canvas canvas) {
canvas.clipPath(getRoundRectPath());
super.draw(canvas);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int oldWidth = getMeasuredWidth();
int oldHeight = getMeasuredHeight();
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int newWidth = getMeasuredWidth();
int newHeight = getMeasuredHeight();
if (newWidth != oldWidth || newHeight != oldHeight) {
isPathValid = false;
}
}
}
Kotlin
import android.graphics.BitmapFactory
import android.os.Bundle
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory
import kotlinx.android.synthetic.main.activity_main.*
val bitmap = BitmapFactory.decodeResource(resources, R.drawable.myImage)
val rounded = RoundedBitmapDrawableFactory.create(resources, bitmap)
rounded.cornerRadius = 20f
profileImageView.setImageDrawable(rounded)
To make ImageView
Circular we can change cornerRadius
with:
rounded.isCircular = true
Answer for the question that is redirected here: "How to create a circular ImageView in Android?"
public static Bitmap getRoundBitmap(Bitmap bitmap) {
int min = Math.min(bitmap.getWidth(), bitmap.getHeight());
Bitmap bitmapRounded = Bitmap.createBitmap(min, min, bitmap.getConfig());
Canvas canvas = new Canvas(bitmapRounded);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
canvas.drawRoundRect((new RectF(0.0f, 0.0f, min, min)), min/2, min/2, paint);
return bitmapRounded;
}
Apply a shape to your imageView
as below:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#faf5e6" />
<stroke
android:width="1dp"
android:color="#808080" />
<corners android:radius="15dp" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
</shape>
it may be helpful to you friend.
The following creates a rounded rectangle layout object that draws a rounded rectangle around any child objects that are placed in it. It also demonstrates how to create views and layouts programmatically without using the layout xml files.
package android.example;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MessageScreen extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int mainBackgroundColor = Color.parseColor("#2E8B57");
int labelTextColor = Color.parseColor("#FF4500");
int messageBackgroundColor = Color.parseColor("#3300FF");
int messageTextColor = Color.parseColor("#FFFF00");
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
float density = metrics.density;
int minMarginSize = Math.round(density * 8);
int paddingSize = minMarginSize * 2;
int maxMarginSize = minMarginSize * 4;
TextView label = new TextView(this);
/*
* The LayoutParams are instructions to the Layout that will contain the
* View for laying out the View, so you need to use the LayoutParams of
* the Layout that will contain the View.
*/
LinearLayout.LayoutParams labelLayoutParams = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
label.setLayoutParams(labelLayoutParams);
label.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
label.setPadding(paddingSize, paddingSize, paddingSize, paddingSize);
label.setText(R.string.title);
label.setTextColor(labelTextColor);
TextView message = new TextView(this);
RoundedRectangle.LayoutParams messageLayoutParams = new RoundedRectangle.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
/*
* This is one of the calls must made to force a ViewGroup to call its
* draw method instead of just calling the draw method of its children.
* This tells the RoundedRectangle to put some extra space around the
* View.
*/
messageLayoutParams.setMargins(minMarginSize, paddingSize,
minMarginSize, maxMarginSize);
message.setLayoutParams(messageLayoutParams);
message.setTextSize(TypedValue.COMPLEX_UNIT_SP, paddingSize);
message.setText(R.string.message);
message.setTextColor(messageTextColor);
message.setBackgroundColor(messageBackgroundColor);
RoundedRectangle messageContainer = new RoundedRectangle(this);
LinearLayout.LayoutParams messageContainerLayoutParams = new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
messageContainerLayoutParams.setMargins(paddingSize, 0, paddingSize, 0);
messageContainer.setLayoutParams(messageContainerLayoutParams);
messageContainer.setOrientation(LinearLayout.VERTICAL);
/*
* This is one of the calls must made to force a ViewGroup to call its
* draw method instead of just calling the draw method of its children.
* This tells the RoundedRectangle to color the the exta space that was
* put around the View as well as the View. This is exterior color of
* the RoundedRectangle.
*/
messageContainer.setBackgroundColor(mainBackgroundColor);
/*
* This is one of the calls must made to force a ViewGroup to call its
* draw method instead of just calling the draw method of its children.
* This is the interior color of the RoundedRectangle. It must be
* different than the exterior color of the RoundedRectangle or the
* RoundedRectangle will not call its draw method.
*/
messageContainer.setInteriorColor(messageBackgroundColor);
// Add the message to the RoundedRectangle.
messageContainer.addView(message);
//
LinearLayout main = new LinearLayout(this);
LinearLayout.LayoutParams mainLayoutParams = new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
main.setLayoutParams(mainLayoutParams);
main.setOrientation(LinearLayout.VERTICAL);
main.setBackgroundColor(mainBackgroundColor);
main.addView(label);
main.addView(messageContainer);
setContentView(main);
}
}
The class for RoundedRectangle layout object is as defined here:
/**
* A LinearLayout that draws a rounded rectangle around the child View that was added to it.
*/
package android.example;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.widget.LinearLayout;
/**
* A LinearLayout that has rounded corners instead of square corners.
*
* @author Danny Remington
*
* @see LinearLayout
*
*/
public class RoundedRectangle extends LinearLayout {
private int mInteriorColor;
public RoundedRectangle(Context p_context) {
super(p_context);
}
public RoundedRectangle(Context p_context, AttributeSet attributeSet) {
super(p_context, attributeSet);
}
// Listener for the onDraw event that occurs when the Layout is drawn.
protected void onDraw(Canvas canvas) {
Rect rect = new Rect(0, 0, getWidth(), getHeight());
RectF rectF = new RectF(rect);
DisplayMetrics metrics = new DisplayMetrics();
Activity activity = (Activity) getContext();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
float density = metrics.density;
int arcSize = Math.round(density * 10);
Paint paint = new Paint();
paint.setColor(mInteriorColor);
canvas.drawRoundRect(rectF, arcSize, arcSize, paint);
}
/**
* Set the background color to use inside the RoundedRectangle.
*
* @param Primitive int - The color inside the rounded rectangle.
*/
public void setInteriorColor(int interiorColor) {
mInteriorColor = interiorColor;
}
/**
* Get the background color used inside the RoundedRectangle.
*
* @return Primitive int - The color inside the rounded rectangle.
*/
public int getInteriorColor() {
return mInteriorColor;
}
}
Thanks a lot to first answer. Here is modified version to convert a rectangular image into a square one (and rounded) and fill color is being passed as parameter.
public static Bitmap getRoundedBitmap(Bitmap bitmap, int pixels, int color) {
Bitmap inpBitmap = bitmap;
int width = 0;
int height = 0;
width = inpBitmap.getWidth();
height = inpBitmap.getHeight();
if (width <= height) {
height = width;
} else {
width = height;
}
Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, width, height);
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(inpBitmap, rect, rect, paint);
return output;
}