2019-01-06

Android封装一个通用的PopupWindow

效果:弹窗在android的每个项目中基本上都会使用到的,主要功能是给用户一些提示和操作,所以我就稍微封装了一个简单的PopupWindUtils,这样方便项目中使用,使用的方法也非常简单,我这里简单提示下,效果如下图所示。

实现:下面的代码即是主要的实现:

public class PopupWindowUtils
{
    public static final int DIALOG_ANIMATION = android.R.style.Animation_Dialog;    //dialog动画,渐现
    public static final int CUSTOM_UP_TO_DOWN_ANIMATION = R.style.popwin_anim_style;      //自定义设置从小往上的的动画

    // 设置屏幕背景透明度
    public static void backgroundAlpha(Activity activity, float bgAlpha) {
        WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
        lp.alpha = bgAlpha; //0.0-1.0
        activity.getWindow().setAttributes(lp);
    }

    /**
     * 获取自适应popupwindow
     *
     * @param activity
     * @param resource
     * @param isTouch
     * @param animation
     * @param callBack
     * @return
     */
    public static PopupWindow getNormalPopupWindow(Activity activity, @LayoutRes int resource, boolean isTouch, int animation, PopupWindowCallBack callBack) {
        return createPopupWidow(activity, resource, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, isTouch, animation, callBack);
    }

    /**
     * 获取宽度占全屏的popupwindow
     *
     * @param activity
     * @param resource
     * @param isTouch
     * @param animation
     * @param callBack
     * @return
     */
    public static PopupWindow getAllScreenPopupWindow(Activity activity, @LayoutRes int resource, boolean isTouch, int animation, PopupWindowCallBack callBack) {
        return createPopupWidow(activity, resource, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, isTouch, animation, callBack);
    }

    /**
     * @param activity
     * @param resource  布局资源
     * @param width     宽度  eg: view.getMeasuredWidth()
     * @param height    高度
     * @param isTouch   点击外部,PopupWindow是否消失
     * @param animation 显示动画
     * @param callBack
     * @return
     */
    public static PopupWindow createPopupWidow(final Activity activity, @LayoutRes int resource, int width, int height, boolean isTouch,
                                               int animation, final PopupWindowCallBack callBack) {
        System.out.println();
        //初始化PopupWindow的布局
        View popView = activity.getLayoutInflater().inflate(resource, null);
        //popView即popupWindow的布局,ture设置focusAble
        PopupWindow popupWindow = new PopupWindow(popView, width, height, isTouch);
        //必须设置BackgroundDrawable后setOutsideTouchable(true)才会有效
        popupWindow.setBackgroundDrawable(new ColorDrawable());
        //点击外部关闭。
        popupWindow.setOutsideTouchable(isTouch);
        //设置一个动画。
        popupWindow.setAnimationStyle(animation);
        // popupWindow消失监听
        popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
            @Override
            public void onDismiss() {
                backgroundAlpha(activity, 1f);
                if (callBack != null) {
                    callBack.onDismiss();
                }
            }
        });
        //设置map的swift的点击监听
        if (callBack != null) {
            callBack.disposePopView(popView);
        }
        return popupWindow;
    }

    /**
     * 显示在指定view的下方
     *
     * @param activity
     * @param popupWindow
     * @param view
     * @param bgAlpha
     */
    public static void showAsDropDown(Activity activity, PopupWindow popupWindow, View view, float bgAlpha) {
        showAsDropDown(activity, popupWindow, view, bgAlpha, 0, 0);
    }

    /**
     * 显示在指定view的下方,设置偏移
     *
     * @param activity
     * @param popupWindow
     * @param view
     * @param bgAlpha
     * @param xOff
     * @param yOff
     */
    public static void showAsDropDown(Activity activity, PopupWindow popupWindow, View view, float bgAlpha, int xOff, int yOff) {
        backgroundAlpha(activity, bgAlpha);
        popupWindow.showAsDropDown(view, xOff, yOff);
    }

    /**
     * 显示在整个界面的指定位置
     *
     * @param activity
     * @param popupWindow
     * @param gravity     eg: Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL or Gravity.CENTER
     * @param bgAlpha
     */
    public static void showAtLocation(Activity activity, PopupWindow popupWindow, int gravity, float bgAlpha) {
        showAtLocation(activity, popupWindow, gravity, bgAlpha, 0, 0);
    }

    /**
     * 显示在整个界面的指定位置,设置偏移
     *
     * @param activity
     * @param popupWindow
     * @param gravity
     * @param bgAlpha
     * @param xOff
     * @param yOff
     */
    public static void showAtLocation(Activity activity, PopupWindow popupWindow, int gravity, float bgAlpha, int xOff, int yOff) {
        backgroundAlpha(activity, bgAlpha);
        View parent = ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
        popupWindow.showAtLocation(parent, gravity, xOff, yOff);
    }

    public interface PopupWindowCallBack {
        void disposePopView(View popView);
        void onDismiss();
    }
}

使用:这里主要需要注意和了解的地方是PopupWindow的显示位置:

  • 如果使用showAsDropDown,默认是弹出在view的下方
  • 如果使用showAtLocation,就是显示在整个界面的指定位置,比如在屏幕的中间弹出,使用Gravity.CENTER(其它Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL等)
  • 可以给PopupWindow设置x和y的偏移量。这里可参考下弹出顶部的实现,理解完这个基本上就可以给PopupWindow任意设置弹出位置了。
private void setDisplayUp()
{
   int[] location = new int[2];
   tvUp.getLocationOnScreen(location);

   // 这是为了避免比如在聊天列表中条目靠近状态栏顶部导致显示出现问题
   int titleBarHeight = Utils.Dp2Px(this, 45);
   int statusBarHeight = Utils.getStatusBarHeight(this);
   if(location[1] < titleBarHeight + statusBarHeight)
   {
      return;
   }

   if(mPopouWindowUp == null)
   {
      mPopouWindowUp = PopupWindowUtils.getNormalPopupWindow(this, R.layout.dialog_up, true, PopupWindowUtils.DIALOG_ANIMATION, new PopupWindowUtils.PopupWindowCallBack()
      {
         @Override
         public void disposePopView(final View popView)
         {
            TextView tvDelete = popView.findViewById(R.id.tv_delete);
            TextView tvCopy = popView.findViewById(R.id.tv_copy);
            tvDelete.setOnClickListener(new View.OnClickListener()
            {
               @Override
               public void onClick(View v)
               {
                  mPopouWindowUp.dismiss();
               }
            });
            tvCopy.setOnClickListener(new View.OnClickListener()
            {
               @Override
               public void onClick(View v)
               {
                  mPopouWindowUp.dismiss();
               }
            });
         }

         @Override
         public void onDismiss()
         {

         }
      });
   }
   mPopouWindowUp.getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
   int width = tvUp.getWidth();
   int height = tvUp.getHeight();
   int measuredWidth = mPopouWindowUp.getContentView().getMeasuredWidth();
   int measuredHeight = mPopouWindowUp.getContentView().getMeasuredHeight();
   PopupWindowUtils.showAsDropDown(this, mPopouWindowUp, tvUp, 1f, (width - measuredWidth) / 2, -height - measuredHeight);
}

如果有需要的可以直接去下载代码,在代码中的注释也已经非常详细了,相信你可以一目了然。GitHub传送门

你可能感兴趣的:(2019-01-06)