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
- Android ImageView sombra de la gota
- Diapositiva de Android para responder como animación de ImageView
- Cuadrícula de imágenes dentro de ScrollView
- Cargador de imágenes asíncronas en listview
- Android ImageView escala la imagen más pequeña al ancho con altura flexible sin recortar ni distorsionar
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
- cómo enviar la imagen de una actividad a otra?
- Cómo agregar un Marcador / Pin en un Android de ImageView?
- Cómo compartir la imagen de imageview?
- ¿El android: scaleType = "fitCenter" sólo funciona con los atributos fix Layout_width y Layout_height?
- Cómo dibujar línea en imageview junto con dedo en android
- El objetivo no debe ser nulo utilizando la Biblioteca Picasso
- ¿Cómo mantener múltiples capas de ImageViews y mantener su relación de aspecto basada en el más grande?
- Recortar imagen de la aplicación de la galería se bloquea - Android
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:
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>
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 usardrawPath()
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.
- Android RelativeLayout alinea el centro de una vista en la esquina superior derecha de otra vista
- AndroidStudio / Gradle con powermock