HarmonyOS弹窗组件,Xpopup 精华

鸿蒙开发者社区官方账号
发布于 2021-9-6 15:01
浏览
0收藏

弹窗可以用来操作数据,也可以用来反馈信息。作为产品与用户沟通的核心枢纽,不管是Web前端还是移动端,经常会看见弹窗类的消息。所以,良好的弹窗效果对于用户体验感非常重要。那么,怎样才能设计出好的弹窗?

不少开发者也为之头疼,因为弹窗的样式千变万化,开发起来比较繁琐。为解决这个问题,Xpopup三方弹窗组件应运而生。

一、什么是Xpopup

Xpopup是一款十分强大的弹窗组件,内置了多种常用的弹窗和良好的动画。遵循Material Design,在设计动画的时候考虑了很多细节、过渡、层级的变化,让UI动画更加流畅。同时,用户可以根据需要在Xpopup的内置弹窗的基础上自定义弹窗的样式和业务逻辑。

二、Xpopup分类

综合常见的弹窗场景,可以将其分为以下七类:

1.Center类型:从界面中间弹出,比如确认和取消弹窗、Loading弹窗。

2.Bottom类型:从界面底部弹出,比如知乎的从底部弹出的评论列表。

3.Attach类型:弹窗的位置需要依附于某个Component或者某个触摸点。

4.Drawer类型:从界面的左边或者右边弹出,并支持手势拖拽。

5.ImageViewer类型:大图片浏览弹窗。

6.FullScreen类型:铺满整个界面的弹窗,可以设置任意的动画器,适合用来实现登录、选择性的界面效果。

7.Position类型:自由定位弹窗,可放在屏幕任意地方,结合强大的动画器,可以实现各种效果。

三、Xpopup演示及使用

Xpopup有两种使用方式。一种是内置弹窗,开发者可以直接拿来用。另一种是自定义弹窗,开发者需根据自己的需求来设置相应的样式。

1、Center类型

Center类型,是在界面中间弹出的弹窗。如下图所示,通过点击“显示Confirm弹窗”、“使用内置弹窗绑定项目已有布局”以及“带输入框的Confirm弹窗”,屏幕中央依次弹出了相对应的弹窗效果。

HarmonyOS弹窗组件,Xpopup-鸿蒙开发者社区

以显示带输入框的Confirm弹窗为例,实现代码如下:

new XPopup.Builder(getContext())
        .hasStatusBarShadow(false)         
.autoOpenSoftInput(true)
        .isDarkTheme(true)
// 用于获取页面根容器,监听页面高度变化,解决输入法盖住弹窗的问题
        .setComponent(component)
        .setPopupCallback(new DemoXPopupListener())
        .asInputConfirm("我是标题", null, null, "我是默认Hint文字",
                new OnInputConfirmListener() {
                    @Override
                    public void onConfirm(String text) {
                        toast("input text: " + text);
                    }
                })
        .show();

当内置弹窗样式已无法满足开发者的需求,开发者就可以根据自己的需求自定义弹窗。

Center类型的自定义弹窗通过继承CenterPopupView接口,重写getImplLayoutId()返回弹窗的布局,再在onCreate中编写业务需要的逻辑即可。

代码如下:

class CustomPopup extends CenterPopupView {
    //注意:自定义弹窗本质是一个自定义控件,但是只需重写一个参数的构造,其他的不要重写,所有的自定义弹窗都是这样
    public CustomPopup(Context context) {
        super(context, null);
    }
    // 返回自定义弹窗的布局
    @Override
    protected int getImplLayoutId() {
        return ResourceTable.Layout_custom_popup;
    }
    // 执行初始化操作,比如:findComponentById,设置点击,或者任何你弹窗内的业务逻辑
    @Override
    protected void onCreate() {
        super.onCreate();
        findComponentById(ResourceTable.Id_tv_close).setClickedListener(new ClickedListener() {
            @Override
            public void onClick(Component component) {
                dismiss(); // 关闭弹窗
            }
        });
    }
    // 设置最大宽度,看需要而定
    @Override
    protected int getMaxWidth() {
        return super.getMaxWidth();
    }
    // 设置最大高度,看需要而定
    @Override
    protected int getMaxHeight() {
        return super.getMaxHeight();
    }
    // 设置自定义动画器,看需要而定
    @Override
    protected PopupAnimator getPopupAnimator() {
        return super.getPopupAnimator();
    }
    // 弹窗的宽度,用来动态设定当前弹窗的宽度,受getMaxWidth()限制
    protected int getPopupWidth() {
        return 0;
    }
    // 弹窗的高度,用来动态设定当前弹窗的高度,受getMaxHeight()限制
    protected int getPopupHeight() {
        return 0;
    }}

