Android打造自定义通用popWindow

日常android开发中经常会用到popWindow。因此封装一个可自定义view,可设置弹出动画,可设置大小的通用popWindow显得尤为重要。

 
效果图如下:
在这里插入图片描述

通用PopWindow分为如下3部分:

1.自定义popWindow
2.popWindow的辅助类
3.popWindow的弹出动画
4.popWindow的使用

1.自定义popWindow

/*
 * 通用的popWindow
 */
public class CommonPopupWindow extends PopupWindow {

    private PopupController controller;

    @Override
    public int getWidth() {
        return controller.mPopupView.getMeasuredWidth();
    }

    @Override
    public int getHeight() {
        return controller.mPopupView.getMeasuredHeight();
    }

    public interface ViewInterface {
        void getChildView(View view, int layoutResId);
    }

    private CommonPopupWindow(Context context) {
        controller = new PopupController(context, this);
    }

    @Override
    public void dismiss() {
        super.dismiss();
        controller.setBackGroundLevel(1.0f);
    }

    public static class Builder {
        private final 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布局
         * @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
         *
         * @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;
            params.bg_level = level;
            return this;
        }

        /**
         * 是否可点击Outside消失
         *
         * @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;
        }

        public CommonPopupWindow create() {
            final CommonPopupWindow popupWindow = new CommonPopupWindow(params.mContext);
            params.apply(popupWindow.controller);
            if (listener != null && params.layoutResId != 0) {
                listener.getChildView(popupWindow.controller.mPopupView, params.layoutResId);
            }
            //测量View的宽高
            int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
            int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
            popupWindow.controller.mPopupView.measure(w, h);
            return popupWindow;
        }


    }
}

2.popWindow的辅助类

/*
*用pop辅助类(只会在CommonPopupWindow中被用到)
 */
public class PopupController {

    private int layoutResId; //布局id

    private Context context;

    private PopupWindow popupWindow;

    public View mPopupView; //弹窗布局View

    private View mView;

    private Window mWindow;

    public 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
     */
    public 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.setOutsideTouchable(touchable);//设置outside可点击
        popupWindow.setFocusable(touchable);
    }


    public 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);//设置outside可点击
            if (isShowBg) {
                //设置背景
                controller.setBackGroundLevel(bg_level);
            }
            if (isShowAnim) {
                controller.setAnimationStyle(animationStyle);
            }
        }
    }
}

3.popWindow的弹出动画

淡入:pop_fade_in_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <alpha
        android:duration="200"
        android:fromAlpha="0.0"
        android:toAlpha="1.0" />
</set>

 
淡出:pop_fade_out_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <alpha
        android:duration="200"
        android:fromAlpha="1.0"
        android:toAlpha="0.0" />
</set>

style.xml

<style name="pop_anim" parent="android:Animation">
    <item name="android:windowEnterAnimation">@anim/pop_fade_in_anim</item>
    <item name="android:windowExitAnimation">@anim/pop_fade_out_anim</item>
</style>

4.popWindow的使用


public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        ImageView addMore = findViewById(R.id.add_more_iv);
        addMore.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                CommonPopupWindow popupWindow = new CommonPopupWindow.Builder(MainActivity.this)
                        .setView(R.layout.popwindow_add_more)
                        .setWidthAndHeight(DensityUtils.dp2px(MainActivity.this, 140),
                                DensityUtils.dp2px(MainActivity.this, 140))
                        .setAnimationStyle(R.style.pop_anim)
                        .setViewOnclickListener(new CommonPopupWindow.ViewInterface() {
                            @Override
                            public void getChildView(View view, int layoutResId) {
                                TextView addFriends = view.findViewById(R.id.add_friends);
                                TextView startWeChat = view.findViewById(R.id.start_we_chat);
                                TextView scan = view.findViewById(R.id.scan);

                                addFriends.setOnClickListener(itemsOnClick);
                                startWeChat.setOnClickListener(itemsOnClick);
                                scan.setOnClickListener(itemsOnClick);
                            }
                        })
                        .setOutsideTouchable(true)
                        .create();

                popupWindow.showAsDropDown(v);

            }
        });
    }

    private View.OnClickListener itemsOnClick = new View.OnClickListener() {

        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.add_friends:
                    Toast.makeText(MainActivity.this,"添加朋友",Toast.LENGTH_SHORT).show();
                    break;
                case R.id.start_we_chat:
                    Toast.makeText(MainActivity.this,"发起群聊",Toast.LENGTH_SHORT).show();
                    break;
                case R.id.scan:
                    Toast.makeText(MainActivity.this,"扫一扫",Toast.LENGTH_SHORT).show();
                    break;
                default:
                    break;
            }
        }
    };
}

至于上面调整popWindow大小用到的dp转换工具类DensityUtils.java,我就不贴出来了,网上一大堆。popWindow的背景用到的点9图,大家需要的话,可点击下载 带箭头的点9图
 
补充一点,关于popWindow的弹出位置可使用

 popupWindow.showAsDropDown(v);
 //或者
 mPopwindow.showAtLocation(v,Gravity.xxx, 0, 0);

  
写完之后发现一个好像挺不错的博文,贴出来吧。
拒绝无用功,封装一个通用的 PopupWindow

 
好了,完了。有问题,请留言。

猜你喜欢

转载自blog.csdn.net/zhangqunshuai/article/details/85100427
今日推荐