如何在android中绘制六边形?

时间:2015-05-13 14:12:26

标签: java android

我在this tutorial中使用了六边形代码并创建了一个createHex类(我应该发布代码吗?)。链接的网页使用以下代码实际使用createHex中的数学绘制六边形:

@Override
public void paint(Graphics g){
    for(int j = 0; int j < BOARD_HEIGHT; j++){
        for(int i = 0; i < BOARD_HEIGHT; I++){
            mCellMetrics.setCellIndex(i, j);
            if(mCells[j][i] != 0){
                mCellMetrics.computeCorners(mCornersX, mCornersY);
                g.setColor((mCells[j][i] == L_ON) ? COLOR.ORANGE):COLOR.GRAY;
                g.fillPolygon(mCornersX, mCornersY, NUM_HEX_CORNERS);
                g.setColor(COLOR.BLACK)
                g.drawPolygon(mCornersX, mCornersY, NUM_HEX_CORNERS);
            }
        }
    }
}

我遇到的问题是Android没有包含所有必需方法的Graphics类。我在android文档周围做了大约一个半小时的钓鱼,我找到的最接近的是Path类,但它没有我需要的方法。我想在顶部的链接文章中使用六边形代码,但我找不到图形类的等价物。如果没有相应的,有人可以告诉我如何使用链接代码获得我想要的结果吗?

我的问题:如何将链接文章中的代码移植到android?

修改

如果我包含计算六边形的边和六边形的六边形代码,我决定对其他人(和潜在的回答者)有帮助,所以这里是createHex.java:

   package com.rush;

/**
 * Uniform hexagonal grid cell's metrics utility class.
 */
public class HexGridCell {
    private static final int[] NEIGHBORS_DI = { 0, 1, 1, 0, -1, -1 };
    private static final int[][] NEIGHBORS_DJ = { 
            { -1, -1, 0, 1, 0, -1 }, { -1, 0, 1, 1, 1, 0 } };

    private final int[] CORNERS_DX; // array of horizontal offsets of the cell's corners
    private final int[] CORNERS_DY; // array of



vertical offsets of the cell's corners
    private final int SIDE;
private int mX = 0; // cell's left coordinate
private int mY = 0; // cell's top coordinate

private int mI = 0; // cell's horizontal grid coordinate
private int mJ = 0; // cell's vertical grid coordinate

/**
 * Cell radius (distance from center to one of the corners)
 */
public final int RADIUS;
/**
 * Cell height
 */
public final int HEIGHT;
/**
 * Cell width
 */
public final int WIDTH;

public static final int NUM_NEIGHBORS = 6;

/**
 * @param radius Cell radius (distance from the center to one of the corners)
 */
public HexGridCell(int radius) {
    RADIUS = radius;
    WIDTH = radius * 2;
    HEIGHT = (int) (((float) radius) * Math.sqrt(3));
    SIDE = radius * 3 / 2;

    int cdx[] = { RADIUS / 2, SIDE, WIDTH, SIDE, RADIUS / 2, 0 };
    CORNERS_DX = cdx;
    int cdy[] = { 0, 0, HEIGHT / 2, HEIGHT, HEIGHT, HEIGHT / 2 };
    CORNERS_DY = cdy;
}

/**
 * @return X coordinate of the cell's top left corner.
 */
public int getLeft() {
    return mX;
}

/**
 * @return Y coordinate of the cell's top left corner.
 */
public int getTop() {
    return mY;
}

/**
 * @return X coordinate of the cell's center
 */
public int getCenterX() {
    return mX + RADIUS;
}

/**
 * @return Y coordinate of the cell's center
 */
public int getCenterY() {
    return mY + HEIGHT / 2;
}

/**
 * @return Horizontal grid coordinate for the cell.
 */
public int getIndexI() {
    return mI;
}

/**
 * @return Vertical grid coordinate for the cell.
 */
public int getIndexJ() {
    return mJ;
}

/**
 * @return Horizontal grid coordinate for the given neighbor.
 */
public int getNeighborI(int neighborIdx) {
    return mI + NEIGHBORS_DI[neighborIdx];
}

/**
 * @return Vertical grid coordinate for the given neighbor.
 */
public int getNeighborJ(int neighborIdx) {
    return mJ + NEIGHBORS_DJ[mI % 2][neighborIdx];
}

/**
 * Computes X and Y coordinates for all of the cell's 6 corners, clockwise,
 * starting from the top left.
 * 
 * @param cornersX Array to fill in with X coordinates of the cell's corners
 * @param cornersX Array to fill in with Y coordinates of the cell's corners
 */
public void computeCorners(int[] cornersX, int[] cornersY) {
    for (int k = 0; k < NUM_NEIGHBORS; k++) {
        cornersX[k] = mX + CORNERS_DX[k];
        cornersY[k] = mY + CORNERS_DY[k];
    }
}

/**
 * Sets the cell's horizontal and vertical grid coordinates.
 */
public void setCellIndex(int i, int j) {
    mI = i;
    mJ = j;
    mX = i * SIDE;
    mY = HEIGHT * (2 * j + (i % 2)) / 2;
}

/**
 * Sets the cell as corresponding to some point inside it (can be used for
 * e.g. mouse picking).
 */
public void setCellByPoint(int x, int y) {
    int ci = (int)Math.floor((float)x/(float)SIDE);
    int cx = x - SIDE*ci;

    int ty = y - (ci % 2) * HEIGHT / 2;
    int cj = (int)Math.floor((float)ty/(float)HEIGHT);
    int cy = ty - HEIGHT*cj;

    if (cx > Math.abs(RADIUS / 2 - RADIUS * cy / HEIGHT)) {
        setCellIndex(ci, cj);
    } else {
        setCellIndex(ci - 1, cj + (ci % 2) - ((cy < HEIGHT / 2) ? 1 : 
0));
            }
        }
    }

有关代码如何工作的说明,请参阅链接文章。

2 个答案:

答案 0 :(得分:3)

试试这个:

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

答案 1 :(得分:1)

试试这个或download demo example

public static Bitmap getHexagonalCroppedBitmap(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(), Bitmap.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(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(finalBitmap, rect, rect, paint);

        return output;
    }

将您的图像裁剪为六边形作为此函数的位图

Bitmap myhexagon = getHexagonalCroppedBitmap(Myimage, yourHexagonalRadius);