Android 功能很强大的弹窗XPopup

一 、 Gradle

implementation  'com.github.li-xiaojun:XPopup:2.6.6'

jitpack还要求在工程根目录的build.gradle中添加如下:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

其中编译版本必须 >= 29:
compileSdkVersion 29

必须添加的依赖库,版本不用和我一致:

implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1'

混淆

-dontwarn com.lxj.xpopup.widget.**
-keep class com.lxj.xpopup.widget.**{*;}

功能很强大,涵盖市面上几乎所有的弹窗UI

带确认和取消按钮的弹窗

 BasePopupView popupView;
 ...
 case R.id.btnShowConfirm: //带确认和取消按钮的弹窗
                /*if(popupView==null)*/
                popupView = new XPopup.Builder(getContext())
                        .hasNavigationBar(false) //设置是否显示导航栏,默认是显示的。如果你希望弹窗隐藏导航栏,就设置为true
                        /*
                         * XPopup的弹窗默认是Dialog实现,该方法设置为true则切换为View实现,两者区别如下:
                         * 1. Dialog实现,独立Window渲染,性能是View实现的2倍以上,但部分与输入法交互效果无法做到,
                         *    比如根据输入进行联想搜索的场景,因为输入法也是一个Dialog,Android中无法实现2个Dialog同时获取焦点,
                         *    而设置为View模式即可轻松实现;
                         *    但是Dialog实现有个缺陷是弹窗内部无法使用Fragment,这是Android的限制;
                         *    Dialog的层级高,会覆盖View层
                         * 2. View实现本质是把弹窗挂载到Activity的decorView上面,由于还是View,所以很多与输入法的交互都能实现;
                         *    View实现内部完全可以使用Fragment;
                         *    缺点是和Activity相同渲染线程,性能比Dialog低
                         *
                         * @param viewMode 是否是View实现,默认是false
                         */
                        .isViewMode(true)
                        /*
                         * 是否在弹窗消失后就立即释放资源,杜绝内存泄漏,仅仅适用于弹窗只用一次的场景,默认为false。
                         * 如果你的弹窗对象需是复用的,千万不要开启这个设置
                         */
                        .isDestroyOnDismiss(true)
                        .hasBlurBg(true)//是否设置背景为高斯模糊背景。默认为false
                        .dismissOnTouchOutside(false)//设置点击弹窗外面是否关闭弹窗,默认为true
                        .autoDismiss(false)//设置当操作完毕后是否自动关闭弹窗,默认为true。比如:点击Confirm弹窗的确认按钮默认是关闭弹窗,如果为false,则不关闭
                        .popupAnimation(PopupAnimation.NoAnimation)// 为弹窗设置内置的动画器,默认情况下,已经为每种弹窗设置了效果最佳的动画器;如果你不喜欢,仍然可以修改。
                        .setPopupCallback(new DemoXPopupListener())// 设置弹窗显示和隐藏的回调监听
                        //.asCustom(new LoginPopup(getContext())); // 登陆弹窗样式
                        /*
                         * title:标题
                         * content:内容
                         * cancelBtnText:取消按钮文本(左边按钮文本)
                         * confirmBtnText:确定按钮文本(右边按钮文本)
                         * confirmListener:确定按钮点击事件(右边按钮点击事件)
                         * cancelListener:取消按钮点击事件(左边按钮点击事件)
                         * isHideCancel:是否隐藏左侧按钮(设置单个点击按钮使用)
                         */
                        .asConfirm("哈哈", "床前明月光,疑是地上霜;举头望明月,低头思故乡。",
                                "取消", "确定",
                                new OnConfirmListener() {
                                    @Override
                                    public void onConfirm() {
                                        popupView.dismiss();
                                    }

                                }, null, true);
                popupView.show();
                break;

在中间弹出的List列表弹窗,带选中效果


  case R.id.btnShowCenterListWithCheck: //在中间弹出的List列表弹窗,带选中效果
         new XPopup.Builder(getContext())
                .isDestroyOnDismiss(true) //对于只使用一次的弹窗,推荐设置这个
                .asCenterList("请选择一项", new String[]{"条目1", "条目2", "条目3", "条目4"},
                null, 1,
                new OnSelectListener() {
                      @Override
                      public void onSelect(int position, String text) {
                          toast("click " + text);
                      }
                 })
               .show();
                break;