2、Bottom类型

Bottom类型,是从页面底部弹出的弹窗。

如下图所示,通过点击“显示Bottom类型的List弹窗”从界面底部弹出了带选中效果的选项列表。

HarmonyOS弹窗组件,Xpopup-鸿蒙开发者社区

实现代码如下:

// 从底部弹出,带手势拖拽的列表弹窗
case ResourceTable.Id_btnShowBottomList: 
        new XPopup.Builder(getContext())
        .isDarkTheme(true)
        .enableDrag(true)
        .asBottomList("请选择一项", new String[]{"条目1", "条目2", "条目3", "条目4", "条目5", "条目6", "条目7"},
        new OnSelectListener() {
@Override
public void onSelect(int position, String text) {
        toast("click " + text);
        }
        })
        .show();
        break;
        case ResourceTable.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;

Bottom类型的自定义弹窗通过继承BottomPopupView接口来实现。这里例举一个模仿知乎评论的实现,效果如下:

HarmonyOS弹窗组件,Xpopup-鸿蒙开发者社区

实现代码如下:

public class ZhihuCommentPopup extends BottomPopupView {
    ListContainer listContainer;
    public ZhihuCommentPopup(Context context) {
        super(context, null);
    }
    @Override
    protected int getImplLayoutId() {
        return ResourceTable.Layout_custom_bottom_popup;
    }
    @Override
    protected void onCreate() {
        super.onCreate();
        listContainer = (ListContainer) findComponentById(ResourceTable.Id_listContainer);
        ArrayList<String> strings = new ArrayList<>();
        for (int i = 0; i < 30; i++) {
            strings.add("");
        }
        EasyProvider commonAdapter = new EasyProvider<String>(getContext(), strings, ResourceTable.Layout_adapter_zhihu_comment) {
            @Override
            protected void bind(ViewHolder holder, String itemData, final int position) {}
        };
        listContainer.setItemClickedListener(new ListContainer.ItemClickedListener() {
            @Override
            public void onItemClicked(ListContainer listContainer, Component component, int position, long id) {
                dismiss();
            }
        });
        listContainer.setItemProvider(commonAdapter);
    }
    // 最大高度为Window的0.7
    @Override
    protected int getMaxHeight() {
        return (int) (XPopupUtils.getScreenHeight(getContext()) * .7f);
    }}

3、Attach类型

Attach类型,弹窗的位置需要依附于某个Component(桌面控件)或者某个触摸点。如下图所示,通过点击或者长按桌面控件,弹窗在点击的位置弹出:

HarmonyOS弹窗组件,Xpopup-鸿蒙开发者社区

依附于Component的Attach类型弹窗的实现代码如下:

new XPopup.Builder(getContext())
        .atView(component)  // 依附于所点击的Component,内部会自动判断在上方或者下方显示
        .asAttachList(new String[]{"分享", "编辑", "不带icon"},
        new int[]{ResourceTable.Media_icon, ResourceTable.Media_icon},
        new OnSelectListener() {
@Override
public void onSelect(int position, String text) {
        toast("click " + text);
        }
        })
        .show();

如果是想依附于某个Component的触摸点,则需要先监视该Component,然后设置点击或长按触发:

Component component = findComponentById(ResourceTable.Id_btnShowAttachPoint);
    // 必须在事件发生前,调用这个方法来监视View的触摸
    final XPopup.Builder builder = new XPopup.Builder(getContext()).watchView(component);
