Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to give hexagon shape to ImageView

How to give hexagon shape to ImageView . Is it possible to do in same way ? If so then how. If this is not possible through this then how this could be achieved ?

<shape xmlns:android="http//schemas.android.com/apk/res/android"        android:shape="hexagon">   <solid android:color="#ffffffff" />   <size android:width="60dp"         android:height="40dp" /> </shape> 

Screenshot

enter image description here

Here I can't do masking image because I can not detect which portion of bitmap I should crop to get hexagon shape bitmap. So I am looking for the answer to give hexagon shape to ImageView

like image 477
N Sharma Avatar asked Mar 24 '14 04:03

N Sharma


People also ask

What is ImageView code?

Displays image resources, for example Bitmap or Drawable resources. ImageView is also commonly used to apply tints to an image and handle image scaling. To learn more about Drawables, see: Drawable Resources.

What is difference between ImageView and ImageButton?

ImageButton has the same property as ImageView . Only one feature is extra, which is, images set through ImageButton are clickable, and actions can be attached with them upon clicking. Just like a button, the setOnClickListener() can be used to set an event listener for click event on this.


2 Answers

Try this View. You might want to adjust it for your specific needs, but it draws a hexagon mask with a border on top of a view. The background resource goes below the mask.

The result:

enter image description here

The code:

HexagonMaskView.java