case R.id.btnShowCenterListWithCheck: //在中间弹出的List列表弹窗,带选中效果
        new XPopup.Builder(getContext())
                  .isDestroyOnDismiss(true) //对于只使用一次的弹窗,推荐设置这个
                        /*
                         * title:标题
                         * data:数据列表
                         * iconIds :图片列表
                         * checkedPosition:选中的位置
                         * selectListener:选中回调事件
                         */
                   .asCenterList("请选择一项", new String[]{"条目1", "条目2", "条目3", "条目4"},
                         new int[]{R.drawable.ic_launcher_background}, 1,
                         new OnSelectListener() {
                            @Override
                            public void onSelect(int position, String text) {
                                toast("click " + text);
                                    }![02.png](https://upload-images.jianshu.io/upload_images/22679253-94481b7fc95879df.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

                           })
                    .show();
     break;

从底部弹出,带手势拖拽的列表弹窗,带选中效果

 case R.id.btnShowBottomListWithCheck: //从底部弹出,带手势拖拽的列表弹窗,带选中效果
      new XPopup.Builder(getContext())
             .isDestroyOnDismiss(true) //对于只使用一次的弹窗,推荐设置这个
             .asBottomList("标题可以没有", new String[]{"条目1", "条目2", "条目3", "条目4", "条目5"},
              null, 2,
              new OnSelectListener() {
                @Override
                 public void onSelect(int position, String text) {
                   toast("click " + text);
                }
             })
             .show();
      break;

在中间弹出的Loading加载框

LoadingPopupView loadingPopup; 
 case R.id.btnShowLoading: //在中间弹出的Loading加载框
                if (loadingPopup == null) {
                    loadingPopup = (LoadingPopupView) new XPopup.Builder(getContext())
                            .dismissOnBackPressed(false)
                            .isLightNavigationBar(true)
                            .isViewMode(true)
                            .asLoading("加载中")
                            .show();
                } else {
                    loadingPopup.show();
                }
                loadingPopup.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        loadingPopup.setTitle("加载中长度变化啊");
                        loadingPopup.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                loadingPopup.setTitle("");
                            }
                        }, 2000);
                    }
                }, 2000);
//                loadingPopup.smartDismiss();
//                loadingPopup.dismiss();
                loadingPopup.delayDismissWith(6000, new Runnable() {
                    @Override
                    public void run() {
                        toast("我消失了!!!");
                    }
                });
                break;

显示自定义Bottom弹窗(自带拖拽交互)

 case R.id.btnCustomBottomPopup: //自定义的底部弹窗
                new XPopup.Builder(getContext())
                        .moveUpToKeyboard(false) //如果不加这个,评论弹窗会移动到软键盘上面
                        .enableDrag(true)
                        .isViewMode(true)
                        .isDestroyOnDismiss(true) //对于只使用一次的弹窗,推荐设置这个
//                        .isThreeDrag(true) //是否开启三阶拖拽,如果设置enableDrag(false)则无效
                        .asCustom(new ZhihuCommentPopup(getContext())/*.enableDrag(false)*/)
                        .show();
                break;

-----------------------------------------------------------------------------------------------------------------

import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.lxj.easyadapter.EasyAdapter;
import com.lxj.easyadapter.MultiItemTypeAdapter;
import com.lxj.easyadapter.ViewHolder;
import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.core.BasePopupView;
import com.lxj.xpopup.core.BottomPopupView;
import com.lxj.xpopup.interfaces.SimpleCallback;
import com.lxj.xpopup.util.XPopupUtils;
import com.lxj.xpopup.widget.VerticalRecyclerView;
import com.lxj.xpopupdemo.DemoActivity;
import com.lxj.xpopupdemo.R;
import java.util.ArrayList;

/**
 * Description: 仿知乎底部评论弹窗
 * Create by dance, at 2018/12/25
 */
public class ZhihuCommentPopup extends BottomPopupView {
    VerticalRecyclerView recyclerView;
    private ArrayList data;
    private EasyAdapter commonAdapter;

    public ZhihuCommentPopup(@NonNull Context context) {
        super(context);
    }

    @Override
    protected int getImplLayoutId() {
        return R.layout.custom_bottom_popup;
    }

