8

以下是程序详细信息:所以我正在创建一个单词搜索游戏,比如将一堆字母排列成一个正方形,你必须找到并选择垂直、水平或对角线的单词。我正在为电路板使用字符串数组,并使用 ArrayAdapter 将此字符串数组存储在网格视图中,这是我的主要活动布局的基本元素。

问题是:如何让用户可以将手指拖动到他们的选择上,选择单词中的所有字母,而无需多次将手指从屏幕上抬起?我希望所选单词上的突出显示在玩家选择一个单词时留在屏幕上,并且我希望当用户没有正确选择一个单词时,当用户从屏幕上抬起手指时,字母上的突出显示消失.

4

1 回答 1

1

我迟到了这个问题,但最近遇到了类似的问题,我决定创建自己的自定义板视图库来解决这个问题。它为您可以做的事情增加了更多的灵活性,并导致更直接的实施。

下面是一些代码片段,展示了它是如何工作的。首先,很容易在自定义视图的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()返回用户触摸的第一个瓷砖和他/她当前触摸的瓷砖之间的所有有效瓷砖。

希望能帮助到你!

于 2016-02-05T10:40:55.657 回答