import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Path; import android.graphics.Region; import android.util.AttributeSet; import android.view.View;  public class HexagonMaskView extends View {     private Path hexagonPath;     private Path hexagonBorderPath;     private float radius;     private float width, height;     private int maskColor;  public HexagonMaskView(Context context) {     super(context);     init(); }  public HexagonMaskView(Context context, AttributeSet attrs) {     super(context, attrs);     init(); }  public HexagonMaskView(Context context, AttributeSet attrs, int defStyleAttr) {     super(context, attrs, defStyleAttr);     init(); }  private void init() {     hexagonPath = new Path();     hexagonBorderPath = new Path();     maskColor = 0xFF01FF77; }  public void setRadius(float r) {     this.radius = r;     calculatePath(); }  public void setMaskColor(int color) {     this.maskColor = color;     invalidate(); }  private void calculatePath() {     float triangleHeight = (float) (Math.sqrt(3) * radius / 2);     float centerX = width/2;     float centerY = height/2;     hexagonPath.moveTo(centerX, centerY + radius);     hexagonPath.lineTo(centerX - triangleHeight, centerY + radius/2);     hexagonPath.lineTo(centerX - triangleHeight, centerY - radius/2);     hexagonPath.lineTo(centerX, centerY - radius);     hexagonPath.lineTo(centerX + triangleHeight, centerY - radius/2);     hexagonPath.lineTo(centerX + triangleHeight, centerY + radius/2);     hexagonPath.moveTo(centerX, centerY + radius);      float radiusBorder = radius - 5;         float triangleBorderHeight = (float) (Math.sqrt(3) * radiusBorder / 2);     hexagonBorderPath.moveTo(centerX, centerY + radiusBorder);     hexagonBorderPath.lineTo(centerX - triangleBorderHeight, centerY + radiusBorder/2);     hexagonBorderPath.lineTo(centerX - triangleBorderHeight, centerY - radiusBorder/2);     hexagonBorderPath.lineTo(centerX, centerY - radiusBorder);     hexagonBorderPath.lineTo(centerX + triangleBorderHeight, centerY - radiusBorder/2);     hexagonBorderPath.lineTo(centerX + triangleBorderHeight, centerY + radiusBorder/2);     hexagonBorderPath.moveTo(centerX, centerY + radiusBorder);     invalidate(); }  @Override public void onDraw(Canvas c){     super.onDraw(c);     c.clipPath(hexagonBorderPath, Region.Op.DIFFERENCE);     c.drawColor(Color.WHITE);     c.save();     c.clipPath(hexagonPath, Region.Op.DIFFERENCE);     c.drawColor(maskColor);     c.save(); }  // getting the view size and default radius @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){     super.onMeasure(widthMeasureSpec, heightMeasureSpec);     width = MeasureSpec.getSize(widthMeasureSpec);     height =  MeasureSpec.getSize(heightMeasureSpec);     radius = height / 2 - 10;     calculatePath(); } } 

Update 29.07.2016

A better way to only clip the source image without painting the whole view's background. Switched to an ImageView as a base class to benefit from the scaleType. I also did some code refactoring.

import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.Region; import android.util.AttributeSet; import android.widget.ImageView;  public class HexagonMaskView extends ImageView {     private Path hexagonPath;     private Path hexagonBorderPath;     private Paint mBorderPaint;      public HexagonMaskView(Context context) {         super(context);         init();     }      public HexagonMaskView(Context context, AttributeSet attrs) {         super(context, attrs);         init();     }      public HexagonMaskView(Context context, AttributeSet attrs, int defStyleAttr) {         super(context, attrs, defStyleAttr);         init();     }      private void init() {         this.hexagonPath = new Path();         this.hexagonBorderPath = new Path();          this.mBorderPaint = new Paint();         this.mBorderPaint.setColor(Color.WHITE);         this.mBorderPaint.setStrokeCap(Paint.Cap.ROUND);         this.mBorderPaint.setStrokeWidth(50f);         this.mBorderPaint.setStyle(Paint.Style.STROKE);     }      public void setRadius(float radius) {         calculatePath(radius);     }      public void setBorderColor(int color) {         this.mBorderPaint.setColor(color);         invalidate();     }      private void calculatePath(float radius) {         float halfRadius = radius / 2f;         float triangleHeight = (float) (Math.sqrt(3.0) * halfRadius);         float centerX = getMeasuredWidth() / 2f;         float centerY = getMeasuredHeight() / 2f;          this.hexagonPath.reset();         this.hexagonPath.moveTo(centerX, centerY + radius);         this.hexagonPath.lineTo(centerX - triangleHeight, centerY + halfRadius);         this.hexagonPath.lineTo(centerX - triangleHeight, centerY - halfRadius);         this.hexagonPath.lineTo(centerX, centerY - radius);         this.hexagonPath.lineTo(centerX + triangleHeight, centerY - halfRadius);         this.hexagonPath.lineTo(centerX + triangleHeight, centerY + halfRadius);         this.hexagonPath.close();          float radiusBorder = radius - 5f;         float halfRadiusBorder = radiusBorder / 2f;         float triangleBorderHeight = (float) (Math.sqrt(3.0) * halfRadiusBorder);          this.hexagonBorderPath.reset();         this.hexagonBorderPath.moveTo(centerX, centerY + radiusBorder);         this.hexagonBorderPath.lineTo(centerX - triangleBorderHeight, centerY + halfRadiusBorder);         this.hexagonBorderPath.lineTo(centerX - triangleBorderHeight, centerY - halfRadiusBorder);         this.hexagonBorderPath.lineTo(centerX, centerY - radiusBorder);         this.hexagonBorderPath.lineTo(centerX + triangleBorderHeight, centerY - halfRadiusBorder);         this.hexagonBorderPath.lineTo(centerX + triangleBorderHeight, centerY + halfRadiusBorder);         this.hexagonBorderPath.close();         invalidate();     }      @Override     public void onDraw(Canvas c) {         c.drawPath(hexagonBorderPath, mBorderPaint);         c.clipPath(hexagonPath, Region.Op.INTERSECT);         c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);         super.onDraw(c);     }      @Override     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){         super.onMeasure(widthMeasureSpec, heightMeasureSpec);         int width = MeasureSpec.getSize(widthMeasureSpec);         int height = MeasureSpec.getSize(heightMeasureSpec);         setMeasuredDimension(width, height);         calculatePath(Math.min(width / 2f, height / 2f) - 10f);     } } 

Example layout:

