我希望在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),但我没有发现任何解决我问题的方法。在此先感谢您的帮助。
答案 0 :(得分:0)
问题在于cellRectangle
中onLayout()
的设置。传递到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);
}