Cómo dar forma hexagonal a ImageView

Cómo dar forma de hexágono a ImageView . ¿Es posible hacer de la misma manera? Si es así entonces cómo. Si esto no es posible a través de este, entonces cómo se podría lograr esto?

 <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> 

Captura de pantalla

Introduzca aquí la descripción de la imagen

Aquí no puedo hacer la imagen de enmascaramiento, porque no puedo detectar qué parte de mapa de bits que debe recortar para obtener hexágono forma de mapa de bits. Así que estoy buscando la respuesta para dar forma de hexágono a ImageView

Pruebe esta vista. Es posible que desee ajustarlo para sus necesidades específicas, pero dibuja una máscara de hexágono con un borde en la parte superior de una vista. El recurso de fondo va por debajo de la máscara.

El resultado:

Introduzca aquí la descripción de la imagen

El código:

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(); } } 

Actualización 29.07.2016

Una mejor manera de sólo recortar la imagen de origen sin pintar el fondo de toda la vista. Cambiado a un ImageView como una clase base para beneficiarse del scaleType. También hice algunos refactorización de código.

 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); } } 

Ejemplo de diseño:

 <?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> 

Nuevo resultado

Aquí está mi código de trabajo para esto, soporta sombras para:

 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); } } 

Hay un par de cosas que puedes probar:

  • Es posible que desee probar dibujar un 9patch en la parte superior de la imagen.

  • También hay este tuto corto de Romain Guy: http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/

     BitmapShader shader; shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); Paint paint = new Paint(); paint.setAntiAlias(true); paint.setShader(shader); RectF rect = new RectF(0.0f, 0.0f, width, height); // rect contains the bounds of the shape // radius is the radius in pixels of the rounded corners // paint contains the shader that will texture the shape canvas.drawRoundRect(rect, radius, radius, paint); 

    En lugar de usar drawRoundRect() método de lienzo, puede intentar usar drawPath() para obtener la forma deseada.

    Espero que esto te pone en la dirección correcta.

Vea este ejemplo que está creando un triángulo para que pueda obtener lógica de ello 🙂

http://looksok.wordpress.com/2013/08/24/android-triangle-arrow-defined-as-an-xml-shape/

Otra solución que encontré pero no probé así que intenta esto también

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TextView tv = (TextView) findViewById(R.id.text); Path path = new Path(); float stdW = 100; float stdH = 100; float w3 = stdW / 3; float h2 = stdH / 2; path.moveTo(0, h2); h2 -= 6 / 2; path.rLineTo(w3, -h2); path.rLineTo(w3, 0); path.rLineTo(w3, h2); path.rLineTo(-w3, h2); path.rLineTo(-w3, 0); path.rLineTo(-w3, -h2); Shape s = new PathShape(path, stdW, stdH); ShapeDrawable d = new ShapeDrawable(s); Paint p = d.getPaint(); p.setColor(0xffeeeeee); p.setStyle(Style.STROKE); p.setStrokeWidth(6); tv.setBackgroundDrawable(d); } 

Fuente: grupo de Google

Tercera solución – Esto podría ser una biblioteca útil

PathDrawable es un Drawable que dibuja formas simples usando el objeto Path.

