Sunday, October 19, 2014

Android Custom Shape Imageview | Rounded Image View in Android | Circuler ImageView in Android | Oval Image View in Android | Triangle Imageview in Android | Hexagonal Shape Imageview in Android

Hello Friend,

Today I am sharing an article for custom shape image-view in android using canvas. There is no library needed, using canvas you can make any type of shape with simple java code. You can make any shape like- circle, oval, triangle, Hexagonal or any thing else. Below is the code copy to them according to your need.





1)MainActivity.java-

package com.androidhub4you.crop;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ImageView;

public class MainActivity extends Activity {
      
       private ImageView imageViewRound;
       private ImageView imageViewOval;
       private ImageView imageViewTriangle;
       private ImageView imageViewHexaGon;

       @Override
       protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              imageViewRound=(ImageView)findViewById(R.id.imageView_round);
              imageViewOval=(ImageView)findViewById(R.id.imageView_oval);
              imageViewTriangle=(ImageView)findViewById(R.id.imageView_triangle);
              imageViewHexaGon=(ImageView)findViewById(R.id.imageView_hexagon);
             
              Bitmap icon = BitmapFactory.decodeResource(getResources(),R.drawable.pic1);
             
              imageViewRound.setImageBitmap(icon);
              imageViewOval.setImageBitmap(icon);
              imageViewTriangle.setImageBitmap(icon);
              imageViewHexaGon.setImageBitmap(icon);
             
             
       }


      
}


2)activity_main.xml-

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <com.androidhub4you.crop.RoundedImageView
        android:id="@+id/imageView_round"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginTop="15dp"
        android:src="@drawable/ic_launcher" />

    <com.androidhub4you.crop.OvalImageView
        android:id="@+id/imageView_oval"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginTop="15dp"
        android:src="@drawable/ic_launcher" />

    <com.androidhub4you.crop.TriangleImageView
        android:id="@+id/imageView_triangle"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginTop="15dp"
        android:src="@drawable/ic_launcher" />

    <com.androidhub4you.crop.HexagonImageView
        android:id="@+id/imageView_hexagon"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginTop="15dp"
        android:src="@drawable/ic_launcher" />

</LinearLayout>

Circle Shape:

package com.androidhub4you.crop;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

public class RoundedImageView extends ImageView {

       public RoundedImageView(Context ctx, AttributeSet attrs) {
              super(ctx, attrs);
       }

       @Override
       protected void onDraw(Canvas canvas) {

              Drawable drawable = getDrawable();

              if (drawable == null) {
                     return;
              }

              if (getWidth() == 0 || getHeight() == 0) {
                     return;
              }
              Bitmap b = ((BitmapDrawable) drawable).getBitmap();
              Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

              int w = getWidth(), h = getHeight();

              Bitmap roundBitmap = getRoundedCroppedBitmap(bitmap, w);
              canvas.drawBitmap(roundBitmap, 0, 0, null);

       }

       public static Bitmap getRoundedCroppedBitmap(Bitmap bitmap, int radius) {
              Bitmap finalBitmap;
              if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
                     finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
                                  false);
              else
                     finalBitmap = bitmap;
              Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
                           finalBitmap.getHeight(), Config.ARGB_8888);
              Canvas canvas = new Canvas(output);

              final Paint paint = new Paint();
              final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
                           finalBitmap.getHeight());

              paint.setAntiAlias(true);
              paint.setFilterBitmap(true);
              paint.setDither(true);
              canvas.drawARGB(0, 0, 0, 0);
              paint.setColor(Color.parseColor("#BAB399"));
              canvas.drawCircle(finalBitmap.getWidth() / 2 + 0.7f,
                           finalBitmap.getHeight() / 2 + 0.7f,
                           finalBitmap.getWidth() / 2 + 0.1f, paint);
              paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
              canvas.drawBitmap(finalBitmap, rect, rect, paint);

              return output;
       }

}

Oval Shape:

package com.androidhub4you.crop;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

public class OvalImageView extends ImageView {

       public OvalImageView(Context ctx, AttributeSet attrs) {
              super(ctx, attrs);
       }

