Android 开发之通用的 PopupWindow

PopupWindow 这个类用来实现一个弹出框,可以使用任意布局的 View 作为其内容,这个弹出框是悬浮在当前 activity 之上的。

效果图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HaX5p9CD-1575526739000)(https://img-my.csdn.net/uploads/201706/15/1497505682_8071.gif-thumb.jpg)]

1,向下弹出用到了 RecyclerView 所以我们在 app 文件夹下的 build.gradle 添加:

compile 'com.android.support:recyclerview-v7:25.2.0'
compile 'com.zhy:base-rvadapter:3.0.3'

2,封装一个通用的 CommonPopupWindow.java

package com.gyq.popupwindowtest.pop;

import android.content.Context;
import android.view.View;
import android.widget.PopupWindow;

import com.gyq.popupwindowtest.PopupController;
import com.gyq.popupwindowtest.utils.CommonUtil;

/**
 * Created by gyq on 2017/6/15 09:53
 */
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);
            }
            CommonUtil.measureWidthAndHeight(popupWindow.controller.mPopupView);
            return popupWindow;
        }



    }
}

其中,用到的 PopupController.java

package com.gyq.popupwindowtest;

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;

/**
 * Created by gyq on 2017/6/15 09:52
 */
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,给 RecyclerView 的 item 设置间距 SpacesItemDecoration.java

package com.gyq.popupwindowtest.pop;

import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 * Created by gyq on 2017/6/15 13:34
 */
public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
    private int space;

    public SpacesItemDecoration(int space) {
        this.space = space;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view,
                               RecyclerView parent, RecyclerView.State state) {
        outRect.left = space;
        outRect.right = space;
        outRect.bottom = space;

        // Add top margin only for the first item to avoid double space between items
        if (parent.getChildPosition(view) == 0)
            outRect.top = space;
    }
}

4,在 MainActivity.java 中使用:

