PopWindow基本使用

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

參考:https://www.jianshu.com/p/799dbb86f908

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章