Open In App

How to Implement Shapeable ImageView in Android?

Last Updated : 20 Dec, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

In Android, ShapeableImageView is used to change the shape of your image to circle, diamond, etc. Also, you can set a corner radius to your ImageView. You can do much more by using this ShapeableImageView with minimal code. So in this article, we are going to make a ShapableImageView in android. By implementing this application we will get a basic idea of how editing of photos is done in android applications. Here we will implement two features i.e to cut or round the corners of an image.

What we are going to build in this article?

Here we will be using two images, one image we will edit with XML code and the other with java code. Using SeekBar the user can round or cut all four corners of the image separately. Note that we are going to implement this application using Java language. A sample video is given below to get an idea about what we are going to do in this article.

Step by Step Implementation

Step 1: Creating a new project

  • Open a new project.
  • We will be working on Empty Activity with language as Java. Leave all other options unchanged.
  • You can change the name of the project at your convenience.
  • There will be two default files named activity_main.xml and MainActivity.java.

If you don’t know how to create a new project in Android Studio then you can refer to How to Create/Start a New Project in Android Studio? 

Step 2: Adding the required dependency

Open Gradle Scripts > build.gradle(module). Go to app > right click > open module settings > dependencies > Add dependency > Library dependency.

Type material in the search bar and click on search. Select the dependency shown in the below image-

Click on sync now to save the changes.

Step 3: Working with the activity_main.xml file

Navigate to the app > res > layout > activity_main.xml and add the below code to that file. Below is the code for the activity_main.xml file. 

XML




<?xml version="1.0" encoding="utf-8"?>
  
<!-- Linear layout as parent layout-->
<LinearLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp"
    android:gravity="center"
    tools:context=".MainActivity">
  
      <!-- text view to show the text "using xml"-->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Using xml"
        android:textStyle="bold"
        android:textSize="20sp"
        android:padding="12dp"
        />
  
      <!-- shapable image view-->
    <com.google.android.material.imageview.ShapeableImageView
        android:layout_width="339dp"
        android:layout_height="230dp"
        android:adjustViewBounds="true"
        android:scaleType="centerCrop"
        android:src="@drawable/gfg"
        app:shapeAppearance="@style/CornerCut" />
    
      <!-- text view to show the text "using java"-->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Using Java"
        android:textSize="20sp"
        android:textStyle="bold"
        android:padding="12dp"
        />
    
     <!-- shapable image view-->
    <com.google.android.material.imageview.ShapeableImageView
        android:layout_width="339dp"
        android:layout_height="230dp"
        android:layout_weight="1"
        android:id="@+id/image_View"
        android:src="@drawable/gfg"
        android:adjustViewBounds="true"
        android:scaleType="centerCrop"
        />
    
      <!-- spinner to provide options of round and cur-->
    <Spinner
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/sp_family"
        android:padding="12dp"
        android:layout_marginTop="16dp"
        />
    
      <!-- seekbar for top left corner-->
    <SeekBar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/sb_top_left"
        android:layout_marginTop="16dp"
        />
    
      <!-- seekbar for top right corner-->
    <SeekBar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/sb_top_right"
        android:layout_marginTop="8dp"
        />
    
      <!-- seekbar for bottom left corner-->
    <SeekBar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/sb_bottom_left"
        android:layout_marginTop="8dp"
        />
    
      <!-- seekbar for bottom right corner-->
    <SeekBar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/sb_bottom_right"
        android:layout_marginTop="8dp"
        />
  
</LinearLayout>


Step 4: Working on themes.xml file

Navigate to res > values > themes > themes.xml file and use the below code in it.

XML




<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.ShapableImageView" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
    </style>
      
    <style name="CornerCut" parent="">
        <item name="cornerFamilyTopLeft">rounded</item>
        <item name="cornerFamilyTopRight">cut</item>
        <item name="cornerFamilyBottomLeft">cut</item>
        <item name="cornerFamilyBottomRight">rounded</item>
        <item name="cornerSizeTopLeft">50%</item>
        <item name="cornerSizeTopRight">25%</item>
        <item name="cornerSizeBottomLeft">25%</item>
        <item name="cornerSizeBottomRight">50%</item>
  
    </style>
</resources>


After executing the above code design of the activity_main.xml file looks like this.

Step 5: Working with the MainActivity.java file

Go to the MainActivity.java file and refer to the following code. Below is the code for the MainActivity.java file. Comments are added inside the code to understand the code in more detail.

Java




package com.example.shapableimageview;
  
import androidx.appcompat.app.AppCompatActivity;
  
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.SeekBar;
import android.widget.Spinner;
  
import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.shape.CornerFamily;
  
import java.util.ArrayList;
  
public class MainActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener {
  
    // Initialize variable
    ShapeableImageView imageView;
    Spinner spFamily;
    SeekBar sbTopLeft,sbTopRight,sbBottomLeft,sbBottomRight;
    int cornerFamily= CornerFamily.CUT,topLeft=0,topRight=0,bottomLeft=0,bottomRight=0;
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
  
        // assign variable
        imageView=findViewById(R.id.image_View);
        spFamily=findViewById(R.id.sp_family);
        sbTopLeft=findViewById(R.id.sb_top_left);
        sbTopRight=findViewById(R.id.sb_top_right);
        sbBottomLeft=findViewById(R.id.sb_bottom_left);
        sbBottomRight=findViewById(R.id.sb_bottom_right);
  
        // Initialize array list
        ArrayList<String> arrayList=new ArrayList<>();
          
        // add values in array List
        arrayList.add("cut");
        arrayList.add("rounded");
  
        // set adapter
        spFamily.setAdapter(new ArrayAdapter<>(MainActivity.this,
                android.R.layout.simple_spinner_dropdown_item,arrayList));
  
        // Set Listener on spinner
        spFamily.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                // check condition
                if(position==0)
                {
                    // when cut selected
                    cornerFamily=CornerFamily.CUT;
                }
                else
                {
                    // when rounded selected
                    cornerFamily=CornerFamily.ROUNDED;
                }
  
                // create update method
                updateImage();
            }
  
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
  
            }
        });
  
        // set listener on all seekbar
        sbTopLeft.setOnSeekBarChangeListener(this);
        sbTopRight.setOnSeekBarChangeListener(this);
        sbBottomRight.setOnSeekBarChangeListener(this);
        sbBottomLeft.setOnSeekBarChangeListener(this);
    }
  
    private void updateImage() {
        // set appearance
        imageView.setShapeAppearanceModel(imageView.getShapeAppearanceModel().toBuilder()
                .setTopLeftCorner(cornerFamily,topLeft)
                .setTopRightCorner(cornerFamily,topRight)
                .setBottomLeftCorner(cornerFamily,bottomLeft)
                .setBottomRightCorner(cornerFamily,bottomRight)
                .build());
    }
  
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        switch (seekBar.getId())
        {
            case R.id.sb_top_left:
                                    topLeft=progress;
                                    break;
            case R.id.sb_top_right:
                                    topRight=progress;
                                    break;
            case R.id.sb_bottom_left:
                                    bottomLeft=progress;
                                    break;
            case R.id.sb_bottom_right:
                                    bottomRight=progress;
                                    break;
        }
        // call update method
        updateImage();
    }
  
    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
  
    }
  
    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
  
    }
}


Here is the final output of our application.

Output:



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads