znq
znq

Reputation: 44973

Android: delegate touch event to underlaying view

I have the following hierarchy: Activity -> PopupWindow -> CustomView

My the PopupWindow itself is a square, but transparent, so you can see the Activity sitting in the background. The CustomView is a circle embedded inside the PopupWindow. alt text

What I have achieved so far is

  1. User clicks on green circle and I invoke "some stuff"
  2. User clicks outside of the PopupWindow and the touch event gets dispatched to the Activity.

The missing part is now, to dispatch any touch event that happens inside the PopupWindow but outside the CustomView (circle) to the Activity.

I already know how to sense when the touch is outside of my circle. I just have problems delegating it to the Activity.

In my CustomView I have the following in onTouch

if (radiusTouch > maxRadius) {
    return false;
}

In my PopupWindow I already setup the following, but it gets never called:

popup.setTouchInterceptor(new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.i(TAG, "PopupWindow :: onTouch()");
        return false;
    }
});

Anything else I have to do to delegate the touch event all the way to the Activity?

Upvotes: 22

Views: 14509

Answers (3)

Kiran Parmar
Kiran Parmar

Reputation: 788

Try setting these on your PopupWindow instance:

window.setBackgroundDrawable(new BitmapDrawable());

window.setOutsideTouchable(true);

and

window.setTouchable(true);

This is just a suggestion... I haven't tested it. Let me know if it works.

[Note: This is for the onTouch() to get called on touch events..]

Upvotes: 3

alex2k8
alex2k8

Reputation: 43214

Consider the FLAG_NOT_TOUCH_MODAL:

/** Window flag: Even when this window is focusable (its
  * {@link #FLAG_NOT_FOCUSABLE is not set), allow any pointer events
  * outside of the window to be sent to the windows behind it.  Otherwise
  * it will consume all pointer events itself, regardless of whether they
  * are inside of the window. */
public static final int FLAG_NOT_TOUCH_MODAL    = 0x00000020;

You can use this code to upate the window flags after the popup window was shown.

FrameLayout popupContainer = (FrameLayout)contentView.getParent();
WindowManager.LayoutParams p = (WindowManager.LayoutParams)popupContainer.getLayoutParams();
p.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
WindowManager windowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
windowManager.updateViewLayout(popupContainer, p);

Upvotes: 13

Vagrant
Vagrant

Reputation: 1716

It's too bad that the PopupWindow is not a subclass of ViewGroup or even View. Then you could override dispatchTouchEvent. Can you modify your custom view to know about the PopupWindow and call dismiss() on it when there is a click outside the circle?

Upvotes: 0

Related Questions