我想创建一个ImageView
,将其内容剪辑到多边形内(在本例中为六边形)。我将视图的图层类型设置为软件,以便我可以使用canvas.clipPath()
:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
setLayerType (LAYER_TYPE_SOFTWARE, null);
}
生成六边形的代码似乎工作正常:
这是计算顶点的代码:
@Override public void calculateVertices () {
width = 2f * radius;
side = 1.5f * radius;
height = (float) Math.sqrt (3f) * radius;
vertices = new Point[6];
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
final float[] p0 = new float[] {center.x - radius, center.y};
final Matrix m = new Matrix ();
final float r = getRotation ();
for (int i = 0; i < vertices.length; i++) {
final float ptRot = rotateBy (r, (float) i * 60f);
final float[] point = new float[2];
if (ptRot != 0f) {
m.reset ();
m.postRotate (ptRot, center.x, center.y);
m.mapPoints (point, p0);
} else {
point[0] = p0[0];
point[1] = p0[1];
}
if (point[0] < minX) {
minX = Math.round (point[0]);
} else if (point[0] > maxX) {
maxX = Math.round (point[0]);
}
if (point[1] < minY) {
minY = Math.round (point[1]);
} else if (point[1] > maxY) {
maxY = Math.round (point[1]);
}
vertices[i] = fromFloat (point);
}
path.reset ();
clipPath.reset ();
path.moveTo (vertices[0].x, vertices[0].y);
clipPath.moveTo (vertices[0].x, vertices[0].y);
for (int i = 1; i < vertices.length; i++) {
path.lineTo (vertices[i].x, vertices[i].y);
clipPath.lineTo (vertices[i].x, vertices[i].y);
}
path.lineTo (vertices[0].x, vertices[0].y);
clipPath.lineTo (vertices[0].x, vertices[0].y);
path.close ();
clipPath.close ();
enclosure.set (minX, minY, maxX, maxY);
}
如上所示,同样的方法生成边界矩形以及定义多边形的路径和多边形的剪切路径。
在此视图的构造函数中,path
和clipPath
被定义为
path = new Path ();
clipPath = new Path ();
clipPath.setFillType (Path.FillType.INVERSE_EVEN_ODD);
视图的onDraw
方法被覆盖:
@Override protected void onDraw (final Canvas canvas) {
final int count = canvas.save ();
canvas.clipPath (hexagon.getClipPath ());
super.onDraw (canvas);
hexagon.draw (canvas, selectBackgroundPaint ());
canvas.restoreToCount (count);
}
只要我使用canvas.clipPath (hexagon.getClipPath ());
启用该行,视图就会显示:
4个裁剪点中有2个甚至不在我的路上!!
我在这里做错了什么?有没有更好的方法呢?
最终,我希望多边形之外的所有内容都只是透明的。总是。包括选择突出显示。
我很感激帮助。我无法发布太多代码(公司IP等),但如果您需要更多详细信息,请通知我,我会更新。
答案 0 :(得分:1)
我已经完全回答了你想要的一个问题。 @SceLus 还有answer被接受的是如此优秀和赏金的赢家,所以你可以从中获得帮助,因为链接可能会改变,所以我复制粘贴那个代码
<强> HexagonMaskView.java 强>
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();
}
}
答案 1 :(得分:0)
这里的兄弟是解决方案..
https://github.com/MostafaGazar/CustomShapeImageView有关详细信息https://coderwall.com/p/hmzf4w
使用此库,您将在此库中找到圆形形状,也易于使用。
你也可以像云一样为这个库制作自定义形状。这个库支持SVG文件格式,他们制作了圆角Imageview的SVG文件。
只要使用并告诉我是否有任何问题