ImageView in circular through XML - android
I'd Like to make any image from my ImageView to be circular with a border.
I searched but couldn't find any useful information (anything that I tried didn't work).
How can I achieve this through XML:
Create an ImageView with certain src and make it circular with a border?
This is the simplest way that I designed. Try this.
dependencies
implementation 'androidx.appcompat:appcompat:1.3.0-beta01'
implementation 'androidx.cardview:cardview:1.0.0'
<android.support.v7.widget.CardView
android:layout_width="80dp"
android:layout_height="80dp"
android:elevation="12dp"
android:id="#+id/view2"
app:cardCornerRadius="40dp"
android:layout_centerHorizontal="true"
android:innerRadius="0dp"
android:shape="ring"
android:thicknessRatio="1.9">
<ImageView
android:layout_height="80dp"
android:layout_width="match_parent"
android:id="#+id/imageView1"
android:src="#drawable/YOUR_IMAGE"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true">
</ImageView>
</android.support.v7.widget.CardView>
If you are working on android versions above lollipop
<android.support.v7.widget.CardView
android:layout_width="80dp"
android:layout_height="80dp"
android:elevation="12dp"
android:id="#+id/view2"
app:cardCornerRadius="40dp"
android:layout_centerHorizontal="true">
<ImageView
android:layout_height="80dp"
android:layout_width="match_parent"
android:id="#+id/imageView1"
android:src="#drawable/YOUR_IMAGE"
android:scaleType="centerCrop"/>
</android.support.v7.widget.CardView>
Adding Border to round ImageView - LATEST VERSION
Wrap it with another CardView slightly bigger than the inner one and set its background color to add a border to your round image. You can increase the size of the outer CardView to increase the thickness of the border.
<androidx.cardview.widget.CardView
android:layout_width="155dp"
android:layout_height="155dp"
app:cardCornerRadius="250dp"
app:cardBackgroundColor="#color/white">
<androidx.cardview.widget.CardView
android:layout_width="150dp"
android:layout_height="150dp"
app:cardCornerRadius="250dp"
android:layout_gravity="center">
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:src="#drawable/default_user"
android:scaleType="centerCrop"/>
</androidx.cardview.widget.CardView>
</androidx.cardview.widget.CardView>
You can make a simple circle with white border and transparent content with shape.
// res/drawable/circle.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dp"
android:shape="ring"
android:thicknessRatio="1.9"
android:useLevel="false" >
<solid android:color="#android:color/transparent" />
<stroke
android:width="10dp"
android:color="#android:color/white" />
</shape>
Then make a layerlist drawable and put it as background to your imageview.
// res/drawable/img.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/circle"/>
<item android:drawable="#drawable/ic_launcher"/>
</layer-list>
and put it as background to your imageview.
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/img"/>
You'll have something like that.
With the Material Components Library Just use the ShapeableImageView.
Somethig like:
<com.google.android.material.imageview.ShapeableImageView
app:shapeAppearanceOverlay="#style/roundedImageViewRounded"
app:strokeColor="#color/....."
app:strokeWidth="1dp"
...
/>
with:
<style name="roundedImageViewRounded">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">50%</item>
</style>
Note: it requires at least the version 1.2.0.
With jetpack compose you can apply the clip Modifier using a CircleShape:
Image(
painter = painterResource(R.drawable.xxxx),
contentDescription = "xxxx",
contentScale = ContentScale.Crop,
modifier = Modifier
.size(100.dp)
.clip(CircleShape)
.border(2.dp, Color.Blue, CircleShape)
)
I hope this will help you.
1) ShapeableImageView
<com.google.android.material.imageview.ShapeableImageView
android:layout_width="250dp"
android:layout_height="250dp"
android:padding="5dp"
app:strokeWidth="10dp"
app:strokeColor="#android:color/darker_gray"
app:shapeAppearanceOverlay="#style/circleImageView"
android:src="#drawable/profile"
android:layout_margin="10dp"/>
Style add here: res/values/styles.xml
<style name="circleImageView" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">50%</item>
</style>
For complete description please check here : The Source here.
2) CircleImageView
<de.hdodenhof.circleimageview.CircleImageView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/profile_image"
android:layout_width="96dp"
android:layout_height="96dp"
android:src="#drawable/profile"
app:civ_border_width="2dp"
app:civ_border_color="#FF000000"/>
Don't forget implementation: Gradle Scripts > build.gradle (Module: app) > dependencies
implementation 'de.hdodenhof:circleimageview:3.1.0'
For complete description please check here : The Source here.
3) CircularImageView
<com.mikhaellopez.circularimageview.CircularImageView
android:layout_width="250dp"
android:layout_height="250dp"
android:src="#drawable/image"
app:civ_border_color="#3f51b5"
app:civ_border_width="4dp"
app:civ_shadow="true"
app:civ_shadow_radius="10"
app:civ_shadow_color="#3f51b5"/>
Don't forget implementation: Gradle Scripts > build.gradle (Module: app) > dependencies
implementation 'com.mikhaellopez:circularimageview:4.3.1'
For complete description please check here : The Source here.
With the help of glide library and RoundedBitmapDrawableFactory class it's easy to achieve. You may need to create circular placeholder image.
Glide V4:
Glide.with(context).load(url).apply(RequestOptions.circleCropTransform()).into(imageView);
Glide V3:
Glide.with(context)
.load(imgUrl)
.asBitmap()
.placeholder(R.drawable.placeholder)
.error(R.drawable.placeholder)
.into(new BitmapImageViewTarget(imgProfilePicture) {
#Override
protected void setResource(Bitmap resource) {
RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(context.getResources(),
Bitmap.createScaledBitmap(resource, 50, 50, false));
drawable.setCircular(true);
imgProfilePicture.setImageDrawable(drawable);
}
});
For Picasso RoundedTransformation, this is a really great solution that gives an additional option of rounding image at either top or bottom edge.
The above methods don't seem to work if you're using the src attribute. What I did is to put two image views inside a frame layout one above another like this:
<FrameLayout android:id="#+id/frame"
android:layout_width="40dp"
android:layout_height="40dp">
<ImageView android:id="#+id/pic"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="#drawable/my_picture" />
<ImageView android:id="#+id/circle_crop"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="#drawable/circle_crop" />
</FrameLayout>
Simply put a circular_crop.png in your drawable folder which is in the shape of your image dimensions (a square in my case) with a white background and a transparent circle in the center. You can use this image if you have want a square imageview.
Just download the picture above.
The following is one of the simplest ways to do it, use the following code:
Dependencies
dependencies {
...
compile 'de.hdodenhof:circleimageview:2.1.0' // use this or use the latest compile version. In case u get bug.
}
XML Code
<de.hdodenhof.circleimageview.CircleImageView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/profile_image"
android:layout_width="96dp" // here u can adjust the width
android:layout_height="96dp" // here u can adjust the height
android:src="#drawable/profile" // here u can change the image
app:civ_border_width="2dp" // here u can adjust the border of the circle.
app:civ_border_color="#FF000000"/> // here u can adjust the border color
Screenshot:
Source: Circular ImageView GitHub Repository
you don't need any third-party library.
you can use the ShapeableImageView in the material.
implementation 'com.google.android.material:material:1.2.0'
style.xml
<style name="ShapeAppearanceOverlay.App.CornerSize">
<item name="cornerSize">50%</item>
</style>
in layout
<com.google.android.material.imageview.ShapeableImageView
android:layout_width="100dp"
android:layout_height="100dp"
app:srcCompat="#drawable/ic_profile"
app:shapeAppearanceOverlay="#style/ShapeAppearanceOverlay.App.CornerSize"
/>
you can see this
https://developer.android.com/reference/com/google/android/material/imageview/ShapeableImageView
or this
https://medium.com/android-beginners/shapeableimageview-material-components-for-android-cac6edac2c0d
You can simply use AndroidX ImageFilterView.
<androidx.constraintlayout.utils.widget.ImageFilterView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="#dimen/margin_medium"
android:layout_marginBottom="#dimen/margin_medium"
android:background="#color/white"
android:padding="#dimen/margin_small"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:roundPercent="1"
app:srcCompat="#drawable/ic_gallery" />
You can simply use CardView without any external Library
<androidx.cardview.widget.CardView
android:id="#+id/roundCardView"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_centerHorizontal="true"
android:elevation="0dp"
app:cardCornerRadius="20dp">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="#drawable/profile" />
</androidx.cardview.widget.CardView>
This will do the trick:
rectangle.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#android:color/transparent" />
<padding android:bottom="-14dp" android:left="-14dp" android:right="-14dp" android:top="-14dp" />
</shape>
circle.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dp"
android:shape="oval"
android:useLevel="false" >
<solid android:color="#android:color/transparent" />
<stroke
android:width="15dp"
android:color="#color/verification_contact_background" />
</shape>
profile_image.xml ( The layerlist )
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/rectangle" />
<item android:drawable="#drawable/circle"/>
</layer-list>
Your layout
<ImageView
android:id="#+id/profile_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/default_org"
android:src="#drawable/profile_image"/>
Posting this answer for future reference. You can use ShapeableImageView available in com.google.android.material:material.
<com.google.android.material.imageview.ShapeableImageView
android:id="#+id/img_launcher_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_margin="5dp"
android:adjustViewBounds="true"
android:background="#android:color/transparent"
android:elevation="5dp"
android:maxWidth="50dp"
android:maxHeight="50dp"
android:scaleType="fitXY"
android:src="#mipmap/ic_launcher"
app:shapeAppearance="?attr/actionButtonStyle"
app:shapeAppearanceOverlay="#style/imageViewRounded"
app:strokeColor="#android:color/white" />
Add imageViewRounded style in your styles.xml
<style name="imageViewRounded">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">51%</item>
</style>
You can add material design dependency if not added.
implementation 'com.google.android.material:material:1.4.0'
Design looks like
Best Solution courtesy https://www.youtube.com/watch?v=0MHoNU7ytaw
the width and height of the card view determine the size of the images it contains set up is as follows:
Add Dependency to Gradle(Module)
Add the xml code to activity.xml or fragment.xml file
implementation 'androidx.cardview:cardview:1.0.0'
<androidx.cardview.widget.CardView
android:layout_width="300dp"
android:layout_height="270dp"
android:layout_gravity="center"
app:cardCornerRadius="150dp"
app:cardBackgroundColor="#color/trans"
>
<ImageView
android:id="#+id/resultImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/congrats"
android:layout_gravity="center">
</ImageView>
</androidx.cardview.widget.CardView>```
Update 2021: Using Glide v4 CircleCrop see https://bumptech.github.io/glide/doc/generatedapi.html
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
XML
<ImageView
android:id="#+id/vinyl"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
In Code
Glide.with(this)
.load("https://images.pexels.com/photos/3828241/pexels-photo-3828241.jpeg")
.transform(CircleCrop())
.into(rootView.findViewById<ImageView>(R.id.vinyl))
I use shape = "oval" instead of the "ring" below. It has worked for me. To keep the image within bounds, I use <padding> and set <adjustViewBounds> to true in my <ImageView>. I have tried with images of size between 50 x 50 px upto 200x200 px .
#Jyotman Singh, answer is very good (for solid backgrounds), so I would like to enhance it by sharing vector drawable that can be re-colored for your needs, also it is convenient since vector one-piece shape is well scalable.
This is the rectangle-circle shape (#drawable/shape_round_profile_pic):
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportWidth="284"
android:viewportHeight="284"
android:width="284dp"
android:height="284dp">
<path
android:pathData="M0 142L0 0l142 0 142 0 0 142 0 142 -142 0 -142 0zm165 137.34231c26.06742 -4.1212 52.67405 -17.543 72.66855 -36.65787 11.82805 -11.30768 20.55487 -22.85153 27.7633 -36.72531C290.23789 158.21592 285.62874 101.14121 253.48951 58.078079 217.58149 9.9651706 154.68849 -10.125717 98.348685 8.5190299 48.695824 24.95084 12.527764 67.047123 3.437787 118.98655 1.4806194 130.16966 1.511302 152.96723 3.4990422 164.5 12.168375 214.79902 47.646316 256.70775 96 273.76783c21.72002 7.66322 44.26673 9.48476 69 5.57448z"
android:fillColor="#ffffff" /> // you can change frame color
</vector>
Usage is the same:
<FrameLayout
android:layout_width="70dp"
android:layout_height="70dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/YOUR_PICTURE" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/shape_round_profile_pic"/>
</FrameLayout>
Just use these lines of code and you are done :
<de.hdodenhof.circleimageview.CircleImageView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:clickable="true"
app:civ_border_width="3dp"
app:civ_border_color="#FFFFFFFF"
android:id="#+id/profile"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_below="#+id/header_cover_image"
android:layout_centerHorizontal="true"
android:layout_marginTop="-130dp"
android:elevation="5dp"
android:padding="20dp"
android:scaleType="centerCrop"
android:src="#drawable/profilemain" />
Don't forget to import :
import de.hdodenhof.circleimageview.CircleImageView;
Add this library in build.gradle :
compile 'de.hdodenhof:circleimageview:2.1.0'
If you use Material Design in your app then use this
<com.google.android.material.card.MaterialCardView
android:layout_width="75dp"
android:layout_height="75dp"
app:cardCornerRadius="50dp"
app:strokeWidth="1dp"
app:strokeColor="#color/black">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/circular_image"
android:scaleType="fitCenter"
android:src="#drawable/your_img" />
</com.google.android.material.card.MaterialCardView>
I did it like that, I used my background color in my vector image
ic_bg_picture.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="100dp"
android:height="100dp"
android:viewportWidth="100"
android:viewportHeight="100">
<path
android:pathData="M100.6,95.5c0,-0.4 -0.1,-0.7 0,-1.1c-0.2,-0.7 -0.2,-1.4 -0.1,-2.1c0,-0.1 0,-0.2 0,-0.3c-0.1,-0.6 -0.1,-1.2 0,-1.8c-1,-1.3 -0.3,-2.9 -0.3,-4.3c-0.1,-28.7 -0.1,-57.3 -0.1,-86C68,-0.1 35.9,-0.1 3.8,-0.2C0.7,-0.2 0,0.5 0,3.6c0.1,32.1 0.1,64.2 0.1,96.2c31,0 62,-0.1 92.9,0.1c3.6,0 6.3,-0.2 7.5,-3.2C100.5,96.4 100.5,95.9 100.6,95.5zM46.3,95.2C26.4,94 2,74.4 3.8,46.8C5.1,27.2 24.4,2.7 52.6,4.6c20.2,1.4 43,21.3 41.5,45.1C96.1,72.4 73,96.8 46.3,95.2z"
android:fillColor="#6200EE"/>
</vector>
in my case I created a vector and changed the android:fillColor="#6200EE"
by the color of my background
<ImageView
android:id="#+id/iv_profile_image"
android:layout_width="100dp"
android:layout_height="100dp"
android:contentDescription="#string/app_name"
app:srcCompat="#color/colorPrimaryDark" />
<ImageView
android:id="#+id/container_profile_image"
android:layout_width="100dp"
android:layout_height="100dp"
android:contentDescription="#string/app_name"
app:srcCompat="#drawable/ic_bg_picture"/>
Another method without using any library is using ImageFilterView and setting round percentage to the view will make the circle round
app:roundPercent="1"
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="#+id/ivProfile"
android:layout_width="150dp"
android:layout_height="150dp"
android:src="#drawable/custom_button_1"
app:roundPercent="1"
android:scaleType="fitXY"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="#+id/etName"/>
Try this.
public class RoundedImageView extends android.support.v7.widget.AppCompatImageView {
private int borderWidth = 4;
private int viewWidth;
private int viewHeight;
private Bitmap image;
private Paint paint;
private Paint paintBorder;
private BitmapShader shader;
public RoundedImageView(Context context)
{
super(context);
setup();
}
public RoundedImageView(Context context, AttributeSet attrs)
{
super(context, attrs);
setup();
}
public RoundedImageView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
setup();
}
private void setup()
{
paint = new Paint();
paint.setAntiAlias(true);
paintBorder = new Paint();
setBorderColor(Color.WHITE);
paintBorder.setAntiAlias(true);
this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.WHITE);
}
public void setBorderWidth(int borderWidth)
{
this.borderWidth = borderWidth;
this.invalidate();
}
public void setBorderColor(int borderColor)
{
if (paintBorder != null)
paintBorder.setColor(borderColor);
this.invalidate();
}
private void loadBitmap()
{
BitmapDrawable bitmapDrawable = (BitmapDrawable) this.getDrawable();
if (bitmapDrawable != null)
image = bitmapDrawable.getBitmap();
}
#SuppressLint("DrawAllocation")
#Override
public void onDraw(Canvas canvas)
{
loadBitmap();
if (image != null)
{
shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvas.getWidth(), canvas.getHeight(), false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(shader);
int circleCenter = viewWidth / 2;
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter + borderWidth - 4.0f, paintBorder);
canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter - 4.0f, paint);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec, widthMeasureSpec);
viewWidth = width - (borderWidth * 2);
viewHeight = height - (borderWidth * 2);
setMeasuredDimension(width, height);
}
private int measureWidth(int measureSpec)
{
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY)
{
result = specSize;
}
else
{
// Measure the text
result = viewWidth;
}
return result;
}
private int measureHeight(int measureSpecHeight, int measureSpecWidth)
{
int result = 0;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY)
{
result = specSize;
}
else
{
result = viewHeight;
}
return (result + 2);
}
}
and use this ImageView in layout like:
<com.app.Demo.RoundedImageView
android:id="#+id/iv_profileImage"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_centerHorizontal="true"
/>
This Class is Custom Circular Imageview with shadow, Stroke,saturation and using this Custom Circular ImageView you can make your image in Circular Shape with Radius. Guys for Circular Shadow ImageView No need Github this class is enough.
Adding CircularImageView to your layout
CircularImageView c=new CircularImageView(this,screen width,screen height,Bitmap myimage);
yourLayout.addView(c);**
public class CircularImageView extends android.support.v7.widget.AppCompatImageView
{
private final Context context;
private final int width, height;
private final Paint paint;
private final Paint paintBorder,imagePaint;
private final Bitmap bitmap2;
private final Paint paint3;
private Bitmap bitmap;
private BitmapShader shader;
private float radius = 4.0f;
float x = 0.0f;
float y = 8.0f;
private float stroke;
private float strokeWidth = 0.0f;
private Bitmap bitmap3;
private int corner_radius=50;
public CircularImageView(Context context, int width, int height, Bitmap bitmap) {
super(context);
this.context = context;
this.width = width;
this.height = height;
//here "bitmap" is the square shape(width* width) scaled bitmap ..
this.bitmap = bitmap;
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
paint3=new Paint();
paint3.setStyle(Paint.Style.STROKE);
paint3.setColor(Color.WHITE);
paint3.setAntiAlias(true);
paintBorder = new Paint();
imagePaint= new Paint();
paintBorder.setColor(Color.WHITE);
paintBorder.setAntiAlias(true);
this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
this.bitmap2 = Bitmap.createScaledBitmap(bitmap, (bitmap.getWidth() - 40), (bitmap.getHeight() - 40), true);
imagePaint.setAntiAlias(true);
invalidate();
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Shader b;
if (bitmap3 != null)
b = new BitmapShader(bitmap3, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
else
b = new BitmapShader(bitmap2, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
imagePaint.setShader(b);
canvas.drawBitmap(maskedBitmap(), 20, 20, null);
}
private Bitmap maskedBitmap()
{
Bitmap l1 = Bitmap.createBitmap(width,width, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(l1);
paintBorder.setShadowLayer(radius, x, y, Color.parseColor("#454645"));
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
final RectF rect = new RectF();
rect.set(20, 20, bitmap2.getWidth(), bitmap2.getHeight());
canvas.drawRoundRect(rect, corner_radius, corner_radius, paintBorder);
canvas.drawRoundRect(rect, corner_radius, corner_radius, imagePaint);
if (strokeWidth!=0.0f)
{
paint3.setStrokeWidth(strokeWidth);
canvas.drawRoundRect(rect, corner_radius, corner_radius, paint3);
}
paint.setXfermode(null);
return l1;
}
// use seekbar here, here you have to pass "0 -- 250" here corner radius will change
public void setCornerRadius(int corner_radius)
{
this.corner_radius = corner_radius;
invalidate();
}
-------->use seekbar here, here you have to pass "0 -- 10.0f" here shadow radius will change
public void setShadow(float radius)
{
this.radius = radius;
invalidate();
}
// use seekbar here, here you have to pass "0 -- 10.0f" here stroke size will change
public void setStroke(float stroke)
{
this.strokeWidth = stroke;
invalidate();
}
private Bitmap updateSat(Bitmap src, float settingSat)
{
int w = src.getWidth();
int h = src.getHeight();
Bitmap bitmapResult =
Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvasResult = new Canvas(bitmapResult);
Paint paint = new Paint();
ColorMatrix colorMatrix = new ColorMatrix();
colorMatrix.setSaturation(settingSat);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix);
paint.setColorFilter(filter);
canvasResult.drawBitmap(src, 0, 0, paint);
return bitmapResult;
}
// use seekbar here, here you have to pass "0 -- 2.0f" here saturation will change
public void setSaturation(float sat)
{
System.out.println("qqqqqqqqqq "+sat);
bitmap3=updateSat(bitmap2, sat);
invalidate();
}
}
// Seekbar to change radius
radius_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
text_radius.setText(""+progress);
circularImageView.setCornerRadius(progress);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// Seekbar to change shadow
shadow_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
float f= 4+progress/10.0f;
text_shadow.setText(""+progress);
circularImageView.setShadow(f);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// Seekbar to change saturation
saturation_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
int progressSat = saturation_seekbar.getProgress();
float sat = (float) ((progressSat*4 / 100.0f)-1.0f);
circularImageView.setSaturation(sat);
text_saturation.setText(""+progressSat);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// Seekbar to change stroke
stroke_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
if (progress==0)
{
float f=(progress*10.0f/100.0f);
circularImageView.setStroke(f);
}
else
{
float f=(progress*10.0f/100.0f);
circularImageView.setStroke(f);
}
text_stroke.setText(""+progress);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
//radius seekbar in xml file
<SeekBar
android:layout_width="match_parent"
android:layout_gravity="center"
android:progress="50"
android:max="250"
android:id="#+id/radius_seekbar"
android:layout_height="wrap_content" />
//saturation seekbar in xml file
<SeekBar
android:layout_width="match_parent"
android:layout_gravity="center"
android:progress="50"
android:max="100"
android:id="#+id/saturation_seekbar"
android:layout_height="wrap_content" />
//shadow seekbar in xml file
<SeekBar
android:layout_width="match_parent"
android:layout_gravity="center"
android:progress="0"
android:max="100"
android:id="#+id/shadow_seekbar"
android:layout_height="wrap_content" />
//stroke seekbar in xml file
<SeekBar
android:layout_width="match_parent"
android:layout_gravity="center"
android:progress="0"
android:max="100"
android:id="#+id/stroke _seekbar"
android:layout_height="wrap_content" />
Actually, you can use what Google provides via the support library RoundedBitmapDrawableFactory class (here and here), instead of using a third party library :
Gradle:
implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val originalDrawable = ContextCompat.getDrawable(this, R.drawable.avatar_1)!!
val bitmap = convertDrawableToBitmap(originalDrawable)
val drawable = RoundedBitmapDrawableFactory.create(resources, bitmap)
drawable.setAntiAlias(true)
drawable.cornerRadius = Math.max(bitmap.width, bitmap.height) / 2.0f
avatarImageView.setImageDrawable(drawable)
}
companion object {
#JvmStatic
fun convertDrawableToBitmap(drawable: Drawable): Bitmap {
if (drawable is BitmapDrawable)
return drawable.bitmap
// We ask for the bounds if they have been set as they would be most
// correct, then we check we are > 0
val bounds = drawable.bounds
val width = if (!bounds.isEmpty) bounds.width() else drawable.intrinsicWidth
val height = if (!bounds.isEmpty) bounds.height() else drawable.intrinsicHeight
// Now we check we are > 0
val bitmap = Bitmap.createBitmap(if (width <= 0) 1 else width, if (height <= 0) 1 else height,
Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
drawable.setBounds(0, 0, canvas.width, canvas.height)
drawable.draw(canvas)
return bitmap
}
}
}
res/layout/activity_main.xml
<FrameLayout
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:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".MainActivity">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/avatarImageView" android:layout_width="100dp" android:layout_height="100dp"
android:layout_gravity="center"/>
</FrameLayout>
res/drawable/avatar_1.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="128dp" android:height="128dp"
android:viewportHeight="128.0" android:viewportWidth="128.0">
<path
android:fillColor="#FF8A80" android:pathData="M0 0h128v128h-128z"/>
<path
android:fillColor="#FFE0B2"
android:pathData="M36.3 94.8c6.4 7.3 16.2 12.1 27.3 12.4 10.7,-.3 20.3,-4.7 26.7,-11.6l.2.1c-17,-13.3,-12.9,-23.4,-8.5,-28.6 1.3,-1.2 2.8,-2.5 4.4,-3.9l13.1,-11c1.5,-1.2 2.6,-3 2.9,-5.1.6,-4.4,-2.5,-8.4,-6.9,-9.1,-1.5,-.2,-3 0,-4.3.6,-.3,-1.3,-.4,-2.7,-1.6,-3.5,-1.4,-.9,-2.8,-1.7,-4.2,-2.5,-7.1,-3.9,-14.9,-6.6,-23,-7.9,-5.4,-.9,-11,-1.2,-16.1.7,-3.3 1.2,-6.1 3.2,-8.7 5.6,-1.3 1.2,-2.5 2.4,-3.7 3.7l-1.8 1.9c-.3.3,-.5.6,-.8.8,-.1.1,-.2 0,-.4.2.1.2.1.5.1.6,-1,-.3,-2.1,-.4,-3.2,-.2,-4.4.6,-7.5 4.7,-6.9 9.1.3 2.1 1.3 3.8 2.8 5.1l11 9.3c1.8 1.5 3.3 3.8 4.6 5.7 1.5 2.3 2.8 4.9 3.5 7.6 1.7 6.8,-.8 13.4,-5.4 18.4,-.5.6,-1.1 1,-1.4 1.7,-.2.6,-.4 1.3,-.6 2,-.4 1.5,-.5 3.1,-.3 4.6.4 3.1 1.8 6.1 4.1 8.2 3.3 3 8 4 12.4 4.5 5.2.6 10.5.7 15.7.2 4.5,-.4 9.1,-1.2 13,-3.4 5.6,-3.1 9.6,-8.9 10.5,-15.2m-14.4,-49.8c.9 0 1.6.7 1.6 1.6 0 .9,-.7 1.6,-1.6 1.6,-.9 0,-1.6,-.7,-1.6,-1.6,-.1,-.9.7,-1.6 1.6,-1.6zm-25.7 0c.9 0 1.6.7 1.6 1.6 0 .9,-.7 1.6,-1.6 1.6,-.9 0,-1.6,-.7,-1.6,-1.6,-.1,-.9.7,-1.6 1.6,-1.6z"/>
<path
android:fillColor="#E0F7FA"
android:pathData="M105.3 106.1c-.9,-1.3,-1.3,-1.9,-1.3,-1.9l-.2,-.3c-.6,-.9,-1.2,-1.7,-1.9,-2.4,-3.2,-3.5,-7.3,-5.4,-11.4,-5.7 0 0 .1 0 .1.1l-.2,-.1c-6.4 6.9,-16 11.3,-26.7 11.6,-11.2,-.3,-21.1,-5.1,-27.5,-12.6,-.1.2,-.2.4,-.2.5,-3.1.9,-6 2.7,-8.4 5.4l-.2.2s-.5.6,-1.5 1.7c-.9 1.1,-2.2 2.6,-3.7 4.5,-3.1 3.9,-7.2 9.5,-11.7 16.6,-.9 1.4,-1.7 2.8,-2.6 4.3h109.6c-3.4,-7.1,-6.5,-12.8,-8.9,-16.9,-1.5,-2.2,-2.6,-3.8,-3.3,-5z"/>
<path
android:fillColor="#444" android:pathData="M76.3,47.5 m-2.0, 0 a 2.0,2.0 0 1,1 4.0,0 a2.0,2.0 0 1,1 -4.0,0"/>
<path
android:fillColor="#444" android:pathData="M50.7,47.6 m-2.0, 0 a 2.0,2.0 0 1,1 4.0,0 a2.0,2.0 0 1,1 -4.0,0"/>
<path
android:fillColor="#444"
android:pathData="M48.1 27.4c4.5 5.9 15.5 12.1 42.4 8.4,-2.2,-6.9,-6.8,-12.6,-12.6,-16.4 17.2 1.5 14.1,-9.4 14.1,-9.4,-1.4 5.5,-11.1 4.4,-11.1 4.4h-18.8c-1.7,-.1,-3.4 0,-5.2.3,-12.8 1.8,-22.6 11.1,-25.7 22.9 10.6,-1.9 15.3,-7.6 16.9,-10.2z"/>
</vector>
The result:
And, suppose you want to add a border on top of it, you can use this for example:
stroke_drawable.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<stroke
android:width="4dp" android:color="#android:color/black"/>
</shape>
And add android:foreground="#drawable/stroke_drawable" to the ImageView in the layout XML file, and you get this :
I'm not sure how to add shadow (that will work on older Android versions), though. Using FloatingActionButton (from the "com.google.android.material:material" dependency), I failed to make the bitmap fill the FAB itself. Using it instead could be even better if it worked.
EDIT: if you wish to add shadow of elevation (available from API 21), you can change a bit what I wrote:
Inside the layout XML file:
<androidx.appcompat.widget.AppCompatImageView android:padding="4dp"
android:id="#+id/avatarImageView" android:layout_width="100dp" android:layout_height="100dp" android:elevation="8dp"
android:layout_gravity="center" android:background="#drawable/stroke_drawable" tools:srcCompat="#drawable/avatar_1"/>
CircularShadowViewOutlineProvider.kt
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
class CircularShadowViewOutlineProvider : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
val size = Math.max(view.width, view.height)
outline.setRoundRect(0, 0, size, size, size / 2f)
}
}
In code:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
avatarImageView.outlineProvider = CircularShadowViewOutlineProvider()
Result:
I have a simple solution.
Create a new Image asset by right clicking your package name and selecting New->Image asset.
Enter name (any name) and path (location of image in your system).
Then click Next and Finish.
If you enter name of image as 'img', a round image with the name 'img_round' is created automatically in mipmap folder.
Then, do this :
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#mipmap/img_round"/>
Your preview may still show a rectangular image. But if you run the app on your device, it will be round.
Create a CustomImageview then simply override its onDraw() method follows:
#Override
protected void onDraw(Canvas canvas) {
float radius = this.getHeight()/2;
Path path = new Path();
RectF rect = new RectF(0, 0, this.getWidth(), this.getHeight());
path.addRoundRect(rect, radius, radius, Path.Direction.CW);
canvas.clipPath(path);
super.onDraw(canvas);
}
In case you want the code for the custom widget as well:-
CircularImageView.java
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
import androidx.annotation.Nullable;
public class CircularImageView extends ImageView {
private Drawable image;
public CircularImageView(Context context) {
super(context);
init(null, 0);
}
public CircularImageView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(attrs, 0);
}
public CircularImageView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs, defStyleAttr);
}
#Override
protected void onDraw(Canvas canvas) {
float radius = this.getHeight()/2;
Path path = new Path();
RectF rect = new RectF(0, 0, this.getWidth(), this.getHeight());
path.addRoundRect(rect, radius, radius, Path.Direction.CW);
canvas.clipPath(path);
super.onDraw(canvas);
}
private void init(AttributeSet attrs, int defStyle) {
TypedArray a = Utils.CONTEXT.getTheme().obtainStyledAttributes(attrs, R.styleable.CircularImageView, 0, 0);
try {
image = a.getDrawable(R.styleable.CircularImageView_src);
} finally {
a.recycle();
}
this.setImageDrawable(image);
}
}
Also, add the following code to your res/attrs.xml to create the required attribute:-
<declare-styleable name="CircularImageView">
<attr name="src" format="reference" />
</declare-styleable>
if you want to set edit icon on to circle imageview than put this below code.
<FrameLayout
android:layout_width="#dimen/_100sdp"
android:layout_height="#dimen/_100sdp"
android:layout_gravity="center"
android:layout_marginTop="10dp">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/profilePic"
android:layout_width="#dimen/_100sdp"
android:layout_height="#dimen/_100sdp"
android:layout_gravity="bottom|center_horizontal"
android:src="#drawable/ic_upload" />
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/iv_camera"
android:layout_width="#dimen/_30sdp"
android:layout_height="#dimen/_30sdp"
android:layout_gravity="top|right"
android:src="#drawable/edit"/>
</FrameLayout>
if you'd rather cut the image to display in circular, here you go
public static Bitmap getCircularBitmap(Bitmap bitmap) {
Bitmap output;
if (bitmap.getWidth() > bitmap.getHeight()) {
output = Bitmap.createBitmap(bitmap.getHeight(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
} else {
output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getWidth(), Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
float r = 0;
if (bitmap.getWidth() > bitmap.getHeight()) {
r = bitmap.getHeight() / 2;
} else {
r = bitmap.getWidth() / 2;
}
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawCircle(r, r, r, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
Another idea is to use clipToOutline property of an ImageView.
Here is an example layout:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Simple view to draw borders for an image,
borders will be rounded because of the oval-shaped background. -->
<View
android:id="#+id/v_border"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#drawable/shape_border"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!-- Image itself: fits the border view,
a margin serves as a border width;
the key point here - is a background shape which will clip the view to its forms. -->
<ImageView
android:id="#+id/iv_image"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="4dp"
android:background="#drawable/shape_oval"
android:src="#mipmap/ic_launcher"
app:layout_constraintBottom_toBottomOf="#+id/v_border"
app:layout_constraintEnd_toEndOf="#+id/v_border"
app:layout_constraintStart_toStartOf="#+id/v_border"
app:layout_constraintTop_toTopOf="#+id/v_border" />
</androidx.constraintlayout.widget.ConstraintLayout>
And here are our shape_border drawable:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="#FF00FF" />
</shape>
And shape_oval drawable:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" />
The only thing you should do in the code - is to enable clipToOutline property:
binding.ivImage.clipToOutline = true
And of course you can avoid even this line of the code with some BindingAdapter.
This is a relatively old question, but you can just make a circle border in the drawable folder (let's assume the xml file will be called circle_border)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#android:color/transparent" />
<!-- If you want a padding -->
<padding android:top="4dp" android:left="4dp" android:right="4dp" android:bottom="4dp" />
<!-- If you want the circle border to have a color -->
<strong android:width="1dp" android:color="#FFFFFF" />
</shape>
Then you can use it as the background of the ImageView
<ImageView
android:background="#drawable/circle_border"
<!-- other attributes here -->
/>
just use this simple code:
First add dependency :
implementation 'de.hdodenhof:circleimageview:2.2.0'
then add in xml layout the following code:-
<de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/Imgshaligram"
android:layout_width="96dp"
android:layout_height="96dp"
android:src="#drawable/shaligram"
app:civ_border_color="#d1b1b1"
android:foregroundGravity="center"/>
Related
Anchor an ImageView to corner of another ImageView
How to anchor an ImageView to bottom right corner of another ImageView like the ones in the above picture (1-man and 2-pencil) I am using retrofit to load my sources as oval into ImageViews I do this : Glide.with(context) .asBitmap() .load(model) .fitCenter() .apply(RequestOptions.circleCropTransform()) .into(object : BitmapImageViewTarget(this) { override fun setResource(resource: Bitmap?) { setImageDrawable( resource?.run { RoundedBitmapDrawableFactory.create( resources, if (borderSize > 0) { createBitmapWithBorder(borderSize, borderColor) } else { this } ).apply { isCircular = true } } ) } })
Base concept To build such layout you can use for example ConstraintLayout or RelativeLayout. Using RelativeLayout you can build such structure: <RelativeLayout android:layout_width="200dp" android:layout_height="200dp"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginEnd="20dp" android:layout_marginBottom="20dp" android:background="#00f" /> <ImageView android:layout_width="70dp" android:layout_height="70dp" android:layout_alignParentEnd="true" android:layout_alignParentBottom="true" android:background="#f0f" /> </RelativeLayout> Which should look like there: Small circle For smaller circle (grey one) you can use only one ImageView. Just set light background - as background and pen icon - as src. 1) For ImageView background you have to create new drawable with two shapes. First ont is for white border around, second it's just light gray background. You can set padding second shape (here, in example, there is 5dp) <?xml version="1.0" encoding="utf-8"?><?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape android:shape="oval"> <solid android:color="#FFFFFF" /> </shape> </item> <item android:bottom="5dp" android:left="5dp" android:right="5dp" android:top="5dp"> <shape android:shape="oval"> <solid android:color="#CACACA" /> </shape> </item> </layer-list> 2) As icon you can use drawable (e.g. vector) or just image and set it as src After this point it should look like there: 3) Set padding in ImageView to scale your (pen) icon correctly: <ImageView android:layout_width="70dp" android:layout_height="70dp" android:layout_alignParentEnd="true" android:layout_alignParentBottom="true" android:background="#drawable/small_circle_background" android:padding="16dp" android:src="#drawable/small_circle_icon" /> Big circle Best approach is to use some library like Picasso or Glide. For Glide, you can use CircleTransform() to crop received image in to circle. When loading image you can just use transform() method: Glide.with(this) .load(URL) .transform(new CircleTransform(context)) .into(imageView); When CircleTransform is: import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Paint; import androidx.annotation.NonNull; import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; import org.jetbrains.annotations.NotNull; import java.security.MessageDigest; public class CircleTransform extends BitmapTransformation { #Override protected Bitmap transform(#NotNull BitmapPool pool, #NotNull Bitmap toTransform, int outWidth, int outHeight) { return circleCrop(pool, toTransform); } private static Bitmap circleCrop(BitmapPool pool, Bitmap source) { if (source == null) return null; int size = Math.min(source.getWidth(), source.getHeight()); int x = (source.getWidth() - size) / 2; int y = (source.getHeight() - size) / 2; Bitmap squared = Bitmap.createBitmap(source, x, y, size, size); Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(result); Paint paint = new Paint(); paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); paint.setAntiAlias(true); float r = size / 2f; canvas.drawCircle(r, r, r, paint); return result; } #Override public void updateDiskCacheKey(#NonNull MessageDigest messageDigest) { } } Final result
You can achieve what you want like this: <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:layout_width="100dp" android:layout_height="100dp" android:src="#drawable/first_image"/> <ImageView android:layout_width="40dp" android:layout_height="40dp" android:src="#drawable/second" android:layout_gravity="bottom|right"/> </FrameLayout>
Unable to get exact circle shape when using card view
I'm using card view for floating action button in android material design. I'm using following code for get the circle <android.support.v7.widget.CardView android:id="#+id/fab" android:layout_width="38dp" android:layout_height="38dp" android:layout_marginBottom="10dp" android:layout_marginRight="10dp" card_view:background="#color/blue" card_view:cardCornerRadius="19dp" card_view:cardPreventCornerOverlap = "false" card_view:cardElevation="6dp" > </android.support.v7.widget.CardView> I have set corner radius as half of width. but still I can't get the circle shape.
To achieve a circular shape using Card view you can set the shape property, android:shape="ring". app:cardCornerRadius should be set to half the width or height of the child view <android.support.v7.widget.CardView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:innerRadius="0dp" android:shape="ring" app:cardCornerRadius="75dp"> <ImageView android:layout_width="150dp" android:layout_height="150dp" android:layout_gravity="center" android:background="#drawable/image" /> </android.support.v7.widget.CardView>
I have solved the problem. Now android providing design library for material design, which has the FloatingActionButton. No need of customizing card view for floating action button. <android.support.design.widget.FloatingActionButton android:id="#+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="#dimen/fab_margin" /> Add design library in gradle dependencies compile 'com.android.support:design:23.1.1' For more detail refer this link
To get a perfect circle shape using a card view, corner radius should be 1/2 of width or height (taking into consideration that it is a square). also, I have noticed that you are using card_view params, don't. <android.support.v7.widget.CardView android:layout_width="38dp" android:layout_height="38dp" app:cardCornerRadius="19dp" app:cardElevation="6dp" android:layout_marginBottom="10dp" android:layout_marginRight="10dp" android:id="#+id/fab" android:background="#color/blue" >
use shape = "ring" use same layout_height and layout_weight and app:cardCornerRadius= half of layout_height or layout_weight example <android.support.v7.widget.CardView android:id="#+id/cardview" android:layout_width="110dp" android:layout_height="110dp" android:shape="ring" app:cardCornerRadius="55dp"> </android.support.v7.widget.CardView>
<androidx.cardview.widget.CardView android:layout_width="60dp" android:layout_marginStart="150dp" app:cardCornerRadius="360dp" android:layout_height="60dp">
I came up with simple Solution of Using a Drawable and it looks amazing! Get Drawable here https://drive.google.com/drive/folders/0B4Vo_ku-aIKzUFFnUjYxYVRLaGc?resourcekey=0-RiH8lUO0i1kwnZsqquqjnQ&usp=sharing
I tried your code and found out that the Cards were less round with respect to the increase in the card elevation value.Try setting it to zero and this at least makes it look better. card_view:cardElevation="0dp"; But a probably better option would be to use the FloatingActionButton for the round button <android.support.design.widget.FloatingActionButton android:src="#drawable/your_drawble_name" app:fabSize="normal" android:layout_width="wrap_content" android:layout_height="wrap_content" />
add this line to the CardView which sets the cardCornerRadius to the Circle diameter. app:cardCornerRadius="360dp"
Yes, I have achieved it by reducing half of the CardCornerRadius to its View's Height.
card_layout.xml <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="#+id/card_view" android:layout_gravity="center" android:layout_width="250dp" android:layout_height="200dp"> <ImageView android:id="#+id/card_thumbnail_image" android:layout_height="match_parent" android:layout_width="match_parent" style="#style/card_thumbnail_image"/> </android.support.v7.widget.CardView> MainActivity.java ImageView imageView = (ImageView) findViewById(R.id.card_thumbnail_image); Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.rose); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){ //Default imageView.setBackgroundResource(R.drawable.rose); } else { //RoundCorners RoundCornersDrawable round = new RoundCornersDrawable(mBitmap, getResources().getDimension(R.dimen.cardview_default_radius), 0); //or your custom radius CardView cardView = (CardView) findViewById(R.id.card_view); cardView.setPreventCornerOverlap(false); //it is very important if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) imageView.setBackground(round); else imageView.setBackgroundDrawable(round); } RoundCornersDrawable.java public class RoundCornersDrawable extends Drawable { private final float mCornerRadius; private final RectF mRect = new RectF(); //private final RectF mRectBottomR = new RectF(); //private final RectF mRectBottomL = new RectF(); private final BitmapShader mBitmapShader; private final Paint mPaint; private final int mMargin; public RoundCornersDrawable(Bitmap bitmap, float cornerRadius, int margin) { mCornerRadius = cornerRadius; mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setShader(mBitmapShader); mMargin = margin; } #Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); mRect.set(mMargin, mMargin, bounds.width() - mMargin, bounds.height() - mMargin); //mRectBottomR.set( (bounds.width() -mMargin) / 2, (bounds.height() -mMargin)/ 2,bounds.width() - mMargin, bounds.height() - mMargin); // mRectBottomL.set( 0, (bounds.height() -mMargin) / 2, (bounds.width() -mMargin)/ 2, bounds.height() - mMargin); } #Override public void draw(Canvas canvas) { canvas.drawRoundRect(mRect, mCornerRadius, mCornerRadius, mPaint); //canvas.drawRect(mRectBottomR, mPaint); //only bottom-right corner not rounded //canvas.drawRect(mRectBottomL, mPaint); //only bottom-left corner not rounded } #Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } #Override public void setAlpha(int alpha) { mPaint.setAlpha(alpha); } #Override public void setColorFilter(ColorFilter cf) { mPaint.setColorFilter(cf); } }
first import the drawbleToolBox library in your project. with this library, you can create drawable dynamically. for make your cardview circle your radius must be half of its height/widht. int radius = cardView.getHeight()/2; Drawable drawable = new DrawableBuilder() .rectangle() .solidColor(0xffffffff) .topRightRadius(radius) // in pixels .bottomRightRadius(radius) //otherplaces .build(); holder.cardView.setBackground(drawable); if you are using cardview in your recycleview, getting the cardview widths doesn't work becuse it doesn't create yet. so you should do as below holder.cardView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { #Override public boolean onPreDraw() { //codes here. } }
Using CardView to obtain circular background with shadow can be quiet troublesome intead use layer-list in drawable to get the desired output. <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape android:shape="oval"> <!--shadow color you want--> <solid android:color="#C3C1C1"/> </shape> </item> <item android:left="0dp" android:right="0dp" android:top="0dp" android:bottom="2dp"> <shape android:shape="oval"> <solid android:color="#color/white"/> </shape> </item> </layer-list>
Button Layout with Profile Picture Alignment
I want to create buttons that look like in the picture. Inside the circle (which is transparent in the png) I want to place the profile picture of players. There should also be text on the blue bar. I've got it working but it just seems way too complicated. I think it is easier to understand what I have done without giving code but if you need it I can add it. Here is the layout: RelativeLayout LinearLayout (horizontal orientation) Empty view with weight 0.7 Profile Picture with weight 0.2 Empty view with weight 0.1 the overlay picture that I posted below LinearLayout (horizontal orientation) RelativeLayout with weight 0.7 (space where all the text can go) empty view with weigh 0.3 By the way: to the right of the circle, the png isn't transparent but white! This works well but there must be a better way! All these empty views just to align the picture to the right position is kind of ugly. And the fact that the overlay picture must go inbetween the profile picture and the text makes it even uglier. I'd prefer to do it without a png as overlay but with simple shapes (so that it looks good on every screen) but I wouldn't know how to do that. Would you recommend that? And if yes, how could that be done? Or do you have an idea how to improve the xml layout or how to do it otherwise. Thanks very much
You can do it without any image: Layout: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="60dp" android:weightSum="1.0"> <TextView android:layout_weight="0.7" android:layout_width="wrap_content" android:layout_height="match_parent" android:text="New Text" android:id="#+id/textView" android:background="#0073ff"/> <ImageView android:layout_weight="0.2" android:layout_width="0dp" android:layout_height="match_parent" android:background="#drawable/half_round_drawable" android:src="#drawable/profile"/> </LinearLayout> </LinearLayout> half_round_drawable: <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item> <shape android:shape="oval"> <corners android:radius="16dp" /> <solid android:color="#0073ff" /> </shape> </item> <item android:bottom="0dp" android:right="32dp"> <!-- radius *2 --> <shape> <solid android:color="#0073ff" /> </shape> </item> </layer-list> To make the profile-image round you should use something like this: How to create a circular ImageView in Android?
You can use a simple LinearLayout if you confine the background image to the profile area at the right side. You can define the content area in the image itself if you use a nine-patch drawable, as follows: Extract the profile portion from your background image file. Create a nine patch drawable from it, defining all the area as stretchable (left and top border lines), and the empty circle as the content area (right and bottom lines). Since you should ideally have the image at the foreground layer to ensure that the photo isn't drawn outside of the circle, you can use a FrameLayout with a foreground drawable to contain your profile photo's ImageView. There would also need to be another dummy child view to work around a bug in FrameLayout that causes a single child with match_parent dimensions to be layout incorrectly. This is how the layout should look like at the end: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="#+id/text" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="#00f" /> <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:foreground="#drawable/profile_bg"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" /> <ImageView android:id="#+id/photo" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout> </LinearLayout>
Now I am ready to present my answer. Portret: Landscape: Layout.xml: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:shape="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin" android:paddingRight="#dimen/activity_horizontal_margin" android:paddingTop="#dimen/activity_vertical_margin" android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity"> <!--This is the CustomView which include --> <!--own attributes: --> <!--circle_radius is the radius of image, --> <!--content_padding is the padding,--> <!--and background_color is the color of shape.--> <CustomShape android:layout_width="match_parent" android:layout_height="wrap_content" shape:circle_radius="40dp" shape:content_padding="8dp" shape:background_color="#FF983493"> <!--There must be two Views:--> <!--TextView and ImageView and only in this order.--> <!--Set--> <!--android:layout_width="wrap_content"--> <!--android:layout_height="wrap_content"--> <!--to bot of them, because in CustomShape it will be--> <!--resized for you. There also don`t need to set --> <!--any kind of margin or location attributes.--> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="#+id/txt" android:padding="5dp" android:textColor="#android:color/white" android:text="sdsfkjsdkfhsdk flsdkfjkls asdfasd fklasdjl fkjasdklfjasd k " android:background="#android:color/transparent"/> <!--For RoundImage I use custom class which round the drawable,--> <!--not a View. Look down.--> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="#+id/img" android:src="#drawable/img" android:scaleType="fitCenter" android:background="#android:color/transparent" /> </CustomShape> </RelativeLayout> CustomShape class: public class CustomShape extends RelativeLayout { Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); int circleRadius; // image radius int diameter; // image diameter int contentPadding; int semiPadding; int rectRightSide; int backgroundColor; int viewWidth; // width of parent(CustomShape layout) public CustomShape(Context context) { super(context); this.setWillNotDraw(false); } public CustomShape(Context context, AttributeSet attrs) { super(context, attrs); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomShape, 0, 0); try { this.circleRadius = (int) ta.getDimension(R.styleable.CustomShape_circle_radius, 40); this.contentPadding = (int) ta.getDimension(R.styleable.CustomShape_content_padding, 8); this.backgroundColor = ta.getColor(R.styleable.CustomShape_background_color, 0); this.semiPadding = contentPadding / 2; this.diameter = circleRadius * 2; } finally { ta.recycle(); } this.setWillNotDraw(false); } public CustomShape(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.setWillNotDraw(false); } #Override protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld) { super.onSizeChanged(xNew, yNew, xOld, yOld); viewWidth = xNew; this.rectRightSide = viewWidth - circleRadius - (circleRadius / 2); // get position for image } #Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { ImageView img = (ImageView) this.getChildAt(1); RelativeLayout.LayoutParams imgParams = new LayoutParams(diameter - contentPadding, diameter - contentPadding); imgParams.leftMargin = rectRightSide - circleRadius + semiPadding; imgParams.topMargin = semiPadding; img.setLayoutParams(imgParams); //Create custom RoundImage and set to image try { Drawable drawable = img.getDrawable(); Bitmap bm = ((BitmapDrawable) drawable).getBitmap(); RoundImage resultImage = new RoundImage(bm); img.setImageDrawable(resultImage); } catch (ClassCastException e) { } //Positioning and resizing TextView View txt = this.getChildAt(0); RelativeLayout.LayoutParams txtParams = new LayoutParams(rectRightSide - circleRadius - semiPadding, diameter - contentPadding); txtParams.topMargin = semiPadding; txtParams.leftMargin = semiPadding; txt.setLayoutParams(txtParams); super.onMeasure(widthMeasureSpec, heightMeasureSpec); int parentWidth = MeasureSpec.getSize(widthMeasureSpec); this.setMeasuredDimension(parentWidth, diameter); // set correct height } #Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); paint.setColor(backgroundColor); canvas.drawRect(0, 0, rectRightSide, diameter, paint); //Draw circle paint.setDither(true); canvas.drawCircle(rectRightSide, circleRadius, circleRadius, paint); } } Attr.xml: <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="CustomShape"> <attr name="circle_radius" format="dimension" /> <attr name="content_padding" format="dimension" /> <attr name="background_color" format="color" /> </declare-styleable> </resources> RoundImage class: public class RoundImage extends Drawable { private final Bitmap mBitmap; private final Paint mPaint; private final RectF mRectF; private final int mBitmapWidth; private final int mBitmapHeight; public RoundImage(Bitmap bitmap) { mBitmap = bitmap; mRectF = new RectF(); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setDither(true); final BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mPaint.setShader(shader); mBitmapWidth = mBitmap.getWidth(); mBitmapHeight = mBitmap.getHeight(); } #Override public void draw(Canvas canvas) { canvas.drawOval(mRectF, mPaint); } #Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); mRectF.set(bounds); } #Override public void setAlpha(int alpha) { if (mPaint.getAlpha() != alpha) { mPaint.setAlpha(alpha); invalidateSelf(); } } #Override public void setColorFilter(ColorFilter cf) { mPaint.setColorFilter(cf); } #Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } #Override public int getIntrinsicWidth() { return mBitmapWidth; } #Override public int getIntrinsicHeight() { return mBitmapHeight; } public void setAntiAlias(boolean aa) { mPaint.setAntiAlias(aa); invalidateSelf(); } #Override public void setFilterBitmap(boolean filter) { mPaint.setFilterBitmap(filter); invalidateSelf(); } #Override public void setDither(boolean dither) { mPaint.setDither(dither); invalidateSelf(); } public Bitmap getBitmap() { return mBitmap; } } Hope it will help you.
How to fit image in circular border and rectangular border [duplicate]
I'd Like to make any image from my ImageView to be circular with a border. I searched but couldn't find any useful information (anything that I tried didn't work). How can I achieve this through XML: Create an ImageView with certain src and make it circular with a border?
This is the simplest way that I designed. Try this. dependencies implementation 'androidx.appcompat:appcompat:1.3.0-beta01' implementation 'androidx.cardview:cardview:1.0.0' <android.support.v7.widget.CardView android:layout_width="80dp" android:layout_height="80dp" android:elevation="12dp" android:id="#+id/view2" app:cardCornerRadius="40dp" android:layout_centerHorizontal="true" android:innerRadius="0dp" android:shape="ring" android:thicknessRatio="1.9"> <ImageView android:layout_height="80dp" android:layout_width="match_parent" android:id="#+id/imageView1" android:src="#drawable/YOUR_IMAGE" android:layout_alignParentTop="true" android:layout_centerHorizontal="true"> </ImageView> </android.support.v7.widget.CardView> If you are working on android versions above lollipop <android.support.v7.widget.CardView android:layout_width="80dp" android:layout_height="80dp" android:elevation="12dp" android:id="#+id/view2" app:cardCornerRadius="40dp" android:layout_centerHorizontal="true"> <ImageView android:layout_height="80dp" android:layout_width="match_parent" android:id="#+id/imageView1" android:src="#drawable/YOUR_IMAGE" android:scaleType="centerCrop"/> </android.support.v7.widget.CardView> Adding Border to round ImageView - LATEST VERSION Wrap it with another CardView slightly bigger than the inner one and set its background color to add a border to your round image. You can increase the size of the outer CardView to increase the thickness of the border. <androidx.cardview.widget.CardView android:layout_width="155dp" android:layout_height="155dp" app:cardCornerRadius="250dp" app:cardBackgroundColor="#color/white"> <androidx.cardview.widget.CardView android:layout_width="150dp" android:layout_height="150dp" app:cardCornerRadius="250dp" android:layout_gravity="center"> <ImageView android:layout_width="150dp" android:layout_height="150dp" android:src="#drawable/default_user" android:scaleType="centerCrop"/> </androidx.cardview.widget.CardView> </androidx.cardview.widget.CardView>
You can make a simple circle with white border and transparent content with shape. // res/drawable/circle.xml <shape xmlns:android="http://schemas.android.com/apk/res/android" android:innerRadius="0dp" android:shape="ring" android:thicknessRatio="1.9" android:useLevel="false" > <solid android:color="#android:color/transparent" /> <stroke android:width="10dp" android:color="#android:color/white" /> </shape> Then make a layerlist drawable and put it as background to your imageview. // res/drawable/img.xml <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item android:drawable="#drawable/circle"/> <item android:drawable="#drawable/ic_launcher"/> </layer-list> and put it as background to your imageview. <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#drawable/img"/> You'll have something like that.
With the Material Components Library Just use the ShapeableImageView. Somethig like: <com.google.android.material.imageview.ShapeableImageView app:shapeAppearanceOverlay="#style/roundedImageViewRounded" app:strokeColor="#color/....." app:strokeWidth="1dp" ... /> with: <style name="roundedImageViewRounded"> <item name="cornerFamily">rounded</item> <item name="cornerSize">50%</item> </style> Note: it requires at least the version 1.2.0. With jetpack compose you can apply the clip Modifier using a CircleShape: Image( painter = painterResource(R.drawable.xxxx), contentDescription = "xxxx", contentScale = ContentScale.Crop, modifier = Modifier .size(100.dp) .clip(CircleShape) .border(2.dp, Color.Blue, CircleShape) )
I hope this will help you. 1) ShapeableImageView <com.google.android.material.imageview.ShapeableImageView android:layout_width="250dp" android:layout_height="250dp" android:padding="5dp" app:strokeWidth="10dp" app:strokeColor="#android:color/darker_gray" app:shapeAppearanceOverlay="#style/circleImageView" android:src="#drawable/profile" android:layout_margin="10dp"/> Style add here: res/values/styles.xml <style name="circleImageView" parent=""> <item name="cornerFamily">rounded</item> <item name="cornerSize">50%</item> </style> For complete description please check here : The Source here. 2) CircleImageView <de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto" android:id="#+id/profile_image" android:layout_width="96dp" android:layout_height="96dp" android:src="#drawable/profile" app:civ_border_width="2dp" app:civ_border_color="#FF000000"/> Don't forget implementation: Gradle Scripts > build.gradle (Module: app) > dependencies implementation 'de.hdodenhof:circleimageview:3.1.0' For complete description please check here : The Source here. 3) CircularImageView <com.mikhaellopez.circularimageview.CircularImageView android:layout_width="250dp" android:layout_height="250dp" android:src="#drawable/image" app:civ_border_color="#3f51b5" app:civ_border_width="4dp" app:civ_shadow="true" app:civ_shadow_radius="10" app:civ_shadow_color="#3f51b5"/> Don't forget implementation: Gradle Scripts > build.gradle (Module: app) > dependencies implementation 'com.mikhaellopez:circularimageview:4.3.1' For complete description please check here : The Source here.
With the help of glide library and RoundedBitmapDrawableFactory class it's easy to achieve. You may need to create circular placeholder image. Glide V4: Glide.with(context).load(url).apply(RequestOptions.circleCropTransform()).into(imageView); Glide V3: Glide.with(context) .load(imgUrl) .asBitmap() .placeholder(R.drawable.placeholder) .error(R.drawable.placeholder) .into(new BitmapImageViewTarget(imgProfilePicture) { #Override protected void setResource(Bitmap resource) { RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(context.getResources(), Bitmap.createScaledBitmap(resource, 50, 50, false)); drawable.setCircular(true); imgProfilePicture.setImageDrawable(drawable); } }); For Picasso RoundedTransformation, this is a really great solution that gives an additional option of rounding image at either top or bottom edge.
The above methods don't seem to work if you're using the src attribute. What I did is to put two image views inside a frame layout one above another like this: <FrameLayout android:id="#+id/frame" android:layout_width="40dp" android:layout_height="40dp"> <ImageView android:id="#+id/pic" android:layout_width="40dp" android:layout_height="40dp" android:src="#drawable/my_picture" /> <ImageView android:id="#+id/circle_crop" android:layout_width="40dp" android:layout_height="40dp" android:src="#drawable/circle_crop" /> </FrameLayout> Simply put a circular_crop.png in your drawable folder which is in the shape of your image dimensions (a square in my case) with a white background and a transparent circle in the center. You can use this image if you have want a square imageview. Just download the picture above.
The following is one of the simplest ways to do it, use the following code: Dependencies dependencies { ... compile 'de.hdodenhof:circleimageview:2.1.0' // use this or use the latest compile version. In case u get bug. } XML Code <de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto" android:id="#+id/profile_image" android:layout_width="96dp" // here u can adjust the width android:layout_height="96dp" // here u can adjust the height android:src="#drawable/profile" // here u can change the image app:civ_border_width="2dp" // here u can adjust the border of the circle. app:civ_border_color="#FF000000"/> // here u can adjust the border color Screenshot: Source: Circular ImageView GitHub Repository
you don't need any third-party library. you can use the ShapeableImageView in the material. implementation 'com.google.android.material:material:1.2.0' style.xml <style name="ShapeAppearanceOverlay.App.CornerSize"> <item name="cornerSize">50%</item> </style> in layout <com.google.android.material.imageview.ShapeableImageView android:layout_width="100dp" android:layout_height="100dp" app:srcCompat="#drawable/ic_profile" app:shapeAppearanceOverlay="#style/ShapeAppearanceOverlay.App.CornerSize" /> you can see this https://developer.android.com/reference/com/google/android/material/imageview/ShapeableImageView or this https://medium.com/android-beginners/shapeableimageview-material-components-for-android-cac6edac2c0d
You can simply use AndroidX ImageFilterView. <androidx.constraintlayout.utils.widget.ImageFilterView android:layout_width="48dp" android:layout_height="48dp" android:layout_marginStart="#dimen/margin_medium" android:layout_marginBottom="#dimen/margin_medium" android:background="#color/white" android:padding="#dimen/margin_small" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:roundPercent="1" app:srcCompat="#drawable/ic_gallery" />
You can simply use CardView without any external Library <androidx.cardview.widget.CardView android:id="#+id/roundCardView" android:layout_width="40dp" android:layout_height="40dp" android:layout_centerHorizontal="true" android:elevation="0dp" app:cardCornerRadius="20dp"> <ImageView android:layout_width="40dp" android:layout_height="40dp" android:src="#drawable/profile" /> </androidx.cardview.widget.CardView>
This will do the trick: rectangle.xml <?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="#android:color/transparent" /> <padding android:bottom="-14dp" android:left="-14dp" android:right="-14dp" android:top="-14dp" /> </shape> circle.xml <shape xmlns:android="http://schemas.android.com/apk/res/android" android:innerRadius="0dp" android:shape="oval" android:useLevel="false" > <solid android:color="#android:color/transparent" /> <stroke android:width="15dp" android:color="#color/verification_contact_background" /> </shape> profile_image.xml ( The layerlist ) <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item android:drawable="#drawable/rectangle" /> <item android:drawable="#drawable/circle"/> </layer-list> Your layout <ImageView android:id="#+id/profile_image" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#drawable/default_org" android:src="#drawable/profile_image"/>
Posting this answer for future reference. You can use ShapeableImageView available in com.google.android.material:material. <com.google.android.material.imageview.ShapeableImageView android:id="#+id/img_launcher_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_margin="5dp" android:adjustViewBounds="true" android:background="#android:color/transparent" android:elevation="5dp" android:maxWidth="50dp" android:maxHeight="50dp" android:scaleType="fitXY" android:src="#mipmap/ic_launcher" app:shapeAppearance="?attr/actionButtonStyle" app:shapeAppearanceOverlay="#style/imageViewRounded" app:strokeColor="#android:color/white" /> Add imageViewRounded style in your styles.xml <style name="imageViewRounded"> <item name="cornerFamily">rounded</item> <item name="cornerSize">51%</item> </style> You can add material design dependency if not added. implementation 'com.google.android.material:material:1.4.0' Design looks like
Best Solution courtesy https://www.youtube.com/watch?v=0MHoNU7ytaw the width and height of the card view determine the size of the images it contains set up is as follows: Add Dependency to Gradle(Module) Add the xml code to activity.xml or fragment.xml file implementation 'androidx.cardview:cardview:1.0.0' <androidx.cardview.widget.CardView android:layout_width="300dp" android:layout_height="270dp" android:layout_gravity="center" app:cardCornerRadius="150dp" app:cardBackgroundColor="#color/trans" > <ImageView android:id="#+id/resultImage" android:layout_width="match_parent" android:layout_height="match_parent" android:src="#drawable/congrats" android:layout_gravity="center"> </ImageView> </androidx.cardview.widget.CardView>```
Update 2021: Using Glide v4 CircleCrop see https://bumptech.github.io/glide/doc/generatedapi.html implementation 'com.github.bumptech.glide:glide:4.11.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' XML <ImageView android:id="#+id/vinyl" android:layout_width="match_parent" android:layout_height="match_parent" tools:ignore="ContentDescription" /> In Code Glide.with(this) .load("https://images.pexels.com/photos/3828241/pexels-photo-3828241.jpeg") .transform(CircleCrop()) .into(rootView.findViewById<ImageView>(R.id.vinyl))
I use shape = "oval" instead of the "ring" below. It has worked for me. To keep the image within bounds, I use <padding> and set <adjustViewBounds> to true in my <ImageView>. I have tried with images of size between 50 x 50 px upto 200x200 px .
#Jyotman Singh, answer is very good (for solid backgrounds), so I would like to enhance it by sharing vector drawable that can be re-colored for your needs, also it is convenient since vector one-piece shape is well scalable. This is the rectangle-circle shape (#drawable/shape_round_profile_pic): <?xml version="1.0" encoding="utf-8"?> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:viewportWidth="284" android:viewportHeight="284" android:width="284dp" android:height="284dp"> <path android:pathData="M0 142L0 0l142 0 142 0 0 142 0 142 -142 0 -142 0zm165 137.34231c26.06742 -4.1212 52.67405 -17.543 72.66855 -36.65787 11.82805 -11.30768 20.55487 -22.85153 27.7633 -36.72531C290.23789 158.21592 285.62874 101.14121 253.48951 58.078079 217.58149 9.9651706 154.68849 -10.125717 98.348685 8.5190299 48.695824 24.95084 12.527764 67.047123 3.437787 118.98655 1.4806194 130.16966 1.511302 152.96723 3.4990422 164.5 12.168375 214.79902 47.646316 256.70775 96 273.76783c21.72002 7.66322 44.26673 9.48476 69 5.57448z" android:fillColor="#ffffff" /> // you can change frame color </vector> Usage is the same: <FrameLayout android:layout_width="70dp" android:layout_height="70dp"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:background="#drawable/YOUR_PICTURE" /> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:background="#drawable/shape_round_profile_pic"/> </FrameLayout>
Just use these lines of code and you are done : <de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto" android:clickable="true" app:civ_border_width="3dp" app:civ_border_color="#FFFFFFFF" android:id="#+id/profile" android:layout_width="200dp" android:layout_height="200dp" android:layout_below="#+id/header_cover_image" android:layout_centerHorizontal="true" android:layout_marginTop="-130dp" android:elevation="5dp" android:padding="20dp" android:scaleType="centerCrop" android:src="#drawable/profilemain" /> Don't forget to import : import de.hdodenhof.circleimageview.CircleImageView; Add this library in build.gradle : compile 'de.hdodenhof:circleimageview:2.1.0'
If you use Material Design in your app then use this <com.google.android.material.card.MaterialCardView android:layout_width="75dp" android:layout_height="75dp" app:cardCornerRadius="50dp" app:strokeWidth="1dp" app:strokeColor="#color/black"> <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="#+id/circular_image" android:scaleType="fitCenter" android:src="#drawable/your_img" /> </com.google.android.material.card.MaterialCardView>
I did it like that, I used my background color in my vector image ic_bg_picture.xml <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="100dp" android:height="100dp" android:viewportWidth="100" android:viewportHeight="100"> <path android:pathData="M100.6,95.5c0,-0.4 -0.1,-0.7 0,-1.1c-0.2,-0.7 -0.2,-1.4 -0.1,-2.1c0,-0.1 0,-0.2 0,-0.3c-0.1,-0.6 -0.1,-1.2 0,-1.8c-1,-1.3 -0.3,-2.9 -0.3,-4.3c-0.1,-28.7 -0.1,-57.3 -0.1,-86C68,-0.1 35.9,-0.1 3.8,-0.2C0.7,-0.2 0,0.5 0,3.6c0.1,32.1 0.1,64.2 0.1,96.2c31,0 62,-0.1 92.9,0.1c3.6,0 6.3,-0.2 7.5,-3.2C100.5,96.4 100.5,95.9 100.6,95.5zM46.3,95.2C26.4,94 2,74.4 3.8,46.8C5.1,27.2 24.4,2.7 52.6,4.6c20.2,1.4 43,21.3 41.5,45.1C96.1,72.4 73,96.8 46.3,95.2z" android:fillColor="#6200EE"/> </vector> in my case I created a vector and changed the android:fillColor="#6200EE" by the color of my background <ImageView android:id="#+id/iv_profile_image" android:layout_width="100dp" android:layout_height="100dp" android:contentDescription="#string/app_name" app:srcCompat="#color/colorPrimaryDark" /> <ImageView android:id="#+id/container_profile_image" android:layout_width="100dp" android:layout_height="100dp" android:contentDescription="#string/app_name" app:srcCompat="#drawable/ic_bg_picture"/>
Another method without using any library is using ImageFilterView and setting round percentage to the view will make the circle round app:roundPercent="1" <androidx.constraintlayout.utils.widget.ImageFilterView android:id="#+id/ivProfile" android:layout_width="150dp" android:layout_height="150dp" android:src="#drawable/custom_button_1" app:roundPercent="1" android:scaleType="fitXY" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toTopOf="#+id/etName"/>
Try this. public class RoundedImageView extends android.support.v7.widget.AppCompatImageView { private int borderWidth = 4; private int viewWidth; private int viewHeight; private Bitmap image; private Paint paint; private Paint paintBorder; private BitmapShader shader; public RoundedImageView(Context context) { super(context); setup(); } public RoundedImageView(Context context, AttributeSet attrs) { super(context, attrs); setup(); } public RoundedImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setup(); } private void setup() { paint = new Paint(); paint.setAntiAlias(true); paintBorder = new Paint(); setBorderColor(Color.WHITE); paintBorder.setAntiAlias(true); this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder); paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.WHITE); } public void setBorderWidth(int borderWidth) { this.borderWidth = borderWidth; this.invalidate(); } public void setBorderColor(int borderColor) { if (paintBorder != null) paintBorder.setColor(borderColor); this.invalidate(); } private void loadBitmap() { BitmapDrawable bitmapDrawable = (BitmapDrawable) this.getDrawable(); if (bitmapDrawable != null) image = bitmapDrawable.getBitmap(); } #SuppressLint("DrawAllocation") #Override public void onDraw(Canvas canvas) { loadBitmap(); if (image != null) { shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvas.getWidth(), canvas.getHeight(), false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); paint.setShader(shader); int circleCenter = viewWidth / 2; canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter + borderWidth - 4.0f, paintBorder); canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, circleCenter - 4.0f, paint); } } #Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = measureWidth(widthMeasureSpec); int height = measureHeight(heightMeasureSpec, widthMeasureSpec); viewWidth = width - (borderWidth * 2); viewHeight = height - (borderWidth * 2); setMeasuredDimension(width, height); } private int measureWidth(int measureSpec) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { // Measure the text result = viewWidth; } return result; } private int measureHeight(int measureSpecHeight, int measureSpecWidth) { int result = 0; int specMode = MeasureSpec.getMode(measureSpecHeight); int specSize = MeasureSpec.getSize(measureSpecHeight); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { result = viewHeight; } return (result + 2); } } and use this ImageView in layout like: <com.app.Demo.RoundedImageView android:id="#+id/iv_profileImage" android:layout_width="70dp" android:layout_height="70dp" android:layout_centerHorizontal="true" />
This Class is Custom Circular Imageview with shadow, Stroke,saturation and using this Custom Circular ImageView you can make your image in Circular Shape with Radius. Guys for Circular Shadow ImageView No need Github this class is enough. Adding CircularImageView to your layout CircularImageView c=new CircularImageView(this,screen width,screen height,Bitmap myimage); yourLayout.addView(c);** public class CircularImageView extends android.support.v7.widget.AppCompatImageView { private final Context context; private final int width, height; private final Paint paint; private final Paint paintBorder,imagePaint; private final Bitmap bitmap2; private final Paint paint3; private Bitmap bitmap; private BitmapShader shader; private float radius = 4.0f; float x = 0.0f; float y = 8.0f; private float stroke; private float strokeWidth = 0.0f; private Bitmap bitmap3; private int corner_radius=50; public CircularImageView(Context context, int width, int height, Bitmap bitmap) { super(context); this.context = context; this.width = width; this.height = height; //here "bitmap" is the square shape(width* width) scaled bitmap .. this.bitmap = bitmap; paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setAntiAlias(true); paint.setFilterBitmap(true); paint.setDither(true); paint3=new Paint(); paint3.setStyle(Paint.Style.STROKE); paint3.setColor(Color.WHITE); paint3.setAntiAlias(true); paintBorder = new Paint(); imagePaint= new Paint(); paintBorder.setColor(Color.WHITE); paintBorder.setAntiAlias(true); this.setLayerType(LAYER_TYPE_SOFTWARE, paintBorder); this.bitmap2 = Bitmap.createScaledBitmap(bitmap, (bitmap.getWidth() - 40), (bitmap.getHeight() - 40), true); imagePaint.setAntiAlias(true); invalidate(); } #Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Shader b; if (bitmap3 != null) b = new BitmapShader(bitmap3, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); else b = new BitmapShader(bitmap2, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); imagePaint.setShader(b); canvas.drawBitmap(maskedBitmap(), 20, 20, null); } private Bitmap maskedBitmap() { Bitmap l1 = Bitmap.createBitmap(width,width, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(l1); paintBorder.setShadowLayer(radius, x, y, Color.parseColor("#454645")); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); final RectF rect = new RectF(); rect.set(20, 20, bitmap2.getWidth(), bitmap2.getHeight()); canvas.drawRoundRect(rect, corner_radius, corner_radius, paintBorder); canvas.drawRoundRect(rect, corner_radius, corner_radius, imagePaint); if (strokeWidth!=0.0f) { paint3.setStrokeWidth(strokeWidth); canvas.drawRoundRect(rect, corner_radius, corner_radius, paint3); } paint.setXfermode(null); return l1; } // use seekbar here, here you have to pass "0 -- 250" here corner radius will change public void setCornerRadius(int corner_radius) { this.corner_radius = corner_radius; invalidate(); } -------->use seekbar here, here you have to pass "0 -- 10.0f" here shadow radius will change public void setShadow(float radius) { this.radius = radius; invalidate(); } // use seekbar here, here you have to pass "0 -- 10.0f" here stroke size will change public void setStroke(float stroke) { this.strokeWidth = stroke; invalidate(); } private Bitmap updateSat(Bitmap src, float settingSat) { int w = src.getWidth(); int h = src.getHeight(); Bitmap bitmapResult = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas canvasResult = new Canvas(bitmapResult); Paint paint = new Paint(); ColorMatrix colorMatrix = new ColorMatrix(); colorMatrix.setSaturation(settingSat); ColorMatrixColorFilter filter = new ColorMatrixColorFilter(colorMatrix); paint.setColorFilter(filter); canvasResult.drawBitmap(src, 0, 0, paint); return bitmapResult; } // use seekbar here, here you have to pass "0 -- 2.0f" here saturation will change public void setSaturation(float sat) { System.out.println("qqqqqqqqqq "+sat); bitmap3=updateSat(bitmap2, sat); invalidate(); } } // Seekbar to change radius radius_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { #Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { text_radius.setText(""+progress); circularImageView.setCornerRadius(progress); } #Override public void onStartTrackingTouch(SeekBar seekBar) { } #Override public void onStopTrackingTouch(SeekBar seekBar) { } }); // Seekbar to change shadow shadow_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { #Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { float f= 4+progress/10.0f; text_shadow.setText(""+progress); circularImageView.setShadow(f); } #Override public void onStartTrackingTouch(SeekBar seekBar) { } #Override public void onStopTrackingTouch(SeekBar seekBar) { } }); // Seekbar to change saturation saturation_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { #Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { int progressSat = saturation_seekbar.getProgress(); float sat = (float) ((progressSat*4 / 100.0f)-1.0f); circularImageView.setSaturation(sat); text_saturation.setText(""+progressSat); } #Override public void onStartTrackingTouch(SeekBar seekBar) { } #Override public void onStopTrackingTouch(SeekBar seekBar) { } }); // Seekbar to change stroke stroke_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { #Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (progress==0) { float f=(progress*10.0f/100.0f); circularImageView.setStroke(f); } else { float f=(progress*10.0f/100.0f); circularImageView.setStroke(f); } text_stroke.setText(""+progress); } #Override public void onStartTrackingTouch(SeekBar seekBar) { } #Override public void onStopTrackingTouch(SeekBar seekBar) { } }); //radius seekbar in xml file <SeekBar android:layout_width="match_parent" android:layout_gravity="center" android:progress="50" android:max="250" android:id="#+id/radius_seekbar" android:layout_height="wrap_content" /> //saturation seekbar in xml file <SeekBar android:layout_width="match_parent" android:layout_gravity="center" android:progress="50" android:max="100" android:id="#+id/saturation_seekbar" android:layout_height="wrap_content" /> //shadow seekbar in xml file <SeekBar android:layout_width="match_parent" android:layout_gravity="center" android:progress="0" android:max="100" android:id="#+id/shadow_seekbar" android:layout_height="wrap_content" /> //stroke seekbar in xml file <SeekBar android:layout_width="match_parent" android:layout_gravity="center" android:progress="0" android:max="100" android:id="#+id/stroke _seekbar" android:layout_height="wrap_content" />
Actually, you can use what Google provides via the support library RoundedBitmapDrawableFactory class (here and here), instead of using a third party library : Gradle: implementation 'androidx.appcompat:appcompat:1.0.0-beta01' MainActivity.kt class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val originalDrawable = ContextCompat.getDrawable(this, R.drawable.avatar_1)!! val bitmap = convertDrawableToBitmap(originalDrawable) val drawable = RoundedBitmapDrawableFactory.create(resources, bitmap) drawable.setAntiAlias(true) drawable.cornerRadius = Math.max(bitmap.width, bitmap.height) / 2.0f avatarImageView.setImageDrawable(drawable) } companion object { #JvmStatic fun convertDrawableToBitmap(drawable: Drawable): Bitmap { if (drawable is BitmapDrawable) return drawable.bitmap // We ask for the bounds if they have been set as they would be most // correct, then we check we are > 0 val bounds = drawable.bounds val width = if (!bounds.isEmpty) bounds.width() else drawable.intrinsicWidth val height = if (!bounds.isEmpty) bounds.height() else drawable.intrinsicHeight // Now we check we are > 0 val bitmap = Bitmap.createBitmap(if (width <= 0) 1 else width, if (height <= 0) 1 else height, Bitmap.Config.ARGB_8888) val canvas = Canvas(bitmap) drawable.setBounds(0, 0, canvas.width, canvas.height) drawable.draw(canvas) return bitmap } } } res/layout/activity_main.xml <FrameLayout 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:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <androidx.appcompat.widget.AppCompatImageView android:id="#+id/avatarImageView" android:layout_width="100dp" android:layout_height="100dp" android:layout_gravity="center"/> </FrameLayout> res/drawable/avatar_1.xml <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="128dp" android:height="128dp" android:viewportHeight="128.0" android:viewportWidth="128.0"> <path android:fillColor="#FF8A80" android:pathData="M0 0h128v128h-128z"/> <path android:fillColor="#FFE0B2" android:pathData="M36.3 94.8c6.4 7.3 16.2 12.1 27.3 12.4 10.7,-.3 20.3,-4.7 26.7,-11.6l.2.1c-17,-13.3,-12.9,-23.4,-8.5,-28.6 1.3,-1.2 2.8,-2.5 4.4,-3.9l13.1,-11c1.5,-1.2 2.6,-3 2.9,-5.1.6,-4.4,-2.5,-8.4,-6.9,-9.1,-1.5,-.2,-3 0,-4.3.6,-.3,-1.3,-.4,-2.7,-1.6,-3.5,-1.4,-.9,-2.8,-1.7,-4.2,-2.5,-7.1,-3.9,-14.9,-6.6,-23,-7.9,-5.4,-.9,-11,-1.2,-16.1.7,-3.3 1.2,-6.1 3.2,-8.7 5.6,-1.3 1.2,-2.5 2.4,-3.7 3.7l-1.8 1.9c-.3.3,-.5.6,-.8.8,-.1.1,-.2 0,-.4.2.1.2.1.5.1.6,-1,-.3,-2.1,-.4,-3.2,-.2,-4.4.6,-7.5 4.7,-6.9 9.1.3 2.1 1.3 3.8 2.8 5.1l11 9.3c1.8 1.5 3.3 3.8 4.6 5.7 1.5 2.3 2.8 4.9 3.5 7.6 1.7 6.8,-.8 13.4,-5.4 18.4,-.5.6,-1.1 1,-1.4 1.7,-.2.6,-.4 1.3,-.6 2,-.4 1.5,-.5 3.1,-.3 4.6.4 3.1 1.8 6.1 4.1 8.2 3.3 3 8 4 12.4 4.5 5.2.6 10.5.7 15.7.2 4.5,-.4 9.1,-1.2 13,-3.4 5.6,-3.1 9.6,-8.9 10.5,-15.2m-14.4,-49.8c.9 0 1.6.7 1.6 1.6 0 .9,-.7 1.6,-1.6 1.6,-.9 0,-1.6,-.7,-1.6,-1.6,-.1,-.9.7,-1.6 1.6,-1.6zm-25.7 0c.9 0 1.6.7 1.6 1.6 0 .9,-.7 1.6,-1.6 1.6,-.9 0,-1.6,-.7,-1.6,-1.6,-.1,-.9.7,-1.6 1.6,-1.6z"/> <path android:fillColor="#E0F7FA" android:pathData="M105.3 106.1c-.9,-1.3,-1.3,-1.9,-1.3,-1.9l-.2,-.3c-.6,-.9,-1.2,-1.7,-1.9,-2.4,-3.2,-3.5,-7.3,-5.4,-11.4,-5.7 0 0 .1 0 .1.1l-.2,-.1c-6.4 6.9,-16 11.3,-26.7 11.6,-11.2,-.3,-21.1,-5.1,-27.5,-12.6,-.1.2,-.2.4,-.2.5,-3.1.9,-6 2.7,-8.4 5.4l-.2.2s-.5.6,-1.5 1.7c-.9 1.1,-2.2 2.6,-3.7 4.5,-3.1 3.9,-7.2 9.5,-11.7 16.6,-.9 1.4,-1.7 2.8,-2.6 4.3h109.6c-3.4,-7.1,-6.5,-12.8,-8.9,-16.9,-1.5,-2.2,-2.6,-3.8,-3.3,-5z"/> <path android:fillColor="#444" android:pathData="M76.3,47.5 m-2.0, 0 a 2.0,2.0 0 1,1 4.0,0 a2.0,2.0 0 1,1 -4.0,0"/> <path android:fillColor="#444" android:pathData="M50.7,47.6 m-2.0, 0 a 2.0,2.0 0 1,1 4.0,0 a2.0,2.0 0 1,1 -4.0,0"/> <path android:fillColor="#444" android:pathData="M48.1 27.4c4.5 5.9 15.5 12.1 42.4 8.4,-2.2,-6.9,-6.8,-12.6,-12.6,-16.4 17.2 1.5 14.1,-9.4 14.1,-9.4,-1.4 5.5,-11.1 4.4,-11.1 4.4h-18.8c-1.7,-.1,-3.4 0,-5.2.3,-12.8 1.8,-22.6 11.1,-25.7 22.9 10.6,-1.9 15.3,-7.6 16.9,-10.2z"/> </vector> The result: And, suppose you want to add a border on top of it, you can use this for example: stroke_drawable.xml <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <stroke android:width="4dp" android:color="#android:color/black"/> </shape> And add android:foreground="#drawable/stroke_drawable" to the ImageView in the layout XML file, and you get this : I'm not sure how to add shadow (that will work on older Android versions), though. Using FloatingActionButton (from the "com.google.android.material:material" dependency), I failed to make the bitmap fill the FAB itself. Using it instead could be even better if it worked. EDIT: if you wish to add shadow of elevation (available from API 21), you can change a bit what I wrote: Inside the layout XML file: <androidx.appcompat.widget.AppCompatImageView android:padding="4dp" android:id="#+id/avatarImageView" android:layout_width="100dp" android:layout_height="100dp" android:elevation="8dp" android:layout_gravity="center" android:background="#drawable/stroke_drawable" tools:srcCompat="#drawable/avatar_1"/> CircularShadowViewOutlineProvider.kt #TargetApi(Build.VERSION_CODES.LOLLIPOP) class CircularShadowViewOutlineProvider : ViewOutlineProvider() { override fun getOutline(view: View, outline: Outline) { val size = Math.max(view.width, view.height) outline.setRoundRect(0, 0, size, size, size / 2f) } } In code: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) avatarImageView.outlineProvider = CircularShadowViewOutlineProvider() Result:
I have a simple solution. Create a new Image asset by right clicking your package name and selecting New->Image asset. Enter name (any name) and path (location of image in your system). Then click Next and Finish. If you enter name of image as 'img', a round image with the name 'img_round' is created automatically in mipmap folder. Then, do this : <ImageView android:layout_width="100dp" android:layout_height="100dp" android:src="#mipmap/img_round"/> Your preview may still show a rectangular image. But if you run the app on your device, it will be round.
Create a CustomImageview then simply override its onDraw() method follows: #Override protected void onDraw(Canvas canvas) { float radius = this.getHeight()/2; Path path = new Path(); RectF rect = new RectF(0, 0, this.getWidth(), this.getHeight()); path.addRoundRect(rect, radius, radius, Path.Direction.CW); canvas.clipPath(path); super.onDraw(canvas); } In case you want the code for the custom widget as well:- CircularImageView.java import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Path; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; import androidx.annotation.Nullable; public class CircularImageView extends ImageView { private Drawable image; public CircularImageView(Context context) { super(context); init(null, 0); } public CircularImageView(Context context, #Nullable AttributeSet attrs) { super(context, attrs); init(attrs, 0); } public CircularImageView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(attrs, defStyleAttr); } #Override protected void onDraw(Canvas canvas) { float radius = this.getHeight()/2; Path path = new Path(); RectF rect = new RectF(0, 0, this.getWidth(), this.getHeight()); path.addRoundRect(rect, radius, radius, Path.Direction.CW); canvas.clipPath(path); super.onDraw(canvas); } private void init(AttributeSet attrs, int defStyle) { TypedArray a = Utils.CONTEXT.getTheme().obtainStyledAttributes(attrs, R.styleable.CircularImageView, 0, 0); try { image = a.getDrawable(R.styleable.CircularImageView_src); } finally { a.recycle(); } this.setImageDrawable(image); } } Also, add the following code to your res/attrs.xml to create the required attribute:- <declare-styleable name="CircularImageView"> <attr name="src" format="reference" /> </declare-styleable>
if you want to set edit icon on to circle imageview than put this below code. <FrameLayout android:layout_width="#dimen/_100sdp" android:layout_height="#dimen/_100sdp" android:layout_gravity="center" android:layout_marginTop="10dp"> <de.hdodenhof.circleimageview.CircleImageView android:id="#+id/profilePic" android:layout_width="#dimen/_100sdp" android:layout_height="#dimen/_100sdp" android:layout_gravity="bottom|center_horizontal" android:src="#drawable/ic_upload" /> <de.hdodenhof.circleimageview.CircleImageView android:id="#+id/iv_camera" android:layout_width="#dimen/_30sdp" android:layout_height="#dimen/_30sdp" android:layout_gravity="top|right" android:src="#drawable/edit"/> </FrameLayout>
if you'd rather cut the image to display in circular, here you go public static Bitmap getCircularBitmap(Bitmap bitmap) { Bitmap output; if (bitmap.getWidth() > bitmap.getHeight()) { output = Bitmap.createBitmap(bitmap.getHeight(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); } else { output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getWidth(), Bitmap.Config.ARGB_8888); } Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); float r = 0; if (bitmap.getWidth() > bitmap.getHeight()) { r = bitmap.getHeight() / 2; } else { r = bitmap.getWidth() / 2; } paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawCircle(r, r, r, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return output; }
Another idea is to use clipToOutline property of an ImageView. Here is an example layout: <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <!-- Simple view to draw borders for an image, borders will be rounded because of the oval-shaped background. --> <View android:id="#+id/v_border" android:layout_width="50dp" android:layout_height="50dp" android:background="#drawable/shape_border" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <!-- Image itself: fits the border view, a margin serves as a border width; the key point here - is a background shape which will clip the view to its forms. --> <ImageView android:id="#+id/iv_image" android:layout_width="0dp" android:layout_height="0dp" android:layout_margin="4dp" android:background="#drawable/shape_oval" android:src="#mipmap/ic_launcher" app:layout_constraintBottom_toBottomOf="#+id/v_border" app:layout_constraintEnd_toEndOf="#+id/v_border" app:layout_constraintStart_toStartOf="#+id/v_border" app:layout_constraintTop_toTopOf="#+id/v_border" /> </androidx.constraintlayout.widget.ConstraintLayout> And here are our shape_border drawable: <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="#FF00FF" /> </shape> And shape_oval drawable: <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" /> The only thing you should do in the code - is to enable clipToOutline property: binding.ivImage.clipToOutline = true And of course you can avoid even this line of the code with some BindingAdapter.
This is a relatively old question, but you can just make a circle border in the drawable folder (let's assume the xml file will be called circle_border) <?xml version="1.0" encoding="utf-8"?> <shape xmlns="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="#android:color/transparent" /> <!-- If you want a padding --> <padding android:top="4dp" android:left="4dp" android:right="4dp" android:bottom="4dp" /> <!-- If you want the circle border to have a color --> <strong android:width="1dp" android:color="#FFFFFF" /> </shape> Then you can use it as the background of the ImageView <ImageView android:background="#drawable/circle_border" <!-- other attributes here --> />
just use this simple code: First add dependency : implementation 'de.hdodenhof:circleimageview:2.2.0' then add in xml layout the following code:- <de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto" android:id="#+id/Imgshaligram" android:layout_width="96dp" android:layout_height="96dp" android:src="#drawable/shaligram" app:civ_border_color="#d1b1b1" android:foregroundGravity="center"/>
Is there a way to implement rounded corners to a Mapfragment?
I want to give the map a nice looking rounded corners as the two boxes below it have. I can't do it with the map fragment it self because there is not a background property to a fragment. setting the map inside a layout and setting it background to a rounded shape didn't help me as well and this is the result: I could merge the map but this would make it smaller and i would like to avoid it. EDIT: #Ryan this is the new result #2: I guess this is not bad, no even close to the corners on the other boxes, but still not bad with a little more work a could get somewhere close i just dont have a normal image editor. but one thing that still bothers me now is the separation between the "Location" Textview and the map it's self. could i painted the patch in other way so that there was now distance? this is how i did it: Well I have finally figured this out: this is what i used for the patch: Thanks.
I know it's an old post, but you can try using Cards like so: <android.support.v7.widget.CardView android:layout_width="300dp" android:layout_height="350dp" android:layout_gravity="center_horizontal|center_vertical" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="20dp" app:cardCornerRadius="12dp" app:cardElevation="12dp"> <fragment android:id="#+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="match_parent" /> </android.support.v7.widget.CardView>
I haven't tried this, but I'd put a view with rounded corners and a transparent middle on top of the mapView / mapFragment. That is, put the mapFragment and the rounded corner view in a FrameLayout with both filling the FrameLayout, then make the middle of the rounded corner view transparent. For further clarification, you could do it in a layout as follows:- <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <fragment xmlns:map="http://schemas.android.com/apk/res-auto" android:id="#+id/mapFragment" android:layout_width="match_parent" android:layout_height="match_parent" class="com.google.android.gms.maps.MapFragment" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#drawable/rounded_background" android:orientation="vertical" > </LinearLayout> </FrameLayout> The rounded_background is a 9-patch with rounded corners and a transparent middle. E.g. Hope that helps, Ryan
The easiest way is to wrap the map fragment inside a FrameLayout along with an ImageView. The Imageview would display a rounded rectangle on top of the map fragment. In its simplest form you will see the map fragment inside the rounded rectangle with its corners sticking out of the rounded rectangle because the map view itself is not rounded. To overcome this visual oddity simply apply a layout_margin value on map fragment. The value should be equal to the rectangle's border width. <FrameLayout android:id="#+id/map_container" android:layout_width="wrap_content" android:layout_height="340dp" > <fragment android:id="#+id/map" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="3dp" android:name="com.google.android.gms.maps.SupportMapFragment"/> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="#drawable/map_bg_box" /> </FrameLayout> The rectangle drawable is defined as an xml shape as below <?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <stroke android:width="3dp" android:color="#ff000000" /> <corners android:bottomRightRadius="7dp" android:bottomLeftRadius="7dp" android:topLeftRadius="7dp" android:topRightRadius="7dp"/> </shape> Notice the stroke width of the rectangle is 3dp that is exactly the same value we applied to the layout_margin property of the map fragment. The result is a nicely round cornered map fragment as shown in the screenshot below
Wrap the map fragment in this layout: package com.example.yourpackage; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.util.AttributeSet; import android.widget.RelativeLayout; /** * Just extend any Layout you like/need */ public class RoundedLayout extends RelativeLayout { private Path mPathCorners = new Path(); private Path mPathCircle = new Path(); private float mCornerRadius; /** * border path */ private Path mPathCornersBorder = new Path(); private Path mPathCircleBorder = new Path(); private int mBorderWidth = 0; private int mBorderHalf; private boolean mShowBorder = false; private int mBorderColor = 0xFFFF7700; private float mDensity = 1.0f; /** * Rounded corners or circle shape */ private boolean mIsCircleShape = false; private Paint mPaint = new Paint(); private float dpFromPx(final float px) { return px / mDensity; } private float pxFromDp(final float dp) { return dp * mDensity; } public RoundedLayout(Context context) { this(context, null); } public RoundedLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RoundedLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mDensity = getResources().getDisplayMetrics().density; // just a default for corner radius mCornerRadius = pxFromDp(25f); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.STROKE); mPaint.setColor(mBorderColor); setBorderWidth(Math.round(pxFromDp(2f))); } /** * Switch to circle or rectangle shape * * #param useCircle */ public void setShapeCircle(boolean useCircle) { mIsCircleShape = useCircle; invalidate(); } /** * change corner radius * * #param radius */ public void setCornerRadius(int radius) { mCornerRadius = radius; invalidate(); } public void showBorder(boolean show) { mShowBorder = show; invalidate(); } public void setBorderWidth(int width) { mBorderWidth = width; mBorderHalf = Math.round(mBorderWidth / 2); if (mBorderHalf == 0) { mBorderHalf = 1; } mPaint.setStrokeWidth(mBorderWidth); updateCircleBorder(); updateRectangleBorder(); invalidate(); } public void setBorderColor(int color) { mBorderColor = color; mPaint.setColor(color); invalidate(); } // helper reusable vars, just IGNORE private float halfWidth, halfHeight, centerX, centerY; private RectF rect = new RectF(0, 0, 0, 0); private RectF rectBorder = new RectF(0, 0, 0, 0); #Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); // just calculate both shapes, is not heavy // rounded corners path rect.left = 0; rect.top = 0; rect.right = w; rect.bottom = h; mPathCorners.reset(); mPathCorners.addRoundRect(rect, mCornerRadius, mCornerRadius, Path.Direction.CW); mPathCorners.close(); // circle path halfWidth = w / 2f; halfHeight = h / 2f; centerX = halfWidth; centerY = halfHeight; mPathCircle.reset(); mPathCircle.addCircle(centerX, centerY, Math.min(halfWidth, halfHeight), Path.Direction.CW); mPathCircle.close(); updateRectangleBorder(); updateCircleBorder(); } // helper reusable var, just IGNORE private int save; #Override protected void dispatchDraw(Canvas canvas) { save = canvas.save(); canvas.clipPath(mIsCircleShape ? mPathCircle : mPathCorners); super.dispatchDraw(canvas); canvas.restoreToCount(save); if (mShowBorder) { canvas.drawPath(mIsCircleShape ? mPathCircleBorder : mPathCornersBorder, mPaint); } } private void updateCircleBorder() { // border path for circle mPathCircleBorder.reset(); mPathCircleBorder.addCircle(centerX, centerY, Math.min(halfWidth - mBorderHalf, halfHeight - mBorderHalf), Path.Direction.CW); mPathCircleBorder.close(); } private void updateRectangleBorder() { // border path for rectangle rectBorder.left = rect.left + mBorderHalf; rectBorder.top = rect.top + mBorderHalf; rectBorder.right = rect.right - mBorderHalf; rectBorder.bottom = rect.bottom - mBorderHalf; mPathCornersBorder.reset(); mPathCornersBorder.addRoundRect(rectBorder, mCornerRadius - mBorderHalf, mCornerRadius - mBorderHalf, Path.Direction.CW); mPathCornersBorder.close(); } } In layout will be like this: <com.example.yourpackage.RoundedLayout android:id="#+id/maplayout" android:layout_width="match_parent" android:layout_height="200dp" android:layout_margin="20dp"> <fragment android:id="#+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="200dp" tools:context="com.example.yourpackage.MapsMarkerActivity"/> </com.example.yourpackage.RoundedLayout> In code can be like this for a round shape with border: RoundedLayout rl = (RoundedLayout) findViewById(R.id.maplayout); rl.setShapeCircle(true); rl.showBorder(true); rl.setBorderWidth(2); This layout can be used to shape any view. It's incredible how google is incapable of making competent (usable) complete demos for it's android API.
For other people looking into this, I just tackled this using GoogleMap.snapshot and manipulating the bitmap result with this stack over flow answer: How to make an ImageView with rounded corners? Mind you this is only valid if you are going to have a static map that is not going to be interacted with. Make sure you take the snap shot after the map is loaded. I updated the image view helper code to draw with path to support rounding only some corners. ie. If you want to round only 2 of the corners. You just need the path round rect function that takes a float[] I show a progress bar until I get a callback from GoogleMap loaded listener than I take the snapshot. If you take your snapshot too early you will get can't create bitmap with 0 width and height error. Hope this helps someone looking for rounded corners or other weird shape in static map snapshot.
If you are only trying to target API 21 (Lollipop) and higher This is the easiest way possible. parentView.setClipToOutline(true); Result
Following #Nouman_Hanif post I ended up with a solution that looks quite good. map_rounded_corner_overlay.xml: <?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <stroke android:width="1dp" android:color="#color/white" /> <corners android:radius="<your_desired_view_corner_radius>"/> </shape> My map xml file: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="#+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_margin="1dp" android:layout_width="match_parent" android:layout_height="match_parent" /> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="#drawable/map_rounded_corner_overlay" /> </RelativeLayout>