Android自定义矩形绘图

时间:2015-03-27 01:34:11

标签: android android-layout

我希望在Android UI中创建Scrabble板类型视图。为此,我现在决定(仍然以最好的方式做到这一点)使用TableLayout和TableRow视图,并将自定义BoardCell视图作为电路板的单个单元格。

我还是Android的新手,我之前从未创建过自定义视图。我遇到了绘制矩形的问题。我可以得到一行中的第一个单元格,但我无法得到该行中剩余的14个单元格。在调试期间,所有BoardCell对象都被初始化,并为每个对象调用'onDraw'。测量以及左,上,右和下位置似乎也是正确的。所以我的问题是......我做错了什么?这一定是我想念的简单事情吗?

我试过简单地绘制一些单元格的笔划(如下面的代码所示),并且缺少右边和底边的线条。我知道这与它有关但我不明白为什么不会绘制单元格的右边和底部?

以下是所有相关代码,删除了相关代码以缩短此帖子。

activity_game.xml

<!-- Game Board --> <TableLayout android:id="@+id/board_grid" android:layout_width="355dp" android:layout_height="355dp" android:layout_below="@+id/score_container" android:layout_marginRight="2dp" android:layout_marginLeft="2dp" android:background="@color/white" android:stretchColumns="*"> <!-- Row 1 --> <TableRow android:layout_weight="1"> <BoardCellView android:layout_height="21dp" android:layout_width="0dp" android:layout_margin="1dp" custom:cellType="doubleWord"/> <BoardCellView android:layout_height="21dp" android:layout_width="0dp" android:layout_margin="1dp"/> <BoardCellView android:layout_height="21dp" android:layout_width="0dp" android:layout_margin="1dp"/> <BoardCellView android:layout_height="21dp" android:layout_width="0dp" android:layout_margin="1dp"/> <BoardCellView android:layout_height="21dp" android:layout_width="0dp" android:layout_margin="1dp"/> <BoardCellView android:layout_height="21dp" android:layout_width="0dp" android:layout_margin="1dp"/> <BoardCellView android:layout_height="21dp" android:layout_width="0dp" android:layout_margin="1dp" custom:cellType="doubleLetter"/> <BoardCellView android:layout_height="21dp" android:layout_width="0dp" android:layout_margin="1dp"/> <BoardCellView android:layout_height="21dp" android:layout_width="0dp" android:layout_margin="1dp" custom:cellType="doubleLetter"/> <BoardCellView android:layout_height="21dp" android:layout_width="0dp" android:layout_margin="1dp"/> <BoardCellView android:layout_height="21dp" android:layout_width="0dp" android:layout_margin="1dp"/> <BoardCellView android:layout_height="21dp" android:layout_width="0dp" android:layout_margin="1dp"/> <BoardCellView android:layout_height="21dp" android:layout_width="0dp" android:layout_margin="1dp"/> <BoardCellView android:layout_height="21dp" android:layout_width="0dp" android:layout_margin="1dp"/> <BoardCellView android:layout_height="21dp" android:layout_width="0dp" android:layout_margin="1dp" custom:cellType="doubleWord"/> </TableRow> </TableLayout>

BoardCellView.java

public class BoardCellView extends View {

    private static final String TAG = BoardCellView.class.getName();

    private static final int STANDARD_CELL_COLOUR       = Color.rgb(234, 234, 234);
    private static final int DOUBLE_LETTER_CELL_COLOUR  = Color.rgb(200, 175, 224);
    private static final int TRIPLE_LETTER_CELL_COLOUR  = Color.rgb(132, 217, 168);
    private static final int DOUBLE_WORD_CELL_COLOUR    = Color.rgb(255, 181, 131);
    private static final int TRIPLE_WORD_CELL_COLOUR    = Color.rgb(146, 205, 251);

    private Paint standardCellPaint;
    private Paint doubleLetterPaint;
    private Paint tripleLetterPaint;
    private Paint doubleWordPaint;
    private Paint tripleWordPaint;

    private CellType cellType;

    private Rect cellRectangle;

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

        init();

        TypedArray typedArray = context.getTheme().obtainStyledAttributes(
            attrs,
            R.styleable.BoardCellView,
            0, 0);