       @Override
       protected void onDraw(Canvas canvas) {

              Drawable drawable = getDrawable();

              if (drawable == null) {
                     return;
              }

              if (getWidth() == 0 || getHeight() == 0) {
                     return;
              }
              Bitmap b = ((BitmapDrawable) drawable).getBitmap();
              Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

              int w = getWidth(), h = getHeight();

              Bitmap roundBitmap = getOvalCroppedBitmap(bitmap, w);
              canvas.drawBitmap(roundBitmap, 0, 0, null);

       }

       public static Bitmap getOvalCroppedBitmap(Bitmap bitmap, int radius) {
              Bitmap finalBitmap;
              if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
                     finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
                                  false);
              else
                     finalBitmap = bitmap;
              Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
                           finalBitmap.getHeight(), Config.ARGB_8888);
              Canvas canvas = new Canvas(output);

              Paint paint = new Paint();
              final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
                           finalBitmap.getHeight());

              paint.setAntiAlias(true);
              paint.setFilterBitmap(true);
              paint.setDither(true);
              canvas.drawARGB(0, 0, 0, 0);
              paint.setColor(Color.parseColor("#BAB399"));
              RectF oval = new RectF(0, 0, 130, 150);
              canvas.drawOval(oval, paint);
              paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
              canvas.drawBitmap(finalBitmap, rect, oval, paint);

              return output;
       }

}

Triangle Shape:

package com.androidhub4you.crop;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

public class TriangleImageView extends ImageView {

       public TriangleImageView(Context ctx, AttributeSet attrs) {
              super(ctx, attrs);
       }

       @Override
       protected void onDraw(Canvas canvas) {

              Drawable drawable = getDrawable();

              if (drawable == null) {
                     return;
              }

              if (getWidth() == 0 || getHeight() == 0) {
                     return;
              }
              Bitmap b = ((BitmapDrawable) drawable).getBitmap();
              Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

              int w = getWidth(), h = getHeight();

              Bitmap roundBitmap = getRoundedCroppedBitmap(bitmap, w);
              canvas.drawBitmap(roundBitmap, 0, 0, null);

       }

       public static Bitmap getRoundedCroppedBitmap(Bitmap bitmap, int radius) {
              Bitmap finalBitmap;
              if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
                     finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
                                  false);
              else
                     finalBitmap = bitmap;
              Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
                           finalBitmap.getHeight(), Config.ARGB_8888);
              Canvas canvas = new Canvas(output);

              Paint paint = new Paint();
              final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
                           finalBitmap.getHeight());

              Point point1_draw = new Point(75, 0);
              Point point2_draw = new Point(0, 180);
              Point point3_draw = new Point(180, 180);

              Path path = new Path();
              path.moveTo(point1_draw.x, point1_draw.y);
              path.lineTo(point2_draw.x, point2_draw.y);
              path.lineTo(point3_draw.x, point3_draw.y);
              path.lineTo(point1_draw.x, point1_draw.y);
              path.close();
              canvas.drawARGB(0, 0, 0, 0);
              paint.setColor(Color.parseColor("#BAB399"));
              canvas.drawPath(path, paint);
              paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
              canvas.drawBitmap(finalBitmap, rect, rect, paint);

              return output;
       }

}

Hexagonal Shape:

package com.androidhub4you.crop;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;

public class HexagonImageView extends ImageView {

       public HexagonImageView(Context ctx, AttributeSet attrs) {
              super(ctx, attrs);
       }

       @Override
       protected void onDraw(Canvas canvas) {

              Drawable drawable = getDrawable();

              if (drawable == null) {
                     return;
              }

              if (getWidth() == 0 || getHeight() == 0) {
                     return;
              }
              Bitmap b = ((BitmapDrawable) drawable).getBitmap();
              Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

              int w = getWidth(), h = getHeight();

              Bitmap roundBitmap = getRoundedCroppedBitmap(bitmap, w);
              canvas.drawBitmap(roundBitmap, 0, 0, null);

       }

