Make INVISIBLE View handle touches as ACTION_OUTSI

2019-05-30 08:07发布

问题:

I want to create transparent system overlay window, which has several round views:

Green view is VISIBLE, red one is INVISIBLE. The thing is that I need red view to pass touches to the underlying window, but by default it doesn't.

I tried setting visibility of red view to GONE, but then overall size of containing view changes. Since I need the containing view to be snapped to the right edge of the screen, this means that position of green view changes, and I don't want this.

Is there any way to override default touch handling in INVISIBLE state?


Here's an actual screenshot to make my question more clear:

Also, I had to override dispatchTouchEvent() to dispatch touch events correctly:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    Circle target=null;
    int targetIndex=-1;
    for (int i=0; i<getChildCount(); i++) {
        Circle child=(Circle) getChildAt(i);
        if (child.viewMetrics.containsPoint(ev.getX(), ev.getY()) && (ev.getAction()==MotionEvent.ACTION_MOVE || child.isVisible())) {
            target=child;
            targetIndex=i;
            break;
        }
    }
    onMotionEvent(ev, target, targetIndex);
    Log.d(">| CircularLayout", "action: "+ev.getAction()+", target: "+target);
    return target!=null && target.dispatchTouchEvent(ev);
}

回答1:

Create custom view to do this. In such case you do not need any trickery related to visible invisible - it's you who decide what is your clickable area and also you who decies what area will alter the state (like is drawn as pressed on touch event). So your custom view should be of the size of desired area but in your onDraw() you shall only draw the change on that smaller inner area.

Here are basics on how to create custom views: http://developer.android.com/training/custom-views/index.html



回答2:

What I ended up doing is calculating two sets of view dimensions: maximum possible (size of the red area) and current (green area). When child view is hidden or shown I set width and height of window LayoutParams to current dimensions and then set difference between maximum and current dimensions to y and x parameters of LayoutParams.

For some reason applying modified LayoutParams triggers measure/layout pass twice (which in turn causes the view to "bounce"), but that seems to be the whole new story.