您好,登錄后才能下訂單哦!
本篇內容主要講解“怎么封裝PopupWindow”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“怎么封裝PopupWindow”吧!
PopupWindow 表示一個彈窗,類似于 AlertDialog,相較 AlertDialog 來說 PopupWindow 使用起來更靈活,可有任意指定要顯示的位置,當然能夠靈活的使用必然在某一層面有所犧牲,如 PopupWindow 相較 AlertDialog 沒有默認的布局,每次都得專門創建彈窗的布局,這一點來說 AlertDialog 就比較方便了,所以在開發中沒有最好的解決方案,要根據具體的需求選擇最合適的解決方案。
PopupWindow 的創建,具體如下:
//構造方法
public PopupWindow (Context context)
public PopupWindow(View contentView)
public PopupWindow(View contentView,
int width,
int height)
public PopupWindow(View contentView,
int width,
int height, boolean focusable)
PopupWindow 的常用屬性設置,具體如下:
//設置View(必須)
window.setContentView(contentView);
//設置寬(必須)
window.setWidth(WindowManager.LayoutParams.MATCH_PARENT);
//設置高(必須)
window.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
//設置背景
window.setBackgroundDrawable(new ColorDrawable(Color.GRAY));
//設置PopupWindow之外的觸摸事件
window.setOutsideTouchable(true);
//設置PopupWindow消失的監聽器
window.setOnDismissListener(this);
//設置PopupWindow上的觸摸事件
window.setTouchable(true);
//設置PopupWindow彈出動畫
window.setAnimationStyle(R.style.PopupWindowTranslateTheme);
PopupWindow 的顯示有兩種設置方式,一種是基于坐標,另一種是基于某個 View ,具體如下:
//基于坐標,參數(當前窗口的某個 View,位置,起始坐標x, 起始坐標y)
void showAtLocation (View parent,
int gravity,
int x,
int y)
//基于某個View,參數(附著的View,x 方向的偏移量,y 方向的偏移量)
void showAsDropDown (View anchor,
int xoff,
int yoff,
int gravity)
void showAsDropDown (View anchor,
int xoff,
int yoff)
void showAsDropDown (View anchor)
PopupWindow 的主要內容基本如上,下面使用原生的 PopupWindow 實現一個彈窗,下面是關鍵代碼,具體如下:
//創建PopupWindow
PopupWindow
window =
new PopupWindow(this);
//設置顯示View
window.setContentView(contentView);
//設置寬高
window.setWidth(WindowManager.LayoutParams.MATCH_PARENT);
window.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
//設置背景
window.setBackgroundDrawable(new ColorDrawable(Color.GRAY));
//設置PopupWindow之外的觸摸事件
window.setOutsideTouchable(true);
//設置PopupWindow消失的監聽器
window.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
//監聽PopupWindow的消失
}
});
//設置PopupWindow上的觸摸事件
window.setTouchable(true);
//設置PopupWindow彈出動畫
window.setAnimationStyle(R.style.PopupWindowTranslateTheme);
window.showAtLocation(btnTarget, Gravity.BOTTOM | Gravity.CENTER,
0,
0);
下面是顯示效果,具體如下:
這里對 PopupWindow 的封裝主要是對 PopupWindow 常用擺放位置做進一步封裝,使 PopupWindow 的調用更加靈活、簡潔。
在封裝過程中遇到的問題是不能正確獲取到 PopupWindow 的寬高,正確獲取寬高的方法是先對 PopupWindow 進行測量,然后再獲取其寬高,具體如下:
//獲取PopupWindow的寬高
mPopupWindow.getContentView().measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
int popupWidth = mPopupWindow.getContentView().getMeasuredWidth();
int popupHeight = mPopupWindow.getContentView().getMeasuredHeight();
對 PopupWindow 的封裝使用了建造者設計模式,下面看一下 PopupWindow 的默認配置,具體如下:
public Builder(Context context) {
this.context = context;
this.popupWindow =
new PopupWindow(context);
//默認PopupWindow響應觸摸事件
this.outsideTouchable =
true;
//默認響應觸摸事件
this.touchable =
true;
//默認背景透明
this.backgroundDrawable =
new ColorDrawable(Color.TRANSPARENT);
//默認寬高為WRAP_CONTENT
this.width = WindowManager.LayoutParams.WRAP_CONTENT;
this.height = WindowManager.LayoutParams.WRAP_CONTENT;
//默認Gravity為Gravity.CENTER
this.gravity = Gravity.CENTER;
this.layoutId =
-1;
//默認偏移量為0
this.offsetX =
0;
this.offsetY =
0;
//...
}
由于寬高、背景、是否可點擊等相關屬性已經設置了默認值,使用時根據自己的需求設置相關屬性,如 PopupWindow 的動畫等,所以這些設置肯定是非必須的,那么那些事創建時必須的呢。
下面是對 PopupWindow 封裝類 MPopupWindow 的初始化,具體如下:
private void setPopupWindowConfig(MPopupWindow
window) {
if (contentView !=
null && layoutId !=
-1){
throw new MException("setContentView and setLayoutId can't be used together.",
"0");
}else if (contentView ==
null && layoutId ==
-1){
throw new MException("contentView or layoutId can't be null.",
"1");
}
if (context ==
null) {
throw new MException("context can't be null.",
"2");
}
else {
window.mContext =
this.context;
}
window.mWidth =
this.width;
window.mHeight =
this.height;
window.mView =
this.contentView;
window.mLayoutId = layoutId;
window.mPopupWindow =
this.popupWindow;
window.mOutsideTouchable =
this.outsideTouchable;
window.mBackgroundDrawable =
this.backgroundDrawable;
window.mOnDismissListener =
this.onDismissListener;
window.mAnimationStyle =
this.animationStyle;
window.mTouchable =
this.touchable;
window.mOffsetX =
this.offsetX;
window.mOffsetY =
this.offsetY;
window.mGravity =
this.gravity;
}
}
顯然,這里可以看出 context 和 contentView 或 layoutId 是必須需要設置的,如果沒有設置相應的會有錯誤提示,當然在封裝中也對 contentView 和 layoutId 不能同時使用做了限制和如果使用了兩者的錯誤提示。
下面是對外提供的顯示 PopupWindow 的方法,根據不同的枚舉類型將 PopupWindow 顯示在不同的位置,具體如下:
public void showPopupWindow(View v, LocationType
type) {
if (mView!=null){
mPopupWindow.setContentView(mView);
}else if (mLayoutId != -1){
View contentView = LayoutInflater.from(mContext).inflate(mLayoutId, null);
mPopupWindow.setContentView(contentView);
}
mPopupWindow.setWidth(mWidth);
mPopupWindow.setHeight(mHeight);
mPopupWindow.setBackgroundDrawable(mBackgroundDrawable);
mPopupWindow.setOutsideTouchable(mOutsideTouchable);
mPopupWindow.setOnDismissListener(mOnDismissListener);
mPopupWindow.setAnimationStyle(mAnimationStyle);
mPopupWindow.setTouchable(mTouchable);
//獲取目標View的坐標
int[] locations = new int[2];
v.getLocationOnScreen(locations);
int left = locations[0];
int top = locations[1];
//獲取PopupWindow的寬高
mPopupWindow.getContentView().measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
int popupWidth = mPopupWindow.getContentView().getMeasuredWidth();
int popupHeight = mPopupWindow.getContentView().getMeasuredHeight();
switch (type) {
case TOP_LEFT:
mPopupWindow.showAtLocation(v,Gravity.NO_GRAVITY,left - popupWidth + mOffsetX,top - popupHeight + mOffsetY);
break;
case TOP_CENTER:
int offsetX = (v.getWidth() - popupWidth) / 2;
mPopupWindow.showAtLocation(v,Gravity.NO_GRAVITY,left + offsetX + mOffsetX,top - popupHeight + mOffsetY);
break;
case TOP_RIGHT:
mPopupWindow.showAtLocation(v,Gravity.NO_GRAVITY,left + v.getWidth() + mOffsetX,top - popupHeight + mOffsetY);
break;
case BOTTOM_LEFT:
mPopupWindow.showAsDropDown(v, -popupWidth + mOffsetX,mOffsetY);
break;
case BOTTOM_CENTER:
int offsetX1 = (v.getWidth() - popupWidth) / 2;
mPopupWindow.showAsDropDown(v,offsetX1 + mOffsetX,mOffsetY);
break;
case BOTTOM_RIGHT:
mPopupWindow.showAsDropDown(v, v.getWidth() + mOffsetX,mOffsetY);
break;
case LEFT_TOP:
mPopupWindow.showAtLocation(v, Gravity.NO_GRAVITY, left - popupWidth + mOffsetX, top - popupHeight + mOffsetY);
break;
case LEFT_BOTTOM:
mPopupWindow.showAtLocation(v, Gravity.NO_GRAVITY, left - popupWidth + mOffsetX, top + v.getHeight() + mOffsetY);
break;
case LEFT_CENTER:
int offsetY = (v.getHeight() - popupHeight) / 2;
mPopupWindow.showAtLocation(v, Gravity.NO_GRAVITY,left - popupWidth + mOffsetX,top + offsetY + mOffsetY);
break;
case RIGHT_TOP:
mPopupWindow.showAtLocation(v, Gravity.NO_GRAVITY, left + v.getWidth() + mOffsetX,top - popupHeight + mOffsetY);
break;
case RIGHT_BOTTOM:
mPopupWindow.showAtLocation(v, Gravity.NO_GRAVITY, left + v.getWidth() + mOffsetX,top + v.getHeight() + mOffsetY);
break;
case RIGHT_CENTER:
int offsetY1 = (v.getHeight() - popupHeight) / 2;
mPopupWindow.showAtLocation(v, Gravity.NO_GRAVITY,left + v.getWidth() + mOffsetX,top + offsetY1 + mOffsetY);
break;
case FROM_BOTTOM:
mPopupWindow.showAtLocation(v,mGravity,mOffsetX,mOffsetY);
break;
}
}
下面是使用封裝后的 PopupWindow,只需四行代碼就可以顯示一個默認的 PopupWindow 了,具體如下:
private void showPopupWindow(MPopupWindow.LocationType
type) {
MPopupWindow popupWindow =
new MPopupWindow
.Builder(this)
.setLayoutId(R.layout.popup_window_layout)
.build();
popupWindow.showPopupWindow(btnTarget,
type);
}
由于默認 PopupWindow 背景是透明的,建議測試時設置背景。
下面是 PopupWindow 在各個位置的顯示,具體如下:
到此,相信大家對“怎么封裝PopupWindow”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。