package com.gyq.popupwindowtest;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.gyq.popupwindowtest.pop.CommonPopupWindow;
import com.gyq.popupwindowtest.pop.SpacesItemDecoration;
import com.gyq.popupwindowtest.utils.CommonUtil;
import com.zhy.adapter.recyclerview.CommonAdapter;
import com.zhy.adapter.recyclerview.MultiItemTypeAdapter;
import com.zhy.adapter.recyclerview.base.ViewHolder;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private Button mCenter,mTop,mBottom,mLeft,mRight;

    private CommonPopupWindow popupWindow;

    private CommonAdapter<String> mAdapter;

    private List<String> mDatas = new ArrayList<>();

    private int spacingInPixels = 18;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initViews();

        initListener();

        loadDatas();
    }

    private void loadDatas() {
        for (int i = 0;i < 10;i++) {
            mDatas.add("王者荣耀");
        }
    }

    private void initListener() {
        //仿微信修改头像弹出pop
        mCenter.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (popupWindow != null && popupWindow.isShowing()) {
                    return;
                }

                View upView = LayoutInflater.from(MainActivity.this).inflate(R.layout.popup_up, null);
                CommonUtil.measureWidthAndHeight(upView);

                popupWindow = new CommonPopupWindow.Builder(MainActivity.this)
                        .setView(R.layout.popup_up)
                        .setWidthAndHeight(ViewGroup.LayoutParams.MATCH_PARENT,upView.getMeasuredHeight())
                        .setBackGroundLevel(0.5f)//取值范围0.0f-1.0f 值越小越暗
                        .setAnimationStyle(R.style.AnimUp)
                        .setViewOnclickListener(new CommonPopupWindow.ViewInterface() {
                            @Override
                            public void getChildView(View view, int layoutResId) {
                                Button btn_take_photo = (Button) view.findViewById(R.id.btn_take_photo);
                                Button btn_select_photo = (Button) view.findViewById(R.id.btn_select_photo);
                                Button btn_cancel = (Button) view.findViewById(R.id.btn_cancel);
                                btn_take_photo.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        toast("拍照");
                                        if (popupWindow != null) {
                                            popupWindow.dismiss();
                                        }
                                    }
                                });
                                btn_select_photo.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        toast("相册选取");
                                        if (popupWindow != null) {
                                            popupWindow.dismiss();
                                        }
                                    }
                                });
                                btn_cancel.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        if (popupWindow != null) {
                                            popupWindow.dismiss();
                                        }
                                    }
                                });
                                view.setOnTouchListener(new View.OnTouchListener() {
                                    @Override
                                    public boolean onTouch(View v, MotionEvent event) {
                                        if (popupWindow != null) {
                                            popupWindow.dismiss();
                                        }
                                        return true;
                                    }
                                });
                            }
                        })
                        .create();

                popupWindow.showAtLocation(mCenter, Gravity.BOTTOM,0,0);

            }
        });

        //向下弹出pop
        mTop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (popupWindow != null && popupWindow.isShowing()) {
                    return;
                }

                popupWindow = new CommonPopupWindow.Builder(MainActivity.this)
                        .setView(R.layout.popup_down)
                        .setWidthAndHeight(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
                        .setAnimationStyle(R.style.AnimDown)
                        .setViewOnclickListener(new CommonPopupWindow.ViewInterface() {
                            @Override
                            public void getChildView(View view, int layoutResId) {
                                RecyclerView rv = (RecyclerView)view.findViewById(R.id.recycler_view);

                                GridLayoutManager manager = new GridLayoutManager(MainActivity.this,3);
                                rv.setLayoutManager(manager);

                                rv.addItemDecoration(new SpacesItemDecoration(spacingInPixels));

                                mAdapter = new CommonAdapter<String>(MainActivity.this,R.layout.itme_rv_popup,mDatas) {
                                    @Override
                                    protected void convert(ViewHolder holder, String s, int position) {
                                        holder.setText(R.id.tv_item_title,s);
                                    }
                                };

                                mAdapter.setOnItemClickListener(new MultiItemTypeAdapter.OnItemClickListener() {
                                    @Override
                                    public void onItemClick(View view, RecyclerView.ViewHolder holder, int position) {
                                        toast("点击了" + position);
                                    }

                                    @Override
                                    public boolean onItemLongClick(View view, RecyclerView.ViewHolder holder, int position) {
                                        return false;
                                    }
                                });

                                rv.setAdapter(mAdapter);

                            }
                        })
                        .setOutsideTouchable(true)
                        .create();

                popupWindow.showAsDropDown(view);
            }
        });

        //向右弹pop
        mRight.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (popupWindow != null && popupWindow.isShowing()) return;
                popupWindow = new CommonPopupWindow.Builder(MainActivity.this)
                        .setView(R.layout.popup_left_or_right)
                        .setWidthAndHeight(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
                        .setAnimationStyle(R.style.AnimHorizontal)
                        .setViewOnclickListener(new CommonPopupWindow.ViewInterface() {
                            @Override
                            public void getChildView(View view, int layoutResId) {
                                TextView tv_like = (TextView) view.findViewById(R.id.tv_like);
                                TextView tv_hate = (TextView) view.findViewById(R.id.tv_hate);
                                tv_like.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        toast("赞一个");
                                        popupWindow.dismiss();
                                    }
                                });
                                tv_hate.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        toast("踩一下");
                                        popupWindow.dismiss();
                                    }
                                });
                            }
                        })
                        .create();
                popupWindow.showAsDropDown(view, view.getWidth(), -view.getHeight());
            }
        });

        //向左弹pop
        mLeft.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (popupWindow != null && popupWindow.isShowing()) return;
                popupWindow = new CommonPopupWindow.Builder(MainActivity.this)
                        .setView(R.layout.popup_left_or_right)
                        .setWidthAndHeight(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
                        .setAnimationStyle(R.style.AnimRight)
                        .setViewOnclickListener(new CommonPopupWindow.ViewInterface() {
                            @Override
                            public void getChildView(View view, int layoutResId) {
                                TextView tv_like = (TextView) view.findViewById(R.id.tv_like);
                                TextView tv_hate = (TextView) view.findViewById(R.id.tv_hate);
                                tv_like.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        toast("赞一个");
                                        popupWindow.dismiss();
                                    }
                                });
                                tv_hate.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        toast("踩一下");
                                        popupWindow.dismiss();
                                    }
                                });
                            }
                        })
                        .create();
                popupWindow.showAsDropDown(view, -popupWindow.getWidth(), -view.getHeight());
            }
        });

        //向上弹pop
        mBottom.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (popupWindow != null && popupWindow.isShowing()) return;
                popupWindow = new CommonPopupWindow.Builder(MainActivity.this)
                        .setView(R.layout.popup_left_or_right)
                        .setWidthAndHeight(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
                        .setViewOnclickListener(new CommonPopupWindow.ViewInterface() {
                            @Override
                            public void getChildView(View view, int layoutResId) {
                                TextView tv_like = (TextView) view.findViewById(R.id.tv_like);
                                TextView tv_hate = (TextView) view.findViewById(R.id.tv_hate);
                                tv_like.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        toast("赞一个");
                                        popupWindow.dismiss();
                                    }
                                });
                                tv_hate.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        toast("踩一下");
                                        popupWindow.dismiss();
                                    }
                                });
                            }
                        })
                        .create();
                popupWindow.showAsDropDown(view, 0, -(popupWindow.getHeight() + view.getMeasuredHeight()));
            }
        });
    }

    private void initViews() {
        mCenter = (Button)findViewById(R.id.show_center);
        mTop = (Button)findViewById(R.id.show_top);
        mBottom = (Button)findViewById(R.id.show_bottom);
        mLeft = (Button)findViewById(R.id.show_left);
        mRight = (Button)findViewById(R.id.show_right);
    }


    private void toast(String s) {
        Toast.makeText(MainActivity.this,s,Toast.LENGTH_SHORT).show();
    }

}

其中,用到的工具类 CommonUtil.java

package com.gyq.popupwindowtest.utils;

import android.view.View;

/**
 * Created by gyq on 2017/6/15 10:06
 */
public class CommonUtil {
    /**
     * 测量View的宽高
     *
     * @param view View
     */
    public static void measureWidthAndHeight(View view) {
        int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        view.measure(w, h);
    }

}

5,布局文件和用到的动画我会上传到我的资源,请自行前往下载!

你可能感兴趣的:(Android,基础)