       public static Bitmap getRoundedCroppedBitmap(Bitmap bitmap, int radius) {
              Bitmap finalBitmap;
              if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
                     finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
                                  false);
              else
                     finalBitmap = bitmap;
              Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
                           finalBitmap.getHeight(), Config.ARGB_8888);
              Canvas canvas = new Canvas(output);

              Paint paint = new Paint();
              final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
                           finalBitmap.getHeight());

              Point point1_draw = new Point(75, 0);
              Point point2_draw = new Point(0, 50);
              Point point3_draw = new Point(0, 100);
              Point point4_draw = new Point(75, 150);
              Point point5_draw = new Point(150, 100);
              Point point6_draw = new Point(150, 50);

              Path path = new Path();
              path.moveTo(point1_draw.x, point1_draw.y);
              path.lineTo(point2_draw.x, point2_draw.y);
              path.lineTo(point3_draw.x, point3_draw.y);
              path.lineTo(point4_draw.x, point4_draw.y);
              path.lineTo(point5_draw.x, point5_draw.y);
              path.lineTo(point6_draw.x, point6_draw.y);

              path.close();
              canvas.drawARGB(0, 0, 0, 0);
              paint.setColor(Color.parseColor("#BAB399"));
              canvas.drawPath(path, paint);
              paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
              canvas.drawBitmap(finalBitmap, rect, rect, paint);

              return output;
       }

}


For more help or suggestion post your comment.

Thanks,
Manish



