问题描述:
页签1控制Fragment1,页签2控制Fragmeng2。
Fragment1和Fragment2 上各有一个按钮,要求点击按钮弹出弹出框。
我们要求点击外部弹出框消失。
问题来了:当Fragment1 弹出popWindow 时,点击页签2,popwindow 消失了,但是fragment2没有切换。
原因:我们设置了setOutsideTouchable(true)。
什么意思呢,如何设置了了true,那么弹窗外的触摸事件将会分配给window。就是说导航签的触摸事件被window消费了,所以页签拿不到点击事件。
解决思路:
setOutsideTouchable(false)。那么并发症来了,当popwindow 处于showing状态时,点击页签外部都不生效。
事件是怎么传递的,我们能否自定义事件?
首先明白事件是怎么传递的:
事件由Activity--->Window-->DecorView-->ViewGroup-->View 一层一层分发下去。
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;
}