        try {
            this.cellType =     CellType.fromInt(typedArray.getInt(R.styleable.BoardCellView_cellType, 0));

        } finally {
            typedArray.recycle();
        }
    }

    /**
     * Setup the paint and rectangle objects
     */
    private void init() {
        // The rectangle we will use to draw
        this.cellRectangle = new Rect();

        // Setup the Paints for each cell type
        this.standardCellPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        this.standardCellPaint.setStyle(Paint.Style.STROKE);
        this.standardCellPaint.setColor(STANDARD_CELL_COLOUR);
        this.standardCellPaint.setStrokeWidth(5.0f);

        this.doubleLetterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        this.doubleLetterPaint.setStyle(Paint.Style.FILL);
        this.doubleLetterPaint.setColor(DOUBLE_LETTER_CELL_COLOUR);

        this.tripleLetterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        this.tripleLetterPaint.setStyle(Paint.Style.FILL);
        this.tripleLetterPaint.setColor(TRIPLE_LETTER_CELL_COLOUR);

        this.doubleWordPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        this.doubleWordPaint.setStyle(Paint.Style.STROKE);
        this.doubleWordPaint.setColor(DOUBLE_WORD_CELL_COLOUR);
        this.doubleWordPaint.setStrokeWidth(5.0f);

        this.tripleWordPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        this.tripleWordPaint.setStyle(Paint.Style.FILL);
        this.tripleWordPaint.setColor(TRIPLE_WORD_CELL_COLOUR);

    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        this.cellRectangle.set(left, top, right, bottom);
        Log.d(TAG, "---- " + left + ":"+ top + ":"+ right + ":"+ bottom);
    }

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

        // Standard cell first as this is by far the most common
        switch (this.cellType) {
            case STANDARD:
                Log.d(TAG, "---- Drawing Standard: " + this.cellRectangle.toShortString());
                canvas.drawRect(this.cellRectangle, this.standardCellPaint);
                break;
            case DL:
                Log.d(TAG, "---- Drawing DL");
                canvas.drawRect(this.cellRectangle, this.doubleLetterPaint);
                break;
            case TL:
                Log.d(TAG, "---- Drawing TL");
                canvas.drawRect(this.cellRectangle, this.tripleLetterPaint);
                break;
            case DW:
                Log.d(TAG, "---- Drawing DW: " + this.cellRectangle.toShortString());
                canvas.drawRect(this.cellRectangle, this.doubleWordPaint);
                break;
            case TW:
                Log.d(TAG, "---- Drawing TW");
                canvas.drawRect(this.cellRectangle, this.tripleWordPaint);
                break;
        }
    }
}

Logcat的输出(首先从onLayout输出,第二个是从onDraw输出)

BoardCellView﹕ ---- 3:3:68:66
03-27 10:57:12.534  27810-27810/app D/BoardCellView﹕ ---- 74:3:139:66
03-27 10:57:12.534  27810-27810/app D/BoardCellView﹕ ---- 145:3:210:66
03-27 10:57:12.534  27810-27810/app D/BoardCellView﹕ ---- 216:3:281:66
03-27 10:57:12.534  27810-27810/app D/BoardCellView﹕ ---- 287:3:352:66
03-27 10:57:12.536  27810-27810/app D/BoardCellView﹕ ---- 358:3:423:66
....
---- Drawing DW: [3,3][68,66]
03-27 10:57:12.576  27810-27810/app D/BoardCellView﹕ ---- Drawing Standard: [74,3][139,66]
03-27 10:57:12.576  27810-27810/app D/BoardCellView﹕ ---- Drawing Standard: [145,3][210,66]
03-27 10:57:12.576  27810-27810/app D/BoardCellView﹕ ---- Drawing Standard: [216,3][281,66]
03-27 10:57:12.576  27810-27810/app D/BoardCellView﹕ ---- Drawing Standard: [287,3][352,66]

以下是绘制视图的方式。前两行使用我的自定义视图。剩余的行使用具有背景颜色的简单View对象。

![电路板视图] http://cl.ly/image/0T2F3i1l3y24

我花了几天时间尝试了谷歌和这里的各种解决方案(Drawing multiple custom views),但我没有发现任何解决我问题的方法。在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

问题在于cellRectangleonLayout()的设置。传递到onLayout()的矩形坐标是相对于父视图的,但是在调用onDraw()时需要在drawRect()中使用的坐标应该相对于视图本身,因为Canvas已设置,因此视图的左上角对应于(0,0)。

父视图中的(左,上)对应于子视图中的(0,0),(右,下)将对应于(右 - 左,下 - 上)。你只需要从它们两个中减去(左,上)。

考虑到这一点,请像这样更改onLayout

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    this.cellRectangle.set(0, 0, right-left, bottom-top);
    Log.d(TAG, "---- " + left + ":"+ top + ":"+ right + ":"+ bottom);
}