当Fragment遇见PopWindow

当Fragment遇见PopWindow_第1张图片

问题描述:

页签1控制Fragment1,页签2控制Fragmeng2。

Fragment1和Fragment2 上各有一个按钮,要求点击按钮弹出弹出框。

我们要求点击外部弹出框消失。

问题来了:当Fragment1 弹出popWindow 时,点击页签2,popwindow 消失了,但是fragment2没有切换。

原因:我们设置了setOutsideTouchable(true)。

当Fragment遇见PopWindow_第2张图片

什么意思呢,如何设置了了true,那么弹窗外的触摸事件将会分配给window。就是说导航签的触摸事件被window消费了,所以页签拿不到点击事件。

当Fragment遇见PopWindow_第3张图片

解决思路:

setOutsideTouchable(false)。那么并发症来了,当popwindow 处于showing状态时,点击页签外部都不生效。

事件是怎么传递的,我们能否自定义事件?

首先明白事件是怎么传递的:

事件由Activity--->Window-->DecorView-->ViewGroup-->View 一层一层分发下去。

当Fragment遇见PopWindow_第4张图片

ViewGrop 和View 的相同点是:都有dispathTouchEvent 和onTouchevent 方法。不同点是View 没有 onInterceptTouchEvent 方法。

灵感来了,我们可以在Activity的dispatchTouchEvent 中动手脚。

首先:popwindow的事件不会经过Activity 进行分发。

@Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int x = (int) ev.getRawX();//点击的x坐标
        int y = (int) ev.getRawY();//点击的y坐标

        if (fragment1!= null) {
                if (fragment1.mPopWindow != null && fragment1.mPopWindow.isShowing()) {
                    fragment1.mPopWindow.dismiss();
                    //是否点击当行页签
                    if (clickInBottomButton(x, y)) {
                    //事件交由actiivty分发处理,最终会默认达到页签
                        return super.dispatchTouchEvent(ev);
                    } else {
                     //事件不进行分发,如:我们不希望点击fragment1中列表中item,进行页面跳转
                        return false;
                    }
                }
            }

        if (fragment2!= null) {
                if (fragment2.mPopWindow != null && fragment2.mPopWindow.isShowing()) {
                    fragment2.mPopWindow.dismiss();
                    if (clickInBottomButton(x, y)) {
                        return super.dispatchTouchEvent(ev);
                    } else {
                        return false;
                    }
                }
            }
     
  return super.dispatchTouchEvent(ev);

}

点击排除区域:

RadioButton radioButton1 = findViewById(R.id.radio_button1);
private Rect fragment1ButtonReact= new Rect();
radioButton1.getGlobalVisibleRect(fragment1ButtonReact);//获取底部按钮区域
 /**
     *
     *排除点击区域
     * @param x
     * @param y
     * @return
     */
    public boolean clickInBottomButton(int x, int y) {
        if (clickInRect(x, y, fragment1ButtonReact)) {
            return true;
        }

        if (clickInRect(x, y, fragment2ButtonReact)) {
            return true;
        }

        return false;
    }

 

你可能感兴趣的:(android)