PopupWindow点击外部区域消失(二)
来源:互联网 发布:怎样注册中文.手机域名 编辑:程序博客网 时间:2024/06/07 17:51
很早之前有遇到过一个问题,点击打开链接就是 PopupWindow 在使用的时候必须要如下设置才可以在点击外部让它消失
而当 mBackgroud == null 的时候
<pre name="code" class="html"> pop.setBackgroundDrawable(new BitmapDrawable()); pop.setOutsideTouchable(true); pop.showAtLocation();
就是说在设置位置与是否点击消失之前必须要先setBackgroundDrawable();
之前也没有深究过此间缘由,正好今天有时间就追了一下PopupWindow的源码看了下,原来事情是这样的……
我们来看这段代码:
public void showAtLocation(IBinder token, int gravity, int x, int y) { if (isShowing() || mContentView == null) { return; } unregisterForScrollChanged(); mIsShowing = true; mIsDropdown = false; WindowManager.LayoutParams p = createPopupLayout(token); p.windowAnimations = computeAnimationResource(); <span style="color:#cc0000;">preparePopup(p);</span> if (gravity == Gravity.NO_GRAVITY) { gravity = Gravity.TOP | Gravity.START; } p.gravity = gravity; p.x = x; p.y = y; if (mHeightMode < 0) p.height = mLastHeight = mHeightMode; if (mWidthMode < 0) p.width = mLastWidth = mWidthMode; invokePopup(p); }
public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) { if (isShowing() || mContentView == null) { return; } registerForScrollChanged(anchor, xoff, yoff, gravity); mIsShowing = true; mIsDropdown = true; WindowManager.LayoutParams p = createPopupLayout(anchor.getWindowToken()); <span style="color:#cc0000;">preparePopup(p);</span> updateAboveAnchor(findDropDownPosition(anchor, p, xoff, yoff, gravity)); if (mHeightMode < 0) p.height = mLastHeight = mHeightMode; if (mWidthMode < 0) p.width = mLastWidth = mWidthMode; p.windowAnimations = computeAnimationResource(); invokePopup(p); }可以看到无乱你调用哪个显示方法都会进入一个 perparePopup(p);的方法。
下面我们来看这个方法做了些什么:
private void preparePopup(WindowManager.LayoutParams p) { if (mContentView == null || mContext == null || mWindowManager == null) { throw new IllegalStateException("You must specify a valid content view by " + "calling setContentView() before attempting to show the popup."); } <span style="color:#cc0000;">if (mBackground != null)</span> { final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams(); int height = ViewGroup.LayoutParams.MATCH_PARENT; if (layoutParams != null && layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) { height = ViewGroup.LayoutParams.WRAP_CONTENT; } // when a background is available, we embed the content view // within another view that owns the background drawable <span style="color:#cc0000;">PopupViewContainer</span> popupViewContainer = new PopupViewContainer(mContext); PopupViewContainer.LayoutParams listParams = new PopupViewContainer.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, height ); popupViewContainer.setBackground(mBackground); popupViewContainer.addView(mContentView, listParams); mPopupView = popupViewContainer; } <span style="color:#cc0000;">else</span> { mPopupView = mContentView; } mPopupView.setElevation(mElevation); mPopupViewInitialLayoutDirectionInherited = (mPopupView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT); mPopupWidth = p.width; mPopupHeight = p.height; }相信看到这里大家应该能看出点端倪来了吧,是的,它有个内部类 PopupViewContainer ,当 mBackground != null 的时候
mPopupView = popupViewContainer;而这个类继承于 FrameLayout ,那么下面再接着看这个类又做了什么事情使得必须要设置 mBackground !
@Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { if (getKeyDispatcherState() == null) { return super.dispatchKeyEvent(event); } if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { KeyEvent.DispatcherState state = getKeyDispatcherState(); if (state != null) { state.startTracking(event, this); } return true; } else if (event.getAction() == KeyEvent.ACTION_UP) { KeyEvent.DispatcherState state = getKeyDispatcherState(); if (state != null && state.isTracking(event) && !event.isCanceled()) { <span style="color:#cc0000;">dismiss();</span> return true; } } return super.dispatchKeyEvent(event); } else { return super.dispatchKeyEvent(event); } }
@Override public boolean onTouchEvent(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); if ((event.getAction() == MotionEvent.ACTION_DOWN) && ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) { <span style="color:#cc0000;">dismiss();</span> return true; } else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { <span style="color:#cc0000;">dismiss();</span> return true; } else { return super.onTouchEvent(event); } }原因找到了!!它是处理了触摸事件,当点击在view外部的时候都调用了 dismiss() 方法。
而当 mBackgroud == null 的时候
mPopupView = mContentView;而 mContentView 只是一个 View 的实例
private View mContentView;
由于篇幅原因,接下来会再续前言,而如果只想知道原理 的话那么就可以到此结束了。。
代码下载地址
PopupWindow点击外部区域消失(三)
0 0
- PopupWindow点击外部区域消失(二)
- PopupWindow点击外部区域消失(三)
- 点击PopupWindow 外部区域消失
- PopupWindow点击外部区域消失
- PopupWindow在点击外部区域的时候消失(二)
- 点击PopupWindow外部消失
- PopupWindow设置点击区域以外部分时自动消失
- PopupWindow点击外部区域不能消失的解决办法
- 点击popupwindow以外区域 popupwindow自动消失
- popupwindow点击其它区域自动消失
- PopupWindow点击外面区域自动消失
- Android Popupwindow 点击外部消失的实现
- popupwindow的基本应用,点击外部消失
- 关于点击popupwindow以外区域 popupwindow自动消失问题
- android:点击popupwindow以外区域 popupwindow自动消失(转载)
- 点击popupwindow窗口之外的区域使popupwindow消失
- android:点击popupwindow以外区域 popupwindow自动消失
- android:点击popupwindow以外区域 popupwindow自动消失
- Android 颜色Color(转)
- 【ASP.NET】Web中的Cookie写入与读取
- 《深入浅出struts2》--第七章,类型转换-支持与Collection一起使用
- 蚂蚁爬杆问题
- Android图
- PopupWindow点击外部区域消失(二)
- android webView js方法和java 方法交互
- js动态创建多个input框带删除按钮
- android查看进程stack的方法
- 流媒体时代,中国音乐行业的呐喊!
- Web开发、测试环境搭建(LAMP、SVN服务器、Laravel项目创建)
- 求最小公约数(辗转相除法<递归和非递归求法>)
- poj2559 Largest Rectangle in a Histogram
- SERVER1 ERROR