Android onInterceptTouchEvent, get childs in ViewG

2019-09-07 05:17发布

问题:

I have a layout(like board) like this that contains cells(buttons)

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

I'm adding Cells programmatically, they contains letters I set.

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++;
        }
    }
}

My aim is connecting cells by finger moving like this:

I'm returning true from onTouchEvent() so I can capture all touchs in ViewGroup onInterceptTouchEvent()

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

But I couldn't get the logic. How can I access a certain child object by click/touch in that ViewGroup?

When I click to 'A' letter, I want to access that cell object.

回答1:

In general:

  • The parent view intercepts all touch events (x,y)

    onInterceptTouchEvent() { return true; }
    
  • On touch event, the parent finds the inner view that match the event location

    onTouchEvent() { // see below }
    
  • Perform action on that view (Light it up, update data, etc)

How the parent can find the inner view?

You can do it in 2 ways,

1) Have a data structure ([][]) for the board that holds a reference to the cells views. Then you know what is the touch event X,Y so if all cells are equal simply calculate the correct cell based on the cells size and location.

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) Iterate on all the parent children (last to first is best), and calculate the child view location inside the parent location and with combination of it's size determine if that child is the target or not.

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

The above is an example, please write a better code :) (reuse loc, etc...)