PopupWindow点击外部区域消失(三)
2015-07-27 17:58
507 查看
续前言PopupWindow点击外部区域消失(二)
既然我们知道了为什么一定要先设置 mBackground 然后才能 dismiss PopupWindow,那么下面就来看怎么不用设置也能破之。。
首先还要来看这里:
既然 mBackgroud == null 的时候 mPopupView = mContentView;
那么我们可以为什么不可以通过自定义该View来处理它的点击事件呢,
在这里我自定义了一个LinearLayout ,下面来看它的实现,
细心的朋友应该会发现这段代码与 PopupViewContainer 的代码特别相似,不错就是照着它的来写的。。值得一提的是这个地方
这里呢,我定义了一个接口来实现它的 dismiss() 功能。
下面来看它的具体用法:
大家可以看到第 42,43行 我们并没有给他设置 mPopupWindow.setBackgroundDrawable(new BitmapDrawable());
它实现了上述的接口,然后在 onDismiss 里调用了 mPopupWindow.dismiss(); 然后来看,第57,58行代码给layout设置监听方法,它的布局是这样的:
然后在Activity里调用它就可以了,
这里是设置它从底部显示。。然后就大功告成了,这个并不是什么特别适用的功能,只是为了证明我们的猜想是正确的。。如有不足,请不吝赐教!
代码下载地址
既然我们知道了为什么一定要先设置 mBackground 然后才能 dismiss PopupWindow,那么下面就来看怎么不用设置也能破之。。
首先还要来看这里:
[code]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."); } if (mBackground != null){ 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 PopupViewContainer popupViewContainer = new PopupViewContainer(mContext); PopupViewContainer.LayoutParams listParams = new PopupViewContainer.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, height ); popupViewContainer.setBackground(mBackground); popupViewContainer.addView(mContentView, listParams); mPopupView = popupViewContainer; }else { **mPopupView = mContentView;** } mPopupView.setElevation(mElevation); mPopupViewInitialLayoutDirectionInherited = (mPopupView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT); mPopupWidth = p.width; mPopupHeight = p.height; }
既然 mBackgroud == null 的时候 mPopupView = mContentView;
那么我们可以为什么不可以通过自定义该View来处理它的点击事件呢,
在这里我自定义了一个LinearLayout ,下面来看它的实现,
[code]public class MyLinearLayout extends LinearLayout{ public MyLinearLayout(Context context) { this(context,null); } public MyLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); } private onMyDismissListener onMyDismissListener; public void setOnMyDismissListener(onMyDismissListener onMyDismissListener) { this.onMyDismissListener = onMyDismissListener; } private static final String TAG = "PopupWindow.MyLinearLayout"; private OnTouchListener mTouchInterceptor; /** * Set a callback for all touch events being dispatched to the popup * window. */ public void setTouchInterceptor(OnTouchListener l) { mTouchInterceptor = l; } @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()) { if(onMyDismissListener != null){ onMyDismissListener.onDismiss(); } return true; } } return super.dispatchKeyEvent(event); } else { return super.dispatchKeyEvent(event); } } @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (mTouchInterceptor != null && mTouchInterceptor.onTouch(this, ev)) { return true; } return super.dispatchTouchEvent(ev); } @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()))) { if(onMyDismissListener != null){ onMyDismissListener.onDismiss(); } return true; } else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { if(onMyDismissListener != null){ onMyDismissListener.onDismiss(); } return true; } else { return super.onTouchEvent(event); } } }
细心的朋友应该会发现这段代码与 PopupViewContainer 的代码特别相似,不错就是照着它的来写的。。值得一提的是这个地方
[code]if(onMyDismissListener != null){ onMyDismissListener.onDismiss(); }
这里呢,我定义了一个接口来实现它的 dismiss() 功能。
[code]public interface onMyDismissListener { void onDismiss(); }
下面来看它的具体用法:
[code]public class MyPopupWindow implements onMyDismissListener{ private static final String TAG = "MyPopupWindow"; public Context mContext; private PopupWindow mPopupWindow; private PopupWindowType type; public PopupWindowType getType() { return type; } public void setType(PopupWindowType type) { this.type = type; } public MyPopupWindow(Context context,PopupWindowType type, int width, int height, boolean focusable) { this.mContext = context; if(type == null){ type = PopupWindowType.TYPE_1; } View view = inflaterView(type); mPopupWindow = new PopupWindow(view, width, height, focusable); // mPopupWindow.setBackgroundDrawable(new BitmapDrawable()); Drawable background = mPopupWindow.getBackground(); Log.v(TAG, ""+background); mPopupWindow.setAnimationStyle(R.style.Animation); mPopupWindow.setOutsideTouchable(focusable); } private View inflaterView(PopupWindowType type){ View contentView; switch (type) { case TYPE_1: default: contentView = LayoutInflater.from(mContext).inflate(R.layout.popup_view, null); try { MyLinearLayout layout = (MyLinearLayout) contentView.findViewById(R.id.mll); layout.setOnMyDismissListener(this); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); Log.e(TAG, "You must set a id name is rId's name " + " in rootlayout"); } break; } return contentView; } @Override public void onDismiss() { mPopupWindow.dismiss(); } public void showAtLocation(View findViewById, int gravity, int x, int y) { // TODO Auto-generated method stub mPopupWindow.showAtLocation(findViewById, gravity, x, y); } }
大家可以看到第 42,43行 我们并没有给他设置 mPopupWindow.setBackgroundDrawable(new BitmapDrawable());
它实现了上述的接口,然后在 onDismiss 里调用了 mPopupWindow.dismiss(); 然后来看,第57,58行代码给layout设置监听方法,它的布局是这样的:
[code]<?xml version="1.0" encoding="utf-8"?> <com.xfchen.opensource.widget.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/mll" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/shape_popup_bg" android:orientation="vertical" > // 可以自行添加布局 </com.xfchen.opensource.widget.MyLinearLayout>
然后在Activity里调用它就可以了,
[code] private void showPopupWindow(){ MyPopupWindow myPopupWindow = new MyPopupWindow(this, PopupWindowType.TYPE_1, LayoutParams.MATCH_PARENT, 500, true); myPopupWindow.showAtLocation(MainActivity.this.findViewById(R.id.rlMain), Gravity.BOTTOM|Gravity.CENTER_VERTICAL, 0, 0); }
这里是设置它从底部显示。。然后就大功告成了,这个并不是什么特别适用的功能,只是为了证明我们的猜想是正确的。。如有不足,请不吝赐教!
代码下载地址
相关文章推荐
- hadoop集群安装(多机,非伪集群)
- 在32位ubuntu中安装docker并且成功启动容器
- errno值(linux )
- operator 的主要用法
- RGB图像转换到CIELab空间的研究及优化
- css 网站大背景(按比例缩放背景图片)
- 阿里云Linux新手入门一
- 解决Linux系统在设置alias命令重启后失效的问题
- 让 Vim 支持 nginx 语法(syntax) 格式化配置文件
- 【linux高级程序设计】(第九章)进程间通信-管道 2
- 运维必须掌握的Linux面试题
- Centos6.3 中文输入法
- opencv各类滤波器详解
- SAP HANA 高可用性 (High Availability) 解决方案 (二) - Host Auto-Failover, 节点失效自动切换
- linux学习
- PopupWindow点击外部区域消失(二)
- CentOS6.6下安装JDK7
- 查看linux系统的版本,查看linux系统对的位数
- with admin option 与with grant option
- 系统架构师经验总结