PopWindow基本使用
PopWindow,類似Dialog 也是可以設置自定義view,設置窗體大小和位置
網上很多人說 PopWindow是阻塞線程的 而 AlertDialog是非阻塞線程的,其實我覺得不太對。
PopWindow和AlertDialog應該都不會阻塞線程的,至於他們說的阻塞線程,只是當設置了 setOutSideTouchable爲true時(且此時的 focusable 要爲 true ,爲false也是可以點擊外部的),點擊外部並不會觸發外部的點擊事件,而只是關閉了 popwindow。但是當setOutSideTouchable爲false時(此時的 focusable 要爲false 爲true時點擊還是會關閉popwindow的),點擊不會關閉PopWindow,並且是可以觸發點擊外部事件的。
大家可以測試一下,如果我寫錯了 歡迎評論指正~
相應點擊事件中:
// product_list_view爲自定義的xml文件
View productListView = LayoutInflater.from(this).inflate(R.layout.product_list_view, null);
方式1:
// 創建popwindow 設置長寬
PopupWindow popWindow = new PopupWindow(productListView, 780, 900);
方式2
也可以通過這種方式取代方式1
popWindow = new PopupWindow(this);
popWindow.setContentView(productListView);
popWindow.setWidth(750);
popWindow.setHeight(888);
但是要注意的 是必須要設置長寬 否則不顯示!
設置點擊外部可消失
注意!!!
1 要調用setBackgroundDrawable方法
2 這裏的setOutsideTouchable 不是說能否點擊外部,只是 點擊外部 popwindow 消失與否!!!若爲true 則點擊外部消失 而外部的點擊事件不響應, 若爲false 則點擊外部不消失,但是外部的點擊事件是可以響應的
3 還有 若setFocusable( true ) + setOutsideTouchable ( false ) 點擊區域外依然 popwindow會消失
popWindow.setOutsideTouchable(true); //必須設置背景
popWindow.setBackgroundDrawable(null);
設置是否獲取焦點
默認爲false
popWindow.setFocusable()
呈現:
設置呈現的位置:
//相對於父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以設置偏移或無偏移
popWindow.showAtLocation(view, Gravity.CENTER, 0, 0);
或者
//直接顯示在參照View 的左下方
popWindow.showAsDropDown(View anchor);
//可以通過xoff,yOff,來調節x,y方向的偏移
popWindow.showAsDropDown(View anchor, int xoff, int off)
//相對於整個屏幕的window而言,通過gravity調整顯示在左、上、右、下、中. x,y調整兩個方向的偏移
popWindow.showAsDropDown(View parent, int gravity, int x, int y)
背景變暗設置:
private Window mWindow;
點擊背景變暗:原理是通過點擊彈出框同時讓Activity的透明度降低
mWindow = getWindow();
WindowManager.LayoutParams params = mWindow.getAttributes();
params.alpha = 0.7f;
mWindow.setAttributes(params);
彈出框消失恢復Activity亮度:
popWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
if(mWindow!=null){
WindowManager.LayoutParams params = mWindow.getAttributes();
params.alpha = 1.0f;
mWindow.setAttributes(params);
}
}
});
完整代碼:
// item點擊事件
@Override
public void onItemClick(View view, int position) {
popWindow(view);
}
private void popWindow(View view){
// 設置背景變暗
mWindow = getWindow();
WindowManager.LayoutParams params = mWindow.getAttributes();
params.alpha = 0.7f;
mWindow.setAttributes(params);
// 設置彈出框
View productListView = LayoutInflater.from(this).inflate(R.layout.product_list_view, null);
PopupWindow popWindow = new PopupWindow(productListView, 780, 900);
popWindow.setOutsideTouchable(true); //必須設置背景 即使爲null或者透明 否則點擊外部不會消失
popWindow.setBackgroundDrawable(null);
//相對於父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以設置偏移或無偏移
popWindow.showAtLocation(view, Gravity.CENTER, 0, 0);
popWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
if(mWindow!=null){
WindowManager.LayoutParams params = mWindow.getAttributes();
params.alpha = 1.0f;
mWindow.setAttributes(params);
}
}
});
}
若無view傳遞,則:
popWindow.showAtLocation(findViewById(R.id.recyclerView),Gravity.CENTER, 0, 0);
記得在點擊了popwindow裏面的控件跳轉界面,或者Activity結束時 dismiss掉PopWindow 避免內存泄漏
@Override
protected void onDestroy(){
super.onDestroy();
if(customPopWindow!=null && customPopWindow.isShowing()){
customPopWindow.dismiss();
}
}
封裝,通過建造者模式,進行鏈式操作
import android.content.Context;
import android.view.View;
import android.widget.PopupWindow;
/**
* popWindow的封裝類 繼承 android自帶的 popwindow
*/
public class CustomPopWindow extends PopupWindow{
// 聲明 popwindow控制器
PopupController pController;
// private的構造函數 避免外部調用
private CustomPopWindow(Context context) {
pController = new PopupController(context, this);
}
@Override
public int getWidth() {
return pController.mPopupView.getMeasuredWidth();
}
@Override
public int getHeight() {
return pController.mPopupView.getMeasuredHeight();
}
@Override
public void dismiss() {
super.dismiss();
pController.setBackGroundLevel(1.0f);
}
// 提供 popwindow內部控件操作的接口
public interface ViewInterface {
void getChildView(View view, int layoutResId);
}
// 建造者模式 通過Builder 暴露方法給外部鏈式調用 並獲取相關參數
public static class Builder {
// 聲明 popwindow控制器的參數類 用於 外部賦予各種參數給 控制器 去 呈現不同的效果
private PopupController.PopupParams params;
// 聲明 接口
private ViewInterface listener;
// 構造方法 創建 參數類對象
public Builder(Context context) {
params = new PopupController.PopupParams(context);
}
/**
* @param layoutResId 設置PopupWindow 佈局ID形式
* @return Builder
*/
public Builder setView(int layoutResId) {
params.mView = null;
params.layoutResId = layoutResId;
return this;
}
/**
* @param view 設置PopupWindow佈局 view形式
* @return Builder
*/
public Builder setView(View view) {
params.mView = view;
params.layoutResId = 0;
return this;
}
/**
* 設置子View 的監聽器
*
* @param listener ViewInterface
* @return Builder
*/
public Builder setViewOnclickListener(ViewInterface listener) {
this.listener = listener;
return this;
}
/**
* 設置寬度和高度 如果不設置 默認是wrap_content (popwindow必須設置 而這裏可以通過參數類自己賦一個初值爲wrapConent)
*
* @param width 寬
* @return Builder
*/
public Builder setWidthAndHeight(int width, int height) {
params.mWidth = width;
params.mHeight = height;
return this;
}
/**
* 設置背景灰色程度
*
* @param level 0.0f-1.0f
* @return Builder
*/
public Builder setBackGroundLevel(float level) {
params.isShowBg = true; // 設置背景 因爲要設置點擊外部消失popwindow要設置背景
params.bg_level = level;
return this;
}
/**
* 是否可點擊外部 popwindow消失 注意這裏只是popwindow消失與否 並不是能否點擊外部與否 都是能夠點擊外部的點擊事件的
*
* @param touchable 是否點擊消失
* @return Builder
*/
public Builder setOutsideTouchable(boolean touchable) {
params.isTouchable = touchable;
return this;
}
/**
* 設置動畫
*
* @return Builder
*/
public Builder setAnimationStyle(int animationStyle) {
params.isShowAnim = true;
params.animationStyle = animationStyle;
return this;
}
// 設置完 以上各種屬性 則創建popwindow
public CustomPopWindow create() {
CustomPopWindow popupWindow = new CustomPopWindow(params.mContext);
params.apply(popupWindow.pController);
if (listener != null && params.layoutResId != 0) {
listener.getChildView(popupWindow.pController.mPopupView, params.layoutResId);
}
// ViewUtil.measureWidthAndHeight(popupWindow.pController.mPopupView);
return popupWindow;
}
}
}
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.PopupWindow;
/**
* 操作 popwindow的 控制類
*/
class PopupController {
private int layoutResId;//佈局id
private Context context;
private PopupWindow popupWindow;
View mPopupView;//彈窗佈局View
private View mView;
private Window mWindow;
PopupController(Context context, PopupWindow popupWindow) {
this.context = context;
this.popupWindow = popupWindow;
}
public void setView(int layoutResId) {
mView = null;
this.layoutResId = layoutResId;
installContent();
}
public void setView(View view) {
mView = view;
this.layoutResId = 0;
installContent();
}
private void installContent() {
if (layoutResId != 0) {
mPopupView = LayoutInflater.from(context).inflate(layoutResId, null);
} else if (mView != null) {
mPopupView = mView;
}
popupWindow.setContentView(mPopupView);
}
/**
* 設置寬度
*
* @param width 寬
* @param height 高
*/
private void setWidthAndHeight(int width, int height) {
if (width == 0 || height == 0) {
//如果沒設置寬高,默認是WRAP_CONTENT
popupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
} else {
popupWindow.setWidth(width);
popupWindow.setHeight(height);
}
}
/**
* 設置背景灰色程度
*
* @param level 0.0f-1.0f
*/
void setBackGroundLevel(float level) {
mWindow = ((Activity) context).getWindow();
WindowManager.LayoutParams params = mWindow.getAttributes();
params.alpha = level;
mWindow.setAttributes(params);
}
/**
* 設置動畫
*/
private void setAnimationStyle(int animationStyle) {
popupWindow.setAnimationStyle(animationStyle);
}
/**
* 設置Outside是否可點擊
*
* @param touchable 是否可點擊
*/
private void setOutsideTouchable(boolean touchable) {
popupWindow.setBackgroundDrawable(new ColorDrawable(0x00000000));//設置爲透明背景
popupWindow.setFocusable(touchable); // 這裏設置爲默認可聚焦 因爲下面設置了 默認touchable爲true popwindow默認爲false的
popupWindow.setOutsideTouchable(touchable);//設置outside可點擊
}
static class PopupParams {
public int layoutResId;//佈局id
public Context mContext;
public int mWidth, mHeight;//彈窗的寬和高
public boolean isShowBg, isShowAnim;
public float bg_level;//屏幕背景灰色程度
public int animationStyle;//動畫Id
public View mView;
public boolean isTouchable = true; // 默認爲 點擊消失
public PopupParams(Context mContext) {
this.mContext = mContext;
}
public void apply(PopupController controller) {
if (mView != null) {
controller.setView(mView);
} else if (layoutResId != 0) {
controller.setView(layoutResId);
} else {
throw new IllegalArgumentException("PopupView's contentView is null");
}
controller.setWidthAndHeight(mWidth, mHeight);
controller.setOutsideTouchable(isTouchable);
if (isShowBg) {
//設置背景透明度
controller.setBackGroundLevel(bg_level);
}
if (isShowAnim) {
controller.setAnimationStyle(animationStyle);
}
}
}
}
使用:
private CustomPopWindow customPopWindow;
customPopWindow = new CustomPopWindow.Builder(OAListActivity.this)
.setView(R.layout.oa_list_choose)
.setWidthAndHeight(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT)
.setBackGroundLevel(0.7f)
.setViewOnclickListener(listChooseListener)
.setOutsideTouchable(true)
.create();
customPopWindow.showAsDropDown(findViewById(R.id.rightButton),0,0);
private CustomPopWindow.ViewInterface listChooseListener = new CustomPopWindow.ViewInterface() {
@Override
public void getChildView(View view, int layoutResId) {
LinearLayout linearLayout1 = view.findViewById(R.id.ll_1);
linearLayout1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intentToQingJiaDan = new Intent(OAListActivity.this,QingJiaDanActivity.class);
startActivityForResult(intentToQingJiaDan,0x05);
customPopWindow.dismiss(); // 設置點擊跳轉 dismiss
}
});
}
};