component.setLongClickedListener(new LongClickedListener() {
@Override
public void onLongClicked(Component component) {
        builder.asAttachList(new String[]{"置顶", "复制", "删除"}, null,
        new OnSelectListener() {
@Override
public void onSelect(int position, String text) {
        toast("click " + text);
        }
        })
        .show();
        }
        });

Attach类型的自定义弹窗,开发者需通过继承AttachPopupView接口来实现。如下图所示,展示了自定义Attach弹窗、横向带气泡Attach弹窗,以及垂直带气泡Attach弹窗。

HarmonyOS弹窗组件,Xpopup-鸿蒙开发者社区

实现代码如下:

public class CustomAttachPopup2 extends AttachPopupView {
    public CustomAttachPopup2(Context context) {
        super(context, null);
    }
    @Override
    protected int getImplLayoutId() {
        return ResourceTable.Layout_custom_attach_popup2;
    }
    // 设置状态栏的高度,用以修正自定义位置弹窗的高度
    @Override
    protected int setStatusBarHeight() {
        return 130;
    }}

4、Drawer类型

Drawer类型,是从界面的左边或者右边弹出,并支持手势拖拽。效果展示如下:

HarmonyOS弹窗组件,Xpopup-鸿蒙开发者社区

实现代码如下:

public class CustomDrawerPopupView extends DrawerPopupView {
    public CustomDrawerPopupView(Context context) {
        super(context, null);
    }
    @Override
    protected int getImplLayoutId() {
        return ResourceTable.Layout_custom_list_drawer;
    }
    @Override
    protected void onCreate() {
        super.onCreate();
        findComponentById(ResourceTable.Id_btn).setClickedListener(new ClickedListener() {
            @Override
            public void onClick(Component component) {
                toast("nothing!!!");
            }
        });
    }}
//使用自定义的DrawerLayout弹窗:
        new XPopup.Builder(getContext())
        .popupPosition(PopupPosition.Right)//右边
        .asCustom(new CustomDrawerPopupView(getContext()))
        .show();

5、ImageViewer类型

ImageViewer类型,支持大图片浏览弹窗。如下图所示,点击图片浏览按钮后,界面会弹出一个图像列表,任意点击一张图片,一张网络上的图片就加载到了界面上。

HarmonyOS弹窗组件,Xpopup-鸿蒙开发者社区

实现代码如下:

// 当你点击图片的时候执行以下代码:
// 多图片场景(你有多张图片需要浏览)
new XPopup.Builder(getContext()).asImageViewer(image, position, list,
        new OnSrcViewUpdateListener() {
@Override
public void onSrcViewUpdate(ImageViewerPopupView popupView, int position) {
        // pager更新当前显示的图片
        // 当启用isInfinite时,position会无限增大,需要映射为当前ViewPager中的页
        int realPosi = position % list.size();
        pager.setCurrentPage(realPosi, false);
        }
        }, new ImageLoader()).show();
// 单张图片场景
        new XPopup.Builder(getContext())
        .asImageViewer(image, url, new ImageLoader())
        .show();// 图片加载器,XPopup不负责加载图片,需要你实现一个图片加载器传给我,这里以Glide和OkGo为例(可直接复制到项目中):
