Android onInterceptTouchEvent, получить дочерние элементы в ViewGroup

У меня есть такой макет (например, доска), который содержит ячейки (кнопки)

| A | B | C | D |
-----------------
| E | F | G | H |
-----------------
| I | J | K | L |
-----------------
| X | Y | Z | W |

Я добавляю ячейки программно, они содержат буквы, которые я установил.

public void addCells(String letters){
    removeAllViews();
    int let = 0;
    for (int j = 0; j < 4; j++){
        for (int i = 0; i < 4; i++){
            String currentLetter = ""+letters.charAt(let);
            //Cell object that contains it's position and letter.
            Cell cell_ = new Cell(this.getContext(), new Point(i , j), new Letter(currentLetter)); 
            this.addView(cell_);
            this.cells[i][j] = cell_;
            let++;
        }
    }
}

Моя цель - соединить ячейки движением пальца следующим образом:

введите здесь описание изображения

Я возвращаюсь true из onTouchEvent(), чтобы зафиксировать все касания в ViewGroup onInterceptTouchEvent()

public boolean onTouchEvent(MotionEvent motionEvent) {
    return true;
}

Но я не мог понять логику. Как я могу получить доступ к определенному дочернему объекту, щелкнув/касаясь в этой ViewGroup?

Когда я нажимаю на букву «А», я хочу получить доступ к этому объекту ячейки.


person Lazy    schedule 29.07.2015    source источник


Ответы (1)


В целом:

  • Родительское представление перехватывает все события касания (x, y)

    onInterceptTouchEvent() { return true; }
    
  • При касании родитель находит внутреннее представление, соответствующее местоположению события.

    onTouchEvent() { // see below }
    
  • Выполните действие в этом представлении (подсветите его, обновите данные и т. д.)

Как родитель может найти внутренний вид?

Вы можете сделать это двумя способами,

1) Иметь структуру данных ([][]) для доски, которая содержит ссылку на представления ячеек. Тогда вы знаете, что такое событие касания X, Y, поэтому, если все ячейки равны, просто вычислите правильную ячейку на основе размера и местоположения ячеек.

View[][] board;
// Add the Views to the board in creation loop

int cellWidth = board[0][0].getMeasuredWidth();
int cellHeight = board[0][0].getMeasuredHeight();

int tragetX = (int)(x / cellWidth);
int targetY = (int)(y / cellHeight);

View targetCell = board[targetX][targetY];

// Do something with targetCell

2) Повторите все родительские дочерние элементы (лучше всего от последнего к первому) и вычислите местоположение дочернего представления внутри родительского местоположения и с комбинацией его размера определите, является ли этот дочерний элемент целью или нет.

View targetChild = null;
int[] loc = new int[2];
for (int i = getChildCount()-1; i >= 0; i--) {
    View child = getChildAt(i);
    child.getLocationInWindow(loc);
    if (x >= loc[0] && x <= loc[0]+child.getMeasuredWidth() &&
        y >= loc[1] && y <= loc[1]+child.getMeasuredHeight()) {
        targetChild = child;
        break;
    }
}
// Do something with targetChild

Вышеприведенный пример, пожалуйста, напишите лучший код :) (повторное использование loc и т. д.)

person Eyal Biran    schedule 29.07.2015
comment
Большое спасибо, я выберу метод 1. Это, безусловно, то, что я ищу. - person Lazy; 30.07.2015
comment
Эй, кстати, getMeasuredWidth() возвращает 0, знаешь почему? После MeasureSpec.UNSPECIFIED возвращается 192, но должно быть 300. - person Lazy; 30.07.2015
comment
Рад, что это помогло :) - Функция getMeasuredWidth вернет 0 до того, как представление будет фактически выложено. Это означает, что размер представления еще не был рассчитан. - person Eyal Biran; 30.07.2015