66 comments:

  1. This demo "ok" for static image view.
    But my Requirement is: Create dynamic "Circular ImageView" and image Load from URL.
    Please any idea regarding this then help me,
    Thanks.

    ReplyDelete
    Replies
    1. So just use above code for your dynamic image. Just use above canvas for your row.xml for imageview.

      Delete
    2. please give the code for dynamic image..How to use it in Recyclerview

      Delete
    3. Extend the custome image view with NetworkImageView of volley library

      Delete
  2. how do i compress and expand an image with fingers , android code pls..?

    ReplyDelete
  3. i mean resizing an image with fingers without affecting image quality , android code

    ReplyDelete
  4. thank you so much .. but I seem to have a problem displaying the image.. all of the shapes displays in half. like the circle shape imageview it only display half of the image and the other half is nothing.. it seems like the image is moved towards the left side.. can you help me please

    ReplyDelete
    Replies
    1. I am not sure what going on with your case, may be source image size is big and your image-view size is very less compare to original image. you can re-size your image using Bitmap method before displaying to them into image-view something like-
      Bitmap bitmap = Bitmap.createScaledBitmap(sourceImage, width, height, true);

      Delete
  5. Thank you very very much Manish, well Done!!!!

    ReplyDelete
  6. plz tell me a how set otp in android project that means ONE TIME PSSWORD in installing time or CALL SERViCES

    ReplyDelete
  7. Thanks a lot Manish!!! Your code just helped me a lot! :D

    ReplyDelete
  8. Hai Manish It's Superb Tutorial ....
    I need the circle as Full layout(Big Circle)....
    In this u r showing small circle..
    For that what can i do...?
    Plsss Reply me...

    ReplyDelete
  9. Hi manish thanks for posting this good tutorial, actually i am facing a problem like if i increase the width and height of the image view the actual image ill not showing in the imageview so please guide me to overcome from this issue.
    Thanks in advance...

    ReplyDelete
  10. This tutorial worked so smoothly....thanx a lot.

    ReplyDelete
  11. what is the library of roundimage to build?

    ReplyDelete
  12. wow!!!! you are great man .... thanks dude....

    ReplyDelete
  13. i m new to android ... u made classes for shapes but where did u instantiate classes in main activity ????

    ReplyDelete
    Replies
    1. Please check activity_main.xml, I am using that shape as VIEW with package name.

      Delete
  14. Please check activity_main.xml, I am using that shape as VIEW with package name.

    <com.androidhub4you.crop.RoundedImageView

    Got it?

    ReplyDelete
  15. can you please tell me how to create heart shape Image View

    ReplyDelete
    Replies
    1. I don't think Java have shape for heart. You can achieve it using SVG file, please Google for it.

      Delete
    2. This comment has been removed by the author.

      Delete
    3. Hi
      Can u please tell me hw to draw a semi circle imageView.

      Delete
  16. Hi
    Can u please tell me hw to draw a semi circle imageView.

    Read more: http://www.androidhub4you.com/2014/10/android-custom-shape-imageview-rounded.html#ixzz3sUbVWAsk

    ReplyDelete
  17. This comment has been removed by the author.

    ReplyDelete
  18. This comment has been removed by the author.

    ReplyDelete
  19. I'm using images dynamically from an object, and the image still being a square. I did:

    A class that inherits from Image View.
    In my adapter I use Image View in the row line
    And in the XML file I put the package of the class

    Can you help me pls?

    ReplyDelete
    Replies
    1. Did you try this demo? Well try below step-

      1)In Your Activity class just pass the list of data
      2)In Adapter class load the row.xml and your adapter must extend Base Adapter.
      3)in your row.xml use the canvas of shape like- com.manish.MyCustomShape.

      That's all.

      Delete
    2. Thank you for your answer, I have a question, I'm using images with extension .jpg instead of .png, it has something to do? Other thing is this line in your activity: Bitmap icon = BitmapFactory.decodeResource(getResources(),R.drawable.pic1); I don't use that line. In my adapter, I set a background drawable to the Image View.

      I don't know if for that reason it still not working

      Delete
    3. The line that I ignore is the key. Thank you too much for your tutorial. It's easy, and without other libraries , I love it

      Delete
  20. What about the square image ? i can't find the square.java file can you please send me this code?

    ReplyDelete
    Replies
    1. Why you need square image shape? Android res provide us square shape so we don't need canvas. well you can create shape too it is not much tough. You can get code for that on stackoverflow.

      Delete
  21. your image static but not dynamic use .so please idea for dynamic image use

    ReplyDelete
    Replies
    1. 1)If you are trying to display in list-view then inside base adapter convert your image URL to bitmap using lazy loading and set it on your image-view.

      2)If you have 1 image inside activity then just convert it into Bitmap and set on your ImageView.

      Delete
  22. your code is work fine when i added a button for taking gallery image before that app is crashing.plz help me sort out this problem.

    ReplyDelete
  23. Thanks a lot for this code it's really works good. But I have one problem image is compressed inside the imageview, height is ok but but width is compressed. I changed the valued of getwidth in the class but there is no correction. Thanks

    ReplyDelete
    Replies
    1. I think you are using a big size of image to set into small size of imageView. So solution is before setting into imageView resize your image. you will find code to resize image on stackoverflow. Some thing like height/4, width/4.

      Delete
  24. Thanks, I am sure you are righte I'll see how can I fix it.

    ReplyDelete
  25. please provide the dependencies

    ReplyDelete
    Replies
    1. This project have no dependencies, just copy the canvas file and call inside your layout with package name.

      Delete
  26. hey thanks this is awesome, I do have one question (I'm a little new to custom views in android). My image is getting squished when i input it, is there a way to have the view not resize the image and instead just trim off the corners (very similar to what happens in html when you use border-radius)

    Thanks!

    ReplyDelete
  27. Hey I tried above code i am getting NullPointerException on line
    Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

    can you help me to get out of this problem.

    Thanxs.

    ReplyDelete
    Replies
    1. Just make null check-

      if(bitmap!=null){
      //only then go inside
      Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

      }

      Delete
  28. This comment has been removed by the author.

    ReplyDelete
  29. Actual problem was from here
    Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.mickeymouse);

    I am not able to use getResources() function because I have created a custom adapter and extending ArrayAdapter.

    Please help me with solution.

    Thanking you.

    ReplyDelete
    Replies
    1. I am not sure where is problem, just pass the context and we have it inside our canvas-
      public TriangleImageView(Context ctx, AttributeSet attrs) {
      super(ctx, attrs);
      }

      so from there you can use context something like this-
      ctx.getResources().

      or you can create a global variable too like-
      on top-
      Context context;
      and inside constructor-
      this.contex=ctx;

      and use this contex with getResoucres().

      Delete
  30. This comment has been removed by the author.

    ReplyDelete
  31. This comment has been removed by the author.

    ReplyDelete
  32. I have tried it but what is "pic1" on this line
    -> Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.pic1);
    It will show cannot resolve the symbol pic1

    ReplyDelete
  33. Hello, first, thanks for the tutorial. I have a question, why you copy the original bitmap? this step is necesary? You can explain me please? Thanks

    ReplyDelete
  34. baki sab theeek hai, ye batao ke custom view ke bahar border kaise denge.

    ReplyDelete