Sono in ritardo per questa domanda ma di recente ho riscontrato un problema simile, ho deciso di creare il mio numero personalizzato board view library per risolvere questo problema. Aggiunge maggiore flessibilità a ciò che puoi fare e porta a un'implementazione più immediata.
Ecco alcuni frammenti di codice che mostrano come funziona. In primo luogo, è facile disegnare la griglia di bordo su metodo di una visualizzazione personalizzata 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);
}
}
Se si dispone di un String[][]
array di stringhe, ecco come è possibile impostare le lettere, assumendo il punto di vista di ogni piastrella già stati immessi sul bordo:
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]);
}
}
Allora avete bisogno di un lavoro più complesso da gestire in realtà il tatto e trascinando sopra le piastrelle da tavolo per selezionare le parole:
@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;
}
I metodi isTileValid()
e isTileAllowed()
assicurano che il riquadro che l'utente sta tentando di selezionare sia in una direzione consentita e che non sia stato precedentemente selezionato. Infine, lo getTilesBetween()
restituisce tutte le tessere valide tra la prima tessera toccata dall'utente e quella che sta attualmente toccando.
Spero che aiuti!