class ImageLoader implements XPopupImageLoader {
    @Override
    public void loadImage(int position, String url, Image imageView) {
        // 一进入页面就加载图片的话,需要加点延迟
        context.getUITaskDispatcher().delayDispatch(new Runnable() {
            @Override
            public void run() {
                Glide.with(context)
                        .load(url)
                        .diskCacheStrategy(DiskCacheStrategy.ALL)
                        .into(image);
            }
        }, 50);
    }
    // 必须实现这个方法,用来下载图片。可参照下面的实现,内部保存图片会用到。如果你不需要保存图片这个功能,可以返回null。
    @Override
    public File getImageFile(Context context, String url) {
        try {
            return OkGo.<File>get(url).tag(this).converter(new FileConvert()).adapt().execute().body();
        } catch (Exception e) {
            LogUtil.error(TAG, e.getMessage());
        }
        return null;
    }

ImageViewer类型的自定义弹窗,开发者需通过继承ImageViewerPopupView接口实现。目前ImageViewer类型弹窗支持在上面添加任意自定义布局和背景颜色。

代码如下:

public class CustomImagePopup extends ImageViewerPopupView {
    public CustomImagePopup(Context context) {
        super(context, null);
    }
    @Override
    protected int getImplLayoutId() {
        return ResourceTable.Layout_custom_image_viewer_popup;
    }}

// 自定义的弹窗需要用asCustom来显示,之前的asImageViewer这些方法当然不能用了。
    CustomImagePopup viewerPopup = new CustomImagePopup(getContext());
// 自定义的ImageViewer弹窗需要自己手动设置相应的属性,必须设置的有srcView,url和imageLoader。
viewerPopup.setSingleSrcView(image2, url2);
        viewerPopup.setXPopupImageLoader(new ImageLoader());
        new XPopup.Builder(getContext())
        .asCustom(viewerPopup)
        .show();

6、FullScreen类型

FullScreen类型,是全屏弹窗。如下图所示,展示了一个铺满整个界面的弹窗。

HarmonyOS弹窗组件,Xpopup-鸿蒙开发者社区

FullScreen类型的自定义弹窗的实现代码如下:

public class CustomFullScreenPopup extends FullScreenPopupView {
    public CustomFullScreenPopup(Context context) {
        super(context, null);
    }
    @Override
    protected int getImplLayoutId() {
        return ResourceTable.Layout_custom_fullscreen_popup;
    }
    @Override
    protected void onCreate() {
        super.onCreate();
        // 初始化
    }}

7、Position类型

Position类型,是自由定位弹窗。如下图所示,通过依次点击不同位置标签,弹窗从对应的位置弹出:

HarmonyOS弹窗组件,Xpopup-鸿蒙开发者社区

Position类型的自定义弹窗的实现代码如下:

public class QQMsgPopup extends PositionPopupView {
    public QQMsgPopup(Context context) {
        super(context, null);
    }
    @Override
    protected int getImplLayoutId() {
        return ResourceTable.Layout_popup_qq_msg;
    }}
new XPopup.Builder(getContext())
        .popupAnimation(PopupAnimation.ScaleAlphaFromCenter)
//通过isCenterHorizontal(true)选项来实现水平居中
        .isCenterHorizontal(true)
//默认是显示在屏幕的左上角,可以通过offsetX()和offsetY()来控制显示位置,
        .offsetY(200)
        .asCustom(new QQMsgPopup(getContext()))
        .show();

四、Xpopup常用设置

在使用Xpopup时,开发者可以根据自身需要,通过调用相应的函数对弹窗的最大宽高、是否水平居中、是否启用拖拽等信息进行设置。可用到的函数,如下表所示:

HarmonyOS弹窗组件,Xpopup-鸿蒙开发者社区

代码如下所示:


new XPopup.Builder(getContext())
        //是否在消失的时候销毁资源,默认false。如果你的弹窗对象只使用一次,非常推荐设置这个,可以杜绝内存泄漏。如果会使用多次,千万不要设置
        .dismissOnBackPressed(true) //按返回键是否关闭弹窗,默认为true
        .customAnimator(null) //设置自定义的动画器
        .offsetX(-10) //弹窗在x方向的偏移量       
        .isDarkTheme(true)  //是否启用暗色主题      
        .borderRadius(10)  //为弹窗设置圆角,默认是15,对内置弹窗生效
        .autoDismiss(false) //操作完毕后是否自动关闭弹窗,默认为true;比如点击ConfirmPopup的确认按钮,默认自动关闭;如果为false,则不会关闭
        .setPopupCallback(new SimpleCallback() { //设置显示和隐藏的回调

以上就是整个Xpopup的使用过程,感兴趣的小伙伴赶快点击下方附件或链接下载吧!

源码链接: https://gitee.com/openharmony-tpc/XPopup

XPopup-master.zip 23.55M 24次下载
已于2021-9-6 15:05:41修改
4
收藏
回复
举报
1条回复
按时间正序
/
按时间倒序
vsrrrrrb
vsrrrrrb

支持,多些组件开发太方便了。

回复
2021-9-6 15:10:15
回复
    相关推荐