美文网首页待研究的内容
Android 功能很强大的弹窗XPopup

Android 功能很强大的弹窗XPopup

作者: 遇见编程 | 来源:发表于2021-11-09 12:05 被阅读0次

    一 、 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://img.haomeiwen.com/i22679253/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<String> data;
        private EasyAdapter<String> 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<String>(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();
                }
            });
        }
    
    ------------------------
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal" android:layout_width="wrap_content"
        android:gravity="center_vertical"
        android:background="#444"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/tv_zan"
            android:textColor="#fff"
            android:textSize="14sp"
            android:text=" 赞 "
            android:paddingTop="10dp"
            android:paddingBottom="10dp"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:background="?android:attr/selectableItemBackground"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <View
            android:background="#eee"
            android:layout_width="1px"
            android:layout_height="15dp"/>
        <TextView
            android:id="@+id/tv_comment"
            android:textColor="#fff"
            android:paddingTop="10dp"
            android:paddingBottom="10dp"
            android:textSize="14sp"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:background="?android:attr/selectableItemBackground"
            android:text="评论"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>
    

    水平方向带气泡弹窗

                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

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