    @Override
    protected void onCreate() {
        super.onCreate();
        recyclerView = findViewById(R.id.recyclerView);
        findViewById(R.id.tv_temp).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //弹出新的弹窗用来输入
                final CustomEditTextBottomPopup textBottomPopup = new CustomEditTextBottomPopup(getContext());
                new XPopup.Builder(getContext())
                        .autoOpenSoftInput(true)
                        .autoFocusEditText(true)
                        .setPopupCallback(new SimpleCallback() {
                            @Override
                            public void onShow(BasePopupView popupView) {
                            }

                            @Override
                            public void onDismiss(BasePopupView popupView) {
                                String comment = textBottomPopup.getComment();
                                if (!comment.isEmpty()) {
                                    data.add(0, comment);
                                    commonAdapter.notifyDataSetChanged();
                                }
                            }
                        })
                        .asCustom(textBottomPopup)
                        .show();
            }
        });

        data = new ArrayList<>();
        for (int i = 0; i < 15; i++) {
            data.add("这是一个自定义Bottom类型的弹窗!你可以在里面添加任何滚动的View,我已经智能处理好嵌套滚动,你只需编写UI和逻辑即可!");
        }
        commonAdapter = new EasyAdapter(data, R.layout.adapter_zhihu_comment) {
            @Override
            protected void bind(@NonNull ViewHolder holder, @NonNull String s, final int position) {
                holder.setText(R.id.name, "知乎大神 - " + position)
                        .setText(R.id.comment, s);
                holder.getView(R.id.btnDel).setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        data.remove(position);
                        commonAdapter.notifyItemRemoved(position);
                        commonAdapter.notifyItemRangeChanged(position, data.size());
                    }
                });
            }
        };
        commonAdapter.setOnItemClickListener(new MultiItemTypeAdapter.SimpleOnItemClickListener() {
            @Override
            public void onItemClick(View view, RecyclerView.ViewHolder holder, int position) {
                //不要直接这样做,会导致消失动画未执行完就跳转界面,不流畅。
//                dismiss();
//                getContext().startActivity(new Intent(getContext(), DemoActivity.class))
                //可以等消失动画执行完毕再开启新界面
                dismissWith(new Runnable() {
                    @Override
                    public void run() {
                        getContext().startActivity(new Intent(getContext(), DemoActivity.class));
                    }
                });

            }
        });
        recyclerView.setAdapter(commonAdapter);
    }

    //完全可见执行
    @Override
    protected void onShow() {
        super.onShow();
        Log.e("tag", "知乎评论 onShow");
    }

    //完全消失执行
    @Override
    protected void onDismiss() {
        Log.e("tag", "知乎评论 onDismiss");
    }

    @Override
    protected int getMaxHeight() {
        return (int) (XPopupUtils.getScreenHeight(getContext()) * .7f);
    }
}

依附于某个View的Attach类型弹窗

  AttachPopupView attachPopupView = new XPopup.Builder(getContext())
  .hasShadowBg(false)
  .isViewMode(true)
  .isClickThrough(true)
//                        .isDestroyOnDismiss(true) //对于只使用一次的弹窗,推荐设置这个
//                        .isDarkTheme(true)
//                        .popupAnimation(PopupAnimation.ScrollAlphaFromTop) //NoAnimation表示禁用动画
//                        .isCenterHorizontal(true) //是否与目标水平居中对齐
//                        .offsetY(60)
//                        .offsetX(80)
//                        .popupPosition(PopupPosition.Top) //手动指定弹窗的位置
//                        .popupWidth(500)
.atView(v)  // 依附于所点击的View,内部会自动判断在上方或者下方显示
.asAttachList(new String[]{"分享", "编辑", "不带icon", "分享分享分享",},
  new int[]{R.mipmap.ic_launcher_round, R.mipmap.ic_launcher_round},
        new OnSelectListener() {
               @Override
               public void onSelect(int position, String text) {
                   toast("click " + text);
               }
              }, 0, 0/*, Gravity.LEFT*/);
 attachPopupView.show();

点击显示

      // 必须在事件发生前,调用这个方法来监视View的触摸
        final XPopup.Builder builder = new XPopup.Builder(getContext())