Es tarde para relucir .. Pero Espero que ayude a alguien …

  public Bitmap getHexagonShape(Bitmap scaleBitmapImage) { // TODO Auto-generated method stub int targetWidth = 200; int targetHeight =200; Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight,Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(targetBitmap); Path path = new Path(); float stdW = 200; float stdH = 200; float w3 =stdW / 2; float h2 = stdH / 2; float radius=stdH/2-10; float triangleHeight = (float) (Math.sqrt(3) * radius / 2); float centerX = stdW/2; float centerY = stdH/2; path.moveTo(centerX, centerY + radius); path.lineTo(centerX - triangleHeight, centerY + radius/2); path.lineTo(centerX - triangleHeight, centerY - radius/2); path.lineTo(centerX, centerY - radius); path.lineTo(centerX + triangleHeight, centerY - radius/2); path.lineTo(centerX + triangleHeight, centerY + radius/2); path.moveTo(centerX, centerY + radius); canvas.clipPath(path); Bitmap sourceBitmap = scaleBitmapImage; canvas.drawBitmap(sourceBitmap, new Rect(0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight()), new Rect(0, 0, targetWidth, targetHeight), null); return targetBitmap; } public static Bitmap drawableToBitmap (Drawable drawable) { if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable)drawable).getBitmap(); } Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } 

Llame a esto donde desee usar

  Drawable drawable = getResources().getDrawable( R.drawable.placeholder ); Bitmap b=getHexagonShape(drawableToBitmap(drawable)); img=(ImageView)findViewById(R.id.imageView); img.setImageBitmap(b); 

La siguiente función lee su imagen como bitmap de entrada y devuelve un mapa de bits que es de forma hexagonal

 public Bitmap getHexagonShape(Bitmap scaleBitmapImage) { // TODO Auto-generated method stub int targetWidth = 600; int targetHeight = 600; Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, targetHeight,Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(targetBitmap); Path path = new Path(); float stdW = 300; float stdH = 300; float w3 =stdW / 2; float h2 = stdH / 2; path.moveTo(0, (float) (h2*Math.sqrt(3)/2)); path.rLineTo(w3/2, -(float) (h2*Math.sqrt(3)/2)); path.rLineTo(w3, 0); path.rLineTo(w3/2, (float) (h2*Math.sqrt(3)/2)); path.rLineTo(-w3/2, (float) (h2*Math.sqrt(3)/2)); path.rLineTo(-w3, 0); path.rLineTo(-w3/2, -(float) (h2*Math.sqrt(3)/2)); canvas.clipPath(path); Bitmap sourceBitmap = scaleBitmapImage; canvas.drawBitmap(sourceBitmap, new Rect(0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight()), new Rect(0, 0, targetWidth, targetHeight), null); return targetBitmap; } 

No sé si el OP obtuvo la respuesta que buscaba, pero aquí va.

He creado una vista personalizada, que amplía ImageView, que hará el trabajo para usted un poco mejor. La respuesta aquí sólo crea un maks dentro del ImageView y te obliga a configurar la imagen como fondo

Mi vista le permite configurar la imagen como un mapa de bits estándar, maneja CenterCrop y el escalado de la imagen. Realmente establece la máscara exterior en su lugar, y con el mismo borde más sombra.

Y si eso no es suficiente, puede crear fácilmente formas personalizadas para renderizar, simplemente extender la clase RenderShape. (4 formas están incluidas en la biblioteca: Círculo, Triángulo, Hexágono y Octagon)

Echa un vistazo a mi github

Aclamaciones

Lo he resuelto usando este código:

  private Bitmap getHexagoneCroppedBitmap(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; } 

Puedes usar la forma de Android ImageView de siamed.

https://github.com/siyamed/android-shape-imageview

 <com.github.siyamed.shapeimageview.HexagonImageView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="8dp" android:src="@drawable/neo" app:siBorderWidth="8dp" app:siBorderColor="@color/darkgray"/> 

Por favor lea la documentación en github, hay muchas opciones disponibles.

  • ¿La llamada de runOnUiThread de Android llama a getView () en Adapters?
  • ¿Cómo desactivan otros botones cuando presiono el botón?
  • Cómo alinear TextView alrededor de un ImageView?
  • Cómo convertir una cadena Base64 en una imagen de BitMap para mostrarlo en un ImageView?
  • Cómo llamar a los colores de los recursos de forma dinámica en Android?
  • Mostrar menú contextual con clic corto no largo
  • Obtener Bitmap de ImageView cargado con Picasso
  • Android - ImageView: setImageBitmap VS setImageDrawable
  • Cómo animar ImageView de centro de cultivo para llenar la pantalla y viceversa (estilo de facebook)?
  • No se puede cargar la imagen tomada desde la cámara en un ImageView
  • ViewPager onClickListener hace referencia a la vista errónea en android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.