<?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"     android:paddingBottom="@dimen/activity_vertical_margin"     android:paddingLeft="@dimen/activity_horizontal_margin"     android:paddingRight="@dimen/activity_horizontal_margin"     android:paddingTop="@dimen/activity_vertical_margin"     android:background="@android:color/holo_green_dark">      <com.scelus.hexagonmaskimproved.HexagonMaskView         android:id="@+id/image"         android:layout_width="match_parent"         android:layout_height="match_parent"         android:src="@drawable/bear"         android:background="@android:color/holo_green_light"/>  </RelativeLayout> 

New result

like image 121
SceLus Avatar answered Sep 28 '22 18:09

SceLus


Here is my working code for this, it supports shadows to:

import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.util.AttributeSet; import android.widget.ImageView;  public class HexagonImageView extends ImageView {      private Path hexagonPath;     private Path hexagonBorderPath;     private float radius;     private Bitmap image;     private int viewWidth;     private int viewHeight;     private Paint paint;     private BitmapShader shader;     private Paint paintBorder;     private int borderWidth = 4;      public HexagonImageView(Context context) {         super(context);         setup();     }      public HexagonImageView(Context context, AttributeSet attrs) {         super(context, attrs);         setup();     }      public HexagonImageView(Context context, AttributeSet attrs, int defStyleAttr) {         super(context, attrs, defStyleAttr);         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, 1.0f, 1.0f, Color.BLACK);          hexagonPath = new Path();         hexagonBorderPath = new Path();     }      public void setRadius(float r) {         this.radius = r;         calculatePath();     }      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 calculatePath() {          float triangleHeight = (float) (Math.sqrt(3) * radius / 2);         float centerX = viewWidth/2;         float centerY = viewHeight/2;          hexagonBorderPath.moveTo(centerX, centerY + radius);         hexagonBorderPath.lineTo(centerX - triangleHeight, centerY + radius/2);         hexagonBorderPath.lineTo(centerX - triangleHeight, centerY - radius/2);         hexagonBorderPath.lineTo(centerX, centerY - radius);         hexagonBorderPath.lineTo(centerX + triangleHeight, centerY - radius/2);         hexagonBorderPath.lineTo(centerX + triangleHeight, centerY + radius/2);         hexagonBorderPath.moveTo(centerX, centerY + radius);          float radiusBorder = radius - borderWidth;             float triangleBorderHeight = (float) (Math.sqrt(3) * radiusBorder / 2);          hexagonPath.moveTo(centerX, centerY + radiusBorder);         hexagonPath.lineTo(centerX - triangleBorderHeight, centerY + radiusBorder/2);         hexagonPath.lineTo(centerX - triangleBorderHeight, centerY - radiusBorder/2);         hexagonPath.lineTo(centerX, centerY - radiusBorder);         hexagonPath.lineTo(centerX + triangleBorderHeight, centerY - radiusBorder/2);         hexagonPath.lineTo(centerX + triangleBorderHeight, centerY + radiusBorder/2);         hexagonPath.moveTo(centerX, centerY + radiusBorder);          invalidate();     }      private void loadBitmap()  {         BitmapDrawable bitmapDrawable = (BitmapDrawable) this.getDrawable();          if (bitmapDrawable != null)             image = bitmapDrawable.getBitmap();     }      @SuppressLint("DrawAllocation")     @Override     public void onDraw(Canvas canvas){         super.onDraw(canvas);          loadBitmap();          // init shader         if (image != null) {              canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);              shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvas.getWidth(), canvas.getHeight(), false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);             paint.setShader(shader);              canvas.drawPath(hexagonBorderPath, paintBorder);             canvas.drawPath(hexagonPath, paint);         }      }      @Override     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){         super.onMeasure(widthMeasureSpec, heightMeasureSpec);          int width = measureWidth(widthMeasureSpec);         int height = measureHeight(heightMeasureSpec, widthMeasureSpec);          viewWidth = width - (borderWidth * 2);         viewHeight = height - (borderWidth * 2);          radius = height / 2 - borderWidth;          calculatePath();          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 {             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);     }   } 
like image 23
lacas Avatar answered Sep 28 '22 19:09

lacas