ShapableImageView in Android: Make Circular Image Border

Do you rely on external libraries to draw shapes on your ImageView ? Well now there is ShapableImageView in Android to facilitate just that.

But the best part is that you don’t need to use the circular image view libraries.

What is ShapableImageView in Android ?

ShapableImageView in Android is a subclass of ImageView that supports custom shapes. Such as circular frame or rounded corners.

Sure, you can achieve that by just wrapping the ImageView inside a CardView. But here we will look at using the ShapableImageView‘s API.

It was introduced in material design library version 1.2. And it provides a rather convenient way to do things.

We will look at what shapes we can create using ShapableImageView. And we will also look at problems and their solutions using in ShapableImageView.

You must also include this library in the dependencies

// update the version if gradle suggests you to 
implementation 'com.google.android.material:material:1.2.1'Code language: JavaScript (javascript)

Styling Attributes in ShapableImageView

Before we move on let us see what do we need to style our view.

We must know that there are exactly 2 ways to do things. One is through Java/Kotlin and the other is through XML.

Here I will described about the XML way. And later we will look into the programmatic way.

Step 1: We must create a style in styles.xml or theme.xml.

<style name="ShapeAppearance.CircularBorder" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">50%</item>
</style>Code language: HTML, XML (xml)

If we look at the snippet above. We can see the cornerFamily and cornerSize attribute.

cornerFamily has only two values rounded and cut. And,

cornerSize takes in the dp unit like: 8dp, 20dp, etc. And the variations are cornerSizeTopLeft, cornerSizeTopRight, cornerSizeBottomLeft, cornerSizeBottomRight.

And it adjusts the roundness of each of the corners.

Now that we have understood what we need let us move on with our goal.

Circular Border for Image

Our resulting UI will look like below. Focus on the Image only.

ShapableImageView Android

To create a circular border add the snippet in your styles.xml or themes.xml. Change the percentage to see how the border changes.

<style name="ShapeAppearance.CircularBorder" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">50%</item>
</style>Code language: HTML, XML (xml)

And add the following ShapableImageView in your layout.

<com.google.android.material.imageview.ShapeableImageView
    android:id="@+id/siv"
    android:layout_width="64dp"
    android:layout_height="64dp"
    android:layout_marginTop="32dp"
    android:scaleType="fitCenter"
    android:src="@drawable/my_bell_icon"
    app:shapeAppearanceOverlay="@style/ShapeAppearance.CircularBorder"
    app:strokeColor="@color/colorPrimaryDark"
    app:strokeWidth="2dp" />Code language: HTML, XML (xml)

From the code snippet about we can see these attributes stand out

  1. app:shapeAppearanceOverlay is how we change the shape. So, in our case it is @style/ShapeAppearance.CircularBorder.
  2. app:strokeColor is for adding the border color. And,
  3. app:strokeWidth is for the width of the border.

Now there is a problem with our output, the image has no space with the border. We will look at this later on in the post.

Diamond Cut Border for Image

The output of cut corner style is shown below

Just like in the style above we have to declare the style with cornerFamily cut.

<style name="ShapeAppearance.CutBorder" parent="">
    <item name="cornerFamily">cut</item>
    <item name="cornerSize">50%</item>
</style>Code language: HTML, XML (xml)
  • 50% will produce a diamond like shape.
  • 25% will produce a octagonal shape.

And the code for our layout will stay same except for the name of app:shapeAppearanceOverlay.

<com.google.android.material.imageview.ShapeableImageView
    android:id="@+id/siv"
    android:layout_width="64dp"
    android:layout_height="64dp"
    android:layout_marginTop="32dp"
    android:scaleType="fitCenter"
    android:src="@drawable/my_bell_icon"
    app:shapeAppearanceOverlay="@style/ShapeAppearance.CutBorder"
    app:strokeColor="@color/colorPrimaryDark"
    app:strokeWidth="2dp" />Code language: HTML, XML (xml)

Now we have completed the basic styling for our ShapableImageView. Let us look at the main problem in each of the example above.

Padding issue with ShapableImageView

If we see closely with the image above we can see that there is no space between the border and the image. This can look really not clean in certain situations.

Let us try adding the padding attribute to the ShapableImageView to solve this.

After adding the output is exactly same except the image has reduced in size. So, clearly setting padding to the layout doesn’t solve the issue.

Whats the solution then ?

Well it’s pretty easy, we have to create a custom inset drawable. Create a new resource file in the drawable directory.

<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_bell"
    android:inset="8dp" />Code language: HTML, XML (xml)
  • android:drawable is where you actual image will be referenced
  • android:inset is just like android:padding put in a dp value

After creating the new drawable resource. We have to use it instead of the actual image like below

android:src="@drawable/inset_draw"Code language: JavaScript (javascript)

Which was before

android:src="@drawable/my_bell_icon"Code language: JavaScript (javascript)

And the out put of the adjustments is like below.

It’s almost perfect but there’s still a little problem. Can you see it ?

Cutting Side Issue in ShapableImageView Android

If you look closely you can see the ShapableImageView has a bit of our border cut off at each side.

Let us solve that issue too. It’s really simple. We just have to use the padding in our layout. And the value must be half of app:strokeWidth.

In the above examples we can see we have 2dp width of stroke. So let us include padding of 1dp in our layout.

As you can see the issue is now gone. If it doesn’t resolve you can try increasing the padding with practical units.

Why did the cut happen ? It’s in the way the ImageView draws the mentioned drawable.

I hope you liked the implementation, be sure to bookmark and visit often for new tutorials.

Related Posts

Android Content URI: How to Get the File URI

Show or Hide Soft Keyboard in Android Application And More

Android Notification Manager: Create Notification in Android

Android Room For Database: Learn SQLite Persistence Library

Related Posts