我迟到了这个问题,但最近遇到了类似的问题,我决定创建自己的自定义板视图库来解决这个问题。它为您可以做的事情增加了更多的灵活性,并导致更直接的实施。
下面是一些代码片段,展示了它是如何工作的。首先,很容易在自定义视图的onDraw()
方法上绘制板网格:
@Override
protected void onDraw(Canvas canvas) {
for (int i = 0; i <= numRows; i++) {
//For custom grid sizes, y can't be equal the board size or the line drawn won't show
int y = Math.min(boardHeight - 1, i * tileSize);
canvas.drawLine(0, y, boardWidth, y, boardPaint);
}
for (int i = 0; i <= numCols; i++) {
//For custom grid sizes, x can't be equal the board size or the line drawn won't show
int x = Math.min(boardWidth - 1, i * tileSize);
canvas.drawLine(x, 0, x, boardHeight, boardPaint);
}
}
如果你有一个String[][]
字符串数组,假设每个图块的视图已经放置在板上,下面是设置字母的方法:
public void setLetterBoard(String[][] letterBoard) {
if (letterBoard.length != getNumRows()
|| letterBoard[0].length != getNumCols()) {
setBoardSize(letterBoard.length, letterBoard[0].length);
}
int row, col;
for (int i=0; i < getChildCount(); i++) {
row = i / getNumCols();
col = i % getNumCols();
LetterTileView child = (LetterTileView) getChildAt(i);
child.setLetter(letterBoard[row][col]);
}
}
然后你需要更复杂的工作来实际处理触摸并拖动板块来选择单词:
@Override
public boolean onTouchEvent(MotionEvent event) {
float X = event.getX();
float Y = event.getY();
int row = (int) (Y / getTileSize());
int col = (int) (X / getTileSize());
View child = getChildAt(row, col);
//Exit on invalid touches
if (event.getActionMasked() != MotionEvent.ACTION_UP
&& (row >= getNumRows()
|| col >= getNumCols()
|| child == null)) {
return true;
}
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
Tile currentTile = new Tile(row, col, child);
if (currentSelectedWord == null) {
currentSelectedWord = new SelectedWord(currentTile);
} else if (!currentTile.equals(currentSelectedWord.lastTile)
&& currentSelectedWord.isTileValid(currentTile)) {
if (!currentSelectedWord.isTileAllowed(currentTile)) {
//Clear the status of the old selection
updateTiles(currentSelectedWord.selectedTiles, false, false);
//If the current tile is valid but not allowed for the current word selection,
//start a new selection that matches the tile
currentSelectedWord = new SelectedWord(currentSelectedWord.getInitialTile());
}
List<Tile> tiles = getTilesBetween(currentSelectedWord.lastTile, currentTile);
if (tiles.size() > 0) {
currentSelectedWord.addTiles(tiles);
}
}
updateTiles(currentSelectedWord.selectedTiles, true, false);
break;
case MotionEvent.ACTION_UP:
if (currentSelectedWord != null) {
boolean isValidSelection = (listener != null && listener.onWordSelected(currentSelectedWord.toBoardWord()));
updateTiles(currentSelectedWord.selectedTiles, false, isValidSelection);
if (isValidSelection) {
selectedWords.add(currentSelectedWord);
}
currentSelectedWord = null;
}
break;
default:
return false;
}
return true;
}
方法isTileValid()
并isTileAllowed()
确保用户尝试选择的图块处于允许的方向并且之前未被选择。最后,getTilesBetween()
返回用户触摸的第一个瓷砖和他/她当前触摸的瓷砖之间的所有有效瓷砖。
希望能帮助到你!