美文网首页
简易封装的PopupWindow

简易封装的PopupWindow

作者: 颤抖的闪电 | 来源:发表于2021-05-07 14:20 被阅读0次
    import android.app.Activity;
    import android.graphics.drawable.ColorDrawable;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.WindowManager;
    import android.widget.PopupWindow;
    
    import com.msyc.onion.R;
    
    import java.lang.ref.WeakReference;
    
    /**
     * 简易封装的PopupWindow
     */
    
    public class CustomPopupWindow implements PopupWindow.OnDismissListener {
        private PopupWindow mPopupWindow;
        private View contentView;
        private static WeakReference<Activity> refActivity;
        private Builder builder;
    
        public CustomPopupWindow(Builder builder) {
            this.builder = builder;
            contentView = LayoutInflater.from(refActivity.get()).inflate(builder.contentViewId, null);
            mPopupWindow = new PopupWindow(contentView, builder.width, builder.height);
            if (builder.outsideTouchable) {
                //设置点击外部可以取消,必须和下面这个方法配合才有效,(setOutsideTouchable设置生效的前提是setTouchable(true)和setFocusable(false),此处存疑)
                mPopupWindow.setOutsideTouchable(true);
                //设置一个空背景,设置了这个背景之后,设置点击外部取消才有效
                mPopupWindow.setBackgroundDrawable(new ColorDrawable()); //如果不设置PopupWindow的背景,有些版本就会出现一个问题:无论是点击外部区域还是Back键都无法dismiss弹框
    //            mPopupWindow.setTouchable(true);
                mPopupWindow.setFocusable(true); // false时PopupWindow不处理返回键(此处设置为true,则效果是正常的,和上方的说法存疑)
            }
            //Popupwindow可以点击,PopupWindow弹出后,所有的触屏和物理按键都有PopupWindows处理。
            // 其他任何事件的响应都必须发生在PopupWindow消失之后, (home  等系统层面的事件除外)。
            // 比如这样一个PopupWindow出现的时候,按back键首先是让PopupWindow消失,
            // 第二次按才是退出activity,
            //解决Pop遮挡住虚拟键盘的问题
            mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
            //让pop自适应输入状态
            mPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
            if (builder.animStyle != 0) {
                mPopupWindow.setAnimationStyle(builder.animStyle); //设置pop显示的动画效果
            }
            mPopupWindow.setOnDismissListener(this); //设置pop关闭的监听事件
    
            // 原生的Outside 事件会穿透到下方(原生问题),故用gray_layout多做一层补充作用(主要用于点击消失popwindow,避免事件穿透)
            if (contentView.findViewById(R.id.gray_layout) != null) {
                View grayLayout = (View) contentView.findViewById(R.id.gray_layout);
                grayLayout.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        dismiss();
                    }
                });
            }
        }
    
        /**
         * popup 消失
         */
        public void dismiss() {
            if (mPopupWindow != null && mPopupWindow.isShowing()) {
                mPopupWindow.dismiss();
            }
        }
    
    
        /**
         * 相对于窗体的显示位置
         *
         * @param view    可以为Activity中的任意一个View(最终的效果一样),
         *                会通过这个View找到其父Window,也就是Activity的Window。
         * @param gravity 在窗体中的位置,默认为Gravity.NO_GRAVITY
         * @param x       表示距离Window边缘的距离,方向由Gravity决定。
         *                例如:设置了Gravity.TOP,则y表示与Window上边缘的距离;
         *                而如果设置了Gravity.BOTTOM,则y表示与下边缘的距离。
         * @param y
         * @return
         */
        public CustomPopupWindow showAtLocation(View view, int gravity, int x, int y) {
            if (mPopupWindow != null) {
                mPopupWindow.showAtLocation(view, gravity, x, y);
                if (builder != null) setBackgroundAlpha(builder.backgroundAlpha); //设置窗体的背景透明度为半透明
            }
            return this;
        }
    
    
        /**
         * 显示在anchor控件的正下方,或者相对这个控件的位置
         *
         * @param anchor 锚点
         * @param xOff   相对这个控件x方向的偏移
         * @param yOff   相对这个控件y方向的偏移
         * @return
         */
    //    public CustomPopupWindow showAsDropDown(View anchor, int xOff, int yOff) {
    //        if (mPopupWindow != null) {
    //            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    //                //7.0以上系统
    //                //获取目标控件在屏幕中的坐标位置
    //                int[] location = new int[2];
    //                anchor.getLocationOnScreen(location);
    //                mPopupWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, 0, location[1] + anchor.getHeight() + yOff);
    //            } else {
    //                mPopupWindow.showAsDropDown(anchor, xOff, yOff);
    //            }
    //            if (builder != null) setBackgroundAlpha(builder.backgroundAlpha); //设置窗体的背景透明度为半透明
    //        }
    //        return this;
    //    }
        public CustomPopupWindow showAsDropDown(View anchor, int xOff, int yOff) {
            if (mPopupWindow != null) {
                if (!mPopupWindow.isShowing()) {
                    // 以下拉方式显示popupwindow
                    mPopupWindow.showAsDropDown(anchor, xOff, yOff);
                    if (builder != null) setBackgroundAlpha(builder.backgroundAlpha); //设置窗体的背景透明度为半透明
                }
    //            else {
    //                this.dismiss();
    //            }
            }
            return this;
        }
    
        public CustomPopupWindow showAsDropDown(View anchor) {
            if (mPopupWindow != null) {
                if (!mPopupWindow.isShowing()) {
                    // 以下拉方式显示popupwindow
                    mPopupWindow.showAsDropDown(anchor);
                    if (builder != null) setBackgroundAlpha(builder.backgroundAlpha); //设置窗体的背景透明度为半透明
                }
    //            else {
    //                this.dismiss();
    //            }
            }
            return this;
        }
    
        /**
         * 根据id获取view
         *
         * @param viewId
         * @return
         */
        public View getItemView(int viewId) {
            if (mPopupWindow != null) {
                return contentView.findViewById(viewId);
            }
            return null;
        }
    
    
        /**
         * 根据id设置pop内部的控件的点击事件的监听
         *
         * @param viewId
         * @param listener
         */
        public void setOnClickListener(int viewId, View.OnClickListener listener) {
            View view = getItemView(viewId);
            view.setOnClickListener(listener);
        }
    
        /**
         * 设置Activity或者Fragment的背景透明度
         *
         * @param bgAlpha 背景的透明度
         */
        public void setBackgroundAlpha(float bgAlpha) {
            if (refActivity.get() == null || refActivity.get().getWindow() == null) return;
            WindowManager.LayoutParams layoutParams = refActivity.get().getWindow().getAttributes();
            layoutParams.alpha = bgAlpha; //0.0-1.0
            refActivity.get().getWindow().setAttributes(layoutParams);
        }
    
        /**
         * builder 类
         */
        public static class Builder {
            private int contentViewId; //pop的布局文件
            private int width; //pop的宽度
            private int height;  //pop的高度
            private int animStyle; //动画效果
            private float backgroundAlpha = 0.5f; //背景的透明度,默认半透明
            private boolean outsideTouchable = false; //设置点击外部可以取消
    
            public Builder(Activity activity) {
                refActivity = new WeakReference<>(activity);
            }
    
            public Builder setContentView(int contentViewId) {
                this.contentViewId = contentViewId;
                return this;
            }
    
            public Builder setwidth(int width) {
                this.width = width;
                return this;
            }
    
            public Builder setheight(int height) {
                this.height = height;
                return this;
            }
    
    
            public Builder setAnimationStyle(int animStyle) {
                this.animStyle = animStyle;
                return this;
            }
    
            public Builder setBackgroundAlpha(float backgroundAlpha) {
                this.backgroundAlpha = backgroundAlpha;
                return this;
            }
    
            public Builder setOutsideTouchable(boolean touchable) {
                outsideTouchable = touchable;
                return this;
            }
    
            public CustomPopupWindow build() {
                return new CustomPopupWindow(this);
            }
        }
    
        @Override
        public void onDismiss() {
            if (builder == null || builder.backgroundAlpha != 1f)
                setBackgroundAlpha(1f); //设置窗体的背景透明度为不透明
        }
    }
    
    

    使用方法:

    private CustomPopupWindow mSearchDropPop; 
    
    /**
         * 初始化Pop,pop的布局是一个列表
         */
        private void initPop() {
            if (mSearchDropPop == null || mSearchDropAdapter == null) {
                mSearchDropPop = new CustomPopupWindow.Builder(this)
                        .setContentView(R.layout.search_drop_pop_window)
                        .setwidth(LinearLayout.LayoutParams.MATCH_PARENT)
                        .setheight(LinearLayout.LayoutParams.WRAP_CONTENT)
                        .setBackgroundAlpha(1.0f)
                        .build();
                //搜索联想结果的列表
                ListView searchLv = (ListView) mSearchDropPop.getItemView(R.id.lv_search_list);
                mSearchDropAdapter = new SearchDropAdapter(this, null);
                searchLv.setAdapter(mSearchDropAdapter);
                searchLv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                        mBinding.editTextSearch.setText(mSearchDropAdapter.getList().get(position).text);
                        mKeyword = mSearchDropAdapter.getList().get(position).text;
                        preSearch().search(mSearchDropAdapter.request_id); // 点击联想词
                    }
                });
            }
        }
    
    /**关键字联想词*/
            mViewModel.mSearchDropData.observe(this, result -> {
                if (result == null || result.getBeanList().size() <= 0) {
                    mSearchDropPop.dismiss();
                } else {
                    String s = mBinding.editTextSearch.getText().toString();
                    if (s.length() > 0 && s.equals(mmSearchDropWord)) {
                        mSearchDropAdapter.setDatas(result);
                        mSearchDropAdapter.notifyDataSetChanged();
                        mSearchDropPop.showAsDropDown(mBinding.editTextSearch); 
                    }
                }
            });
    
    @Override
        protected void onDestroy() {
            if (mSearchDropPop != null) {
                mSearchDropPop.dismiss();
            }
            super.onDestroy();
        }
    

    xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#66000000"
        android:orientation="vertical">
    
        <ListView
            android:id="@+id/lv_search_list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:divider="@null"
            android:paddingTop="@dimen/dp_6" />
        <!--该View用来撑满屏幕用 显示灰色透明背景-->
        <View
            android:id="@+id/gray_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#F1F2F4" />
    
    </LinearLayout>
    

    相关文章

      网友评论

          本文标题:简易封装的PopupWindow

          本文链接:https://www.haomeiwen.com/subject/nuwsdltx.html