//                .isCenterHorizontal(true)
                .watchView(view.findViewById(R.id.btnShowAttachPoint));
        view.findViewById(R.id.btnShowAttachPoint).setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                XPopup.fixLongClick(v);//能保证弹窗弹出后,下层的View无法滑动
                builder.asAttachList(new String[]{"置顶11", "复制", "删除", "编辑编辑编辑编辑"
                        }, null,
                        new OnSelectListener() {
                            @Override
                            public void onSelect(int position, String text) {
                                toast("click " + text);
                            }
                        })
                        .show();
                return true;
            }
        });

        drawerPopupView = new CustomDrawerPopupView(getContext());

水平方向的Attach弹窗,就像微信朋友圈的点赞弹窗那样

            case R.id.btnAttachPopup1: //水平方向的Attach弹窗,就像微信朋友圈的点赞弹窗那样
                new XPopup.Builder(getContext())
                        .isDestroyOnDismiss(true) //对于只使用一次的弹窗,推荐设置这个
//                        .offsetX(50) //偏移10
//                        .offsetY(10)  //往下偏移10
//                        .popupPosition(PopupPosition.Right) //手动指定位置,有可能被遮盖
                        .hasShadowBg(false) // 去掉半透明背景
                        .isViewMode(true)
                        .atView(v)
                        .asCustom(new CustomAttachPopup(getContext()))
                        .show();
                break;

-----------------------------------------------
import android.content.Context;
import androidx.annotation.NonNull;
import android.view.View;
import android.widget.Toast;
import com.lxj.xpopup.core.HorizontalAttachPopupView;
import com.lxj.xpopupdemo.R;
import com.lxj.xpopupdemo.XPopupApp;

/**
 * Description: 自定义Attach弹窗,水平方向的
 * Create by lxj, at 2019/3/13
 */
public class CustomAttachPopup extends HorizontalAttachPopupView {
    public CustomAttachPopup(@NonNull Context context) {
        super(context);
    }

    @Override
    protected int getImplLayoutId() {
        return R.layout.custom_attach_popup;
    }

    @Override
    protected void onCreate() {
        super.onCreate();
        findViewById(R.id.tv_zan).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(XPopupApp.context, "赞", Toast.LENGTH_LONG).show();
                dismiss();
            }
        });
        findViewById(R.id.tv_comment).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(XPopupApp.context, "评论", Toast.LENGTH_LONG).show();
                dismiss();
            }
        });
    }

------------------------


    
    
    

水平方向带气泡弹窗

            case R.id.btnBubbleAttachPopup1: //水平方向带气泡弹窗
                new XPopup.Builder(getContext())
                        .isDestroyOnDismiss(true) //对于只使用一次的弹窗,推荐设置这个
                        .atView(v)
                        .hasShadowBg(false) // 去掉半透明背景
                        .asCustom(new CustomHorizontalBubbleAttachPopup(getContext()))
                        .show();
                break;

-----------------------------

import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import com.lxj.xpopup.core.BubbleHorizontalAttachPopupView;
import com.lxj.xpopup.util.XPopupUtils;
import com.lxj.xpopupdemo.R;
import com.lxj.xpopupdemo.XPopupApp;

/**
 * Description: 自定义Attach弹窗,水平方向的带气泡的弹窗
 * Create by lxj, at 2019/3/13
 */
public class CustomHorizontalBubbleAttachPopup extends BubbleHorizontalAttachPopupView {
    public CustomHorizontalBubbleAttachPopup(@NonNull Context context) {
        super(context);
    }

    @Override
    protected int getImplLayoutId() {
        return R.layout.custom_attach_popup;
    }

    @Override
    protected void onCreate() {
        super.onCreate();
        setBubbleBgColor(Color.parseColor("#4D5063"));
        setBubbleShadowSize(XPopupUtils.dp2px(getContext(), 10));
        setBubbleShadowColor(Color.BLACK);
        getPopupImplView().setBackgroundResource(0);
        findViewById(R.id.tv_zan).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(XPopupApp.context, "赞", Toast.LENGTH_LONG).show();
                dismiss();
            }
        });
        findViewById(R.id.tv_comment).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(XPopupApp.context, "评论", Toast.LENGTH_LONG).show();
                dismiss();
            }
        });
    }
}

你可能感兴趣的:(Android 功能很强大的弹窗XPopup)