可以使Android的蜂巢XML布局? [英] Possible to make a beehive XML layout in Android?

查看:253
本文介绍了可以使Android的蜂巢XML布局?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个蜂箱版面应该像这样

A beehive layout should look like this

彩色蜂巢只是让你明白,我怎么也得放下元素。

The colored hives are just so you understand how I have to lay down elements.

其中布局插件你建议使用?

我试着用的GridView ,但我不能让这些细胞,然后的FrameLayout ,但不想处理设置蜂巢的位置,当像素(或DP)值。

I tried with GridView but I cannot make such cells, then FrameLayout but don't want to deal with pixel (or dp) values when setting hive location.

我在我束手无策。我靠近结论,这样的事情不能在Android的一个高品质的方式,而无需使用游戏般的库完成。我希望有人可以给我一个很好的线索,以解决方案。

I am at my wits end. I am close to conclusion that something like this cannot be done in Android in a high quality way and without using game-like libraries. I hope someone will give me a good clue to solution.

推荐答案

由于我不能确定的预期目的,或要求,以下仅仅是证明了概念。该 HoneycombView 类没有非法参数的检查,或任何形式的异常处理,真的。大多数属性是硬codeD,如墙面的颜色和宽度,单元格的颜色和方向等,这些都是很容易地修改,增加了相应的getter和setter方法​​。 我已经包括了一个简单的活动类来说明它的使用。

As I'm not certain of the intended purpose or requirements, the following is merely proof-of-concept. The HoneycombView class has no illegal argument checks, or exception handling of any kind, really. Most of the properties are "hard-coded", such as wall color and width, cell colors and orientation, etc. These are all easily modified with the addition of the appropriate setters and getters. I've included a simple Activity class to demonstrate its use.

public class HoneycombView extends View
{
    private Paint wallPaint = new Paint();
    private Paint fillPaint = new Paint();
    private Paint cachePaint = new Paint();
    private Path combPath;
    private Bitmap cacheBmp;
    private Canvas cacheCan;

    private int cellWidth;
    private int columns;
    private int rows;
    private boolean[][] cellSet;

    private OnCellClickListener listener;

    public HoneycombView(Context context)
    {
        this(context, null);
    }

    public HoneycombView(Context context, AttributeSet attrs)
    {
        super(context, attrs);

        wallPaint.setColor(Color.YELLOW);
        wallPaint.setStyle(Paint.Style.STROKE);
        wallPaint.setStrokeWidth(5f);

        fillPaint.setStyle(Paint.Style.FILL);       
        cachePaint.setStyle(Paint.Style.FILL);
    }

    public void initialize(int columns, int rows)
    {
        this.columns = columns;
        this.rows = rows;

        this.cellSet = new boolean[columns][rows];
    }

    public interface OnCellClickListener
    {
        public void onCellClick(int column, int row);
    }

    public void setOnCellClickListener(OnCellClickListener listener)
    {
        this.listener = listener;
    }

    public void setCell(int column, int row, boolean isSet)
    {
        cellSet[column][row] = isSet;
        invalidate();
    }

    public boolean isCellSet(int column, int row)
    {
        return cellSet[column][row];
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        super.onSizeChanged(w, h, oldw, oldh);

        cacheBmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        cacheCan = new Canvas(cacheBmp);

        cellWidth = 2 * w / (2 * columns + columns - 1);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);

        canvas.drawColor(Color.WHITE);

        boolean oddRow;
        int xOff;

        combPath = getHexPath(cellWidth / 2f, cellWidth / 2f, (float) (cellWidth * Math.sqrt(3) / 4));

        for (int r = 0; r < rows; r++)
        {
            oddRow = (r & 1) == 1;
            xOff = 0;

            for (int c = 0; c < columns; c++)
            {
                if (!(oddRow && c == columns - 1))
                {
                    fillPaint.setColor(cellSet[c][r] ? Color.RED : Color.WHITE);
                    canvas.drawPath(combPath, fillPaint);

                    canvas.drawPath(combPath, wallPaint);

                    cachePaint.setColor(Color.argb(255, 1, c, r));
                    cacheCan.drawPath(combPath, cachePaint);

                    combPath.offset((int) (1.5f * cellWidth), 0);
                    xOff += 1.5f * cellWidth;
                }
            }

            combPath.offset(-xOff + (oddRow ? -1 : 1) * 3 * cellWidth / 4, (float) (cellWidth * Math.sqrt(3) / 4));
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        if (event.getAction() != MotionEvent.ACTION_DOWN)
            return true;

        int pixel = cacheBmp.getPixel((int) event.getX(), (int) event.getY());

        int r = Color.red(pixel);
        if (r == 1)
        {
            int g = Color.green(pixel);
            int b = Color.blue(pixel);  

            if (listener != null)
            {
                listener.onCellClick(g, b);
            }
        }
        return true;
    } 

    private Path getHexPath(float size, float centerX, float centerY)
    {
        Path path = new Path();

        for (int j = 0; j <= 6; j++)
        {
            double angle = j * Math.PI / 3;
            float x = (float) (centerX + size * Math.cos(angle));
            float y = (float) (centerY + size * Math.sin(angle));
            if (j == 0)
            {
                path.moveTo(x, y);
            }
            else
            {
                path.lineTo(x, y);
            }
        }

        return path;
    }
}

活动

public class MainActivity extends Activity
implements HoneycombView.OnCellClickListener
{
    HoneycombView honey;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_NO_TITLE);

        honey = new HoneycombView(this);
        honey.initialize(4, 8);
        honey.setOnCellClickListener(this);

        setContentView(honey);
    }

    @Override
    public void onCellClick(int column, int row)
    {
        honey.setCell(column, row, !honey.isCellSet(column, row));
    }
}

我去稍微改变一个区域的颜色来确定触摸事件会发生我的最初的建议,但我最终这样做的一员位图这样的导通屏幕色彩不受影响。正如你可以从code看到的,细胞在这个位图填充以这样的方式来连接code相关的小区信息在颜色的RGB分量。红色分量被设置为1,以指示给定像素是相关的区域(即,内全蜂窝)内。网格内的单元格的列和行位置,然后连接codeD上的绿色和蓝色组成部分,并在的onTouchEvent()方法很容易地检索。

I went with my initial suggestion of slightly altering an area's color to determine where touch events would occur, but I ended up doing so in a member Bitmap so the on-screen colors are unaffected. As you can see from the code, the cells in this Bitmap are filled in such a way as to encode relevant cell info in the Color's RGB components. The Red component is set to 1 to indicate that a given pixel is within the pertinent region (i.e., within the whole "honeycomb"). The cell's column and row positions within the grid are then encoded in the Green and Blue components, and are easily retrieved in the onTouchEvent() method.

初始化()方法设置网格中的行和列的数量,并在样品中活动它们被设置为赞成横向。只是为了清楚起见,在我的实现,与细胞取向使得长轴是水平的,我定义一排为包含所述细胞的轴线是共线的。我已经张贴在我的评论的链接做不同的事情。

The initialize() method sets the number of columns and rows in the grid, and in the sample Activity they are set to favor a landscape orientation. Just for clarity, in my implementation, with the cells oriented so the long axis is horizontal, I define a row to consist of the cells whose axes are co-linear. The link I had posted in my comment did things differently.

我差点忘了给予信贷:我得到了六边形路径 $ C $从的这个问题

I almost forgot to give credit: I got the hexagonal Path code from this question.

这篇关于可以使Android的蜂巢XML布局?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