PopupWindow点击外部区域消失(三)

来源:互联网 发布:淘宝视频直播内容下载 编辑:程序博客网 时间:2024/05/17 21:48

续前言PopupWindow点击外部区域消失(二)
既然我们知道了为什么一定要先设置 mBackground 然后才能 dismiss PopupWindow,那么下面就来看怎么不用设置也能破之。。
首先还要来看这里:

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 ,下面来看它的实现,

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 的代码特别相似,不错就是照着它的来写的。。值得一提的是这个地方

if(onMyDismissListener != null){                onMyDismissListener.onDismiss();            }

这里呢,我定义了一个接口来实现它的 dismiss() 功能。

public interface onMyDismissListener {    void onDismiss();}

下面来看它的具体用法:

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设置监听方法,它的布局是这样的:

<?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里调用它就可以了,

    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);    }

这里是设置它从底部显示。。然后就大功告成了,这个并不是什么特别适用的功能,只是为了证明我们的猜想是正确的。。如有不足,请不吝赐教!
代码下载地址

0 0
原创粉丝点击