鴻蒙開源三方組件--強大的彈窗庫XPopup組件
1. 介紹
XPopup是一個彈窗庫,可能是Harmony平臺最好的彈窗庫。它從設計的時候就本著實用的原則,兼顧了美觀和優雅的交互。用戶都喜歡自然舒適的UI和交互,希望XPopup能帶給你一些幫助或者驚喜!
2. 效果一覽
相關效果演示可以點擊鏈接前往原文章進行觀看:
https://harmonyos.51cto.com/posts/4198
3. 依賴
- allprojects{
- repositories{
- mavenCentral()
- }
- }
- implementation 'io.openharmony.tpc.thirdlib:XPopup:1.0.3'
4. 如何使用
4.1 內置彈窗的使用
4.1.1 顯示確認和取消對話框
- new XPopup.Builder(getContext()).asConfirm("我是標題", "我是內容",
- new OnConfirmListener() {
- @Override
- public void onConfirm() {
- toast("click confirm");
- }
- })
- .show();
4.1.2 顯示待輸入框的確認和取消對話框
- new XPopup.Builder(getContext()).asInputConfirm("我是標題", "請輸入內容。",
- new OnInputConfirmListener() {
- @Override
- public void onConfirm(String text) {
- toast("input text: " + text);
- }
- })
- .show();
4.1.3 顯示中間彈出的列表彈窗
- new XPopup.Builder(getContext())
- //.maxWidth(600)
- .asCenterList("請選擇一項", new String[]{"條目1", "條目2", "條目3", "條目4"},
- new OnSelectListener() {
- @Override
- public void onSelect(int position, String text) {
- toast("click " + text);
- }
- })
- .show();
4.1.4 顯示中間彈出的加載框
- new XPopup.Builder(getContext())
- .asLoading("正在加載中")
- .show();
4.1.5 顯示從底部彈出的列表彈窗
- new XPopup.Builder(getContext())
- .asBottomList("請選擇一項", new String[]{"條目1", "條目2", "條目3", "條目4", "條目5"},
- new OnSelectListener() {
- @Override
- public void onSelect(int position, String text) {
- toast("click " + text);
- }
- })
- .show();
4.1.6 顯示依附于某個Component或者某個點的彈窗
- 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的觸摸點,則需要先watch該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();
- }
- });
asAttachList方法內部是對AttachPopupView的封裝,如果你的布局不是列表,可以繼承AttachPopupView實現自己想要的布局。AttachPopupView會出現在目標的上方或者下方,如果你想要出現在目標的左邊或者右邊(像微信朋友圈那樣點贊的彈窗),可以繼承HorizontalAttachPopupView,然后編寫你的布局即可。
最簡單的示例如下:
- public class CustomAttachPopup extends HorizontalAttachPopupView {
- public CustomAttachPopup(Context context) {
- super(context, null);
- }
- @Override
- protected int getImplLayoutId() {
- return ResourceTable.Layout_custom_attach_popup;
- }
- @Override
- protected void onCreate() {
- super.onCreate();
- findComponentById(ResourceTable.Id_tv_zan).setClickedListener(new ClickedListener() {
- @Override
- public void onClick(Component component) {
- ToastUtil.showToast(getContext(), "贊");
- dismiss();
- }
- });
- findComponentById(ResourceTable.Id_tv_comment).setClickedListener(new ClickedListener() {
- @Override
- public void onClick(Component component) {
- ToastUtil.showToast(getContext(), "評論");
- dismiss();
- }
- });
- } // 設置狀態欄的高度,用以修正自定義位置彈窗的高度
- @Override
- protected int setStatusBarHeight() {
- return 130;
- }}
4.1.7 顯示大圖瀏覽彈窗
- // 當你點擊圖片的時候執行以下代碼:
- // 多圖片場景(你有多張圖片需要瀏覽)
- 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;
- }
- }
如果你用的不是Glide,請參考去實現即可。
4.1.8 關閉彈窗
先拿到彈窗對象,以Loading彈窗為例,其他也是一樣:
- BasePopupView popupView = new XPopup.Builder(getContext())
- .asLoading("正在加載中")
- .show();
執行消失:
- //有四個消失方法可供選擇:
- popupView.dismiss();
- //立即消失
- popupView.delayDismiss(300);
- //延時消失,有時候消失過快體驗可能不好,可以延時一下
- popupView.smartDismiss();
- //會等待彈窗的開始動畫執行完畢再進行消失,可以防止接口調用過快導致的動畫不完整。
- popupView.dismissWith({});
- //消失動畫執行完之后執行某些邏輯
我們在項目中經常會點擊某個按鈕然后關閉彈窗,接著去做一些事。比如:點擊一個按鈕,關閉彈窗,然后開啟一個界面,要知道彈窗的關閉是有一個動畫過程的,上面的寫法會出現彈窗還沒有完全關閉,就立即跳頁面,界面有一種頓挫感;而且在設備資源不足的時候,還可能造成丟幀。所以很多時候不推薦直接使用dismiss()方法,除非你關閉完彈窗后面沒有任何邏輯執行。
為了得到最佳體驗,您可以等dismiss動畫完全結束去執行一些東西,而不是立即就執行。可以這樣做:
- popupView.dismissWith(new Runnable() {
- @Override
- public void run() {
- // 跳轉到新頁面
- }});
每個彈窗本身也有onShow()和onDismiss()的生命周期回調,可以根據需要使用。
還有這樣一種場景:彈窗show()完之后,你的邏輯執行完畢,然后調用dismiss()。但是你的邏輯執行過快,可能導致彈窗的show動畫還沒有執行完就直接dismiss了,界面上的感覺并不好。這個時候推薦使用smartDismiss()方法,這個方法能保證彈窗的show動畫執行完再關閉彈窗。
4.1.9 復用項目已有布局
如果你項目中已經有寫好的彈窗布局,而想用XPopup提供的動畫和交互能力,也是完全沒有問題的。目前支持設置自定義布局的彈窗有:
Confirm彈窗,就是確認和取消彈窗
- 帶輸入框的Confirm彈窗
- Loading彈窗
- 帶列表的Attach彈窗,Center彈窗和Bottom彈窗
假設,你想使用XPopup的Confirm彈窗,但布局想用自己的,只需要這樣設置一下,其他不用動即可:
- new XPopup.Builder(getContext())
- .asConfirm(null, "您可以復用項目已有布局,來使用XPopup強大的交互能力和邏輯封裝,彈窗的布局完全由你自己控制。\n" +
- "需要注意的是:你自己的布局必須提供一些控件Id,否則XPopup找不到控件。",
- "關閉", "XPopup牛逼",
- new OnConfirmListener() {
- @Override
- public void onConfirm() {
- toast("click confirm");
- }
- }, null, false, ResourceTable.Layout_my_confim_popup)//綁定已有布局
- .show();
這樣布局就是您自己的了,動畫和交互XPopup會幫你完成。但是需要注意的是,你自己提供的布局必須包含一些id,否則XPopup無法找到控件;id必須有,控件你可以隨意組合與擺放。具體如下:
- Confirm彈窗必須包含的Text以及id有:tv_title,tv_content,tv_cancel,tv_confirm
- 帶輸入框的Confirm彈窗在Confirm彈窗基礎上需要增加一個id為et_input的TextField
- Loading彈窗,如果你想顯示一個Loading文字說明,則必須有一個id為tv_title的Text;如果不需要文字說明,則沒要求
- 帶列表的彈窗會多一個bindItemLayout()方法用來綁定item布局
- 其他不在多說,看bindLayout方法說明,會說明要求哪些id
每種內置彈窗的bindLayout和bindItemLayout的要求都在方法說明上,無需記憶,用的時候查看下方法的說明即可。
4.2 自定義彈窗
當你自定義彈窗的時候,需要根據需求選擇繼承CenterPopupView,BottomPopupView,AttachPopupView/HorizontalAttachPopupView,DrawerPopupView,PartShadowPopupView,FullScreenPopupView,PositionPopupView其中之一。
每種彈窗的功能和使用場景如下:
- CenterPopupView:中間彈窗的彈窗,比如:確認取消對話框,Loading彈窗等,如果不滿意默認的動畫效果,可以設置不同的動畫器
- BottomPopupView:從底部彈出的彈窗,比如:從底部彈出的分享彈窗,知乎的從底部彈出的評論彈窗,抖音從底部彈出的評論彈窗。這種彈窗帶有智能的嵌套滾動和手勢拖動
- AttachPopupView/HorizontalAttachPopupView:Attach彈窗是需要依附于某個點或者某個Component來顯示的彈窗;其中AttachPopupView會出現在目標的上方或者下方。如果希望想要微信朋友圈點贊彈窗那樣的效果,出現在目標的左邊或者右邊,則需要繼承 HorizontalAttachPopupView來做
- DrawerPopupView:從界面的左邊或者右邊彈出的像DrawerLayout那樣的彈窗,Drawer彈窗本身是橫向滑動的,但對PageSlider和ScrollView等橫向滑動控件做了兼容,在彈窗內部可以放心使用它們
- FullScreenPopupView:全屏彈窗,看起來和Ability 一樣。該彈窗其實是繼承Center彈窗進行的一種實現,可以設置任意的動畫器
- ImageViewerPopupView:大圖瀏覽彈窗
- PositionPopupView:自由定位彈窗,如果你想讓彈窗顯示在左上角,或者右上角,或者任意位置,并且不需要依附任何Component,此時你需要它
自定義彈窗只有2個步驟:
一:根據自己的需求編寫一個類繼承對應的彈窗
二:重寫getImplLayoutId()返回彈窗的布局,在onCreate中像Ability那樣編寫你的邏輯即可
注意:自定義彈窗本質是一個自定義控件,但是只需重寫一個參數的構造,其他的不要重寫,所有的自定義彈窗都是這樣。
4.2.1 自定義Center彈窗
- 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;
- }}
注意:Center彈窗的最大寬度默認是屏幕寬度的0.8,如果你自定義布局的寬度是寫死的,有可能超出屏幕寬度的0.8,如果你不想被最大寬度限制,只需要重寫方法:
- @Overrideprotected int getMaxWidth() {
- return 0;
- //返回0表示不限制最大寬度
- }
使用自定義彈窗:
- new XPopup.Builder(getContext())
- .asCustom(new CustomPopup(getContext()))
- .show();
4.2.2 自定義Attach彈窗
- 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.2.3 自定義DrawerLayout類型彈窗
- 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();
4.2.4 自定義Bottom類型的彈窗
自定義Bottom類型的彈窗會比較常見,默認Bottom彈窗帶有手勢交互和嵌套滾動;如果您不想要手勢交互可以調用enableDrag(false)方法關閉。
請注意:彈窗的寬高是自適應的,大部分情況下都應該將彈窗布局的高設置為match_content;除非你希望得到一個高度撐滿的彈窗。
Demo中有一個模仿知乎評論的實現,代碼如下:
- 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);
- }}
4.2.5 自定義全屏彈窗
- 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();
- // 初始化
- }}
4.2.6 自定義ImageViewer彈窗
目前大圖瀏覽彈窗支持在上面添加任意自定義布局和背景顏色,做法是寫一個類繼承ImageViewerPopupView彈窗,然后重寫布局即可。
代碼如下:
- 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();
4.2.7 自定義Position彈窗
- public class QQMsgPopup extends PositionPopupView {
- public QQMsgPopup(Context context) {
- super(context, null);
- }
- @Override
- protected int getImplLayoutId() {
- return ResourceTable.Layout_popup_qq_msg;
- }}
自由定位彈窗,默認是顯示在屏幕的左上角,你可以通過offsetX()和offsetY()來控制顯示位置,如果你希望水平居中,可以用isCenterHorizontal(true)選項來做到。
- new XPopup.Builder(getContext())
- .popupAnimation(PopupAnimation.ScaleAlphaFromCenter)
- .isCenterHorizontal(true)
- .offsetY(200)
- .asCustom(new QQMsgPopup(getContext()))
- .show();
4.3 自定義動畫
自定義動畫已經被設計得非常簡單,動畫和彈窗是無關的;這意味著你可以將動畫設置給內置彈窗或者自定義彈窗。繼承PopupAnimator,實現3個方法:
- 如何初始化動畫
- 動畫如何開始
- 動畫如何結束
比如:自定義一個旋轉的動畫:
- class RotateAnimator extends PopupAnimator {
- @Override
- public void initAnimator() {
- targetView.setScaleX(0.0f);
- targetView.setScaleY(0.0f);
- targetView.setAlpha(0.0f);
- targetView.setRotation(360.0f);
- }
- @Override
- public void animateShow() {
- targetView.createAnimatorProperty().rotate(0.0f).scaleX(1.0f).scaleY(1.0f).alpha(1.0f).setDuration(getDuration()).start();
- }
- @Override
- public void animateDismiss() {
- targetView.createAnimatorProperty().rotate(720.0f).scaleX(0.0f).scaleY(0.0f).alpha(0.0f).setDuration(getDuration()).start();
- }}
使用自定義動畫:
- new XPopup.Builder(getContext())
- .customAnimator(new RotateAnimator())
- .asConfirm("演示自定義動畫", "當前的動畫是一個自定義的旋轉動畫,無論是自定義彈窗還是自定義動畫,已經被設計得非常簡單;這個動畫代碼只有6行即可完成!", null)
- .show();
不想要動畫:
- new XPopup.Builder(getContext())
- .customAnimator(new EmptyAnimator(null))
- .asConfirm("演示自定義動畫", "當前的動畫是一個自定義的旋轉動畫,無論是自定義彈窗還是自定義動畫,已經被設計得非常簡單;這個動畫代碼只有6行即可完成!", null)
- .show();
4.4 常用設置
4.4.1 全局設置
1.設置主色調 默認情況下,XPopup的主色為灰色,主色作用于Button文字,TextField邊框和光標,Check文字的顏色上。 主色調只需要設置一次即可,可以放在啟動頁中。
- XPopup.setPrimaryColor(getColor(ResourceTable.Color_colorPrimary));
2.設置全局的動畫時長 默認情況下,彈窗的動畫時長為360毫秒。你可以通過下面的方法進行修改:
- XPopup.setAnimationDuration(200); // 傳入的時長最小為0,動畫的時長會影響除Drawer彈窗外的所有彈窗
4.4.2 常用設置
所有的設置如下,根據需要使用:
- new XPopup.Builder(getContext())
- .isDestroyOnDismiss(true) //是否在消失的時候銷毀資源,默認false。如果你的彈窗對象只使用一次,非常推薦設置這個,可以杜絕內存泄漏。如果會使用多次,千萬不要設置
- .dismissOnBackPressed(true) //按返回鍵是否關閉彈窗,默認為true
- .dismissOnTouchOutside(true) //點擊外部是否關閉彈窗,默認為true
- .autoOpenSoftInput(true) //是否彈窗顯示的同時打開輸入法,只在包含輸入框的彈窗內才有效,默認為false
- .popupAnimation(PopupAnimation.ScaleAlphaFromCenter) //設置內置的動畫
- .customAnimator(null) //設置自定義的動畫器
- .popupPosition(PopupPosition.Right) //手動指定彈窗出現在目標的什么位置,對Attach和Drawer類型彈窗生效
- .positionByWindowCenter(false) //默認是false,是否以屏幕中心進行定位,默認是false,為false時根據Material范式進行定位,主要影響Attach系列彈窗
- .offsetX(-10) //彈窗在x方向的偏移量 .offsetY(-10) //彈窗在y方向的偏移量
- .maxWidth(10) //設置彈窗的最大寬度,如果重寫彈窗的getMaxWidth(),以重寫的為準
- .maxHeight(10) //設置彈窗的最大高度,如果重寫彈窗的getMaxHeight(),以重寫的為準
- .isCenterHorizontal(true) //是否和目標水平居中,比如:默認情況下Attach彈窗依靠著目標的左邊或者右邊,如果isCenterHorizontal為true,則與目標水平居中對齊
- .isRequestFocus(false) //默認為true,默認情況下彈窗會搶占焦點,目的是為了響應返回按鍵按下事件;如果為false,則不搶焦點
- .enableDrag(true) //是否啟用拖拽,默認為true,目前對Bottom和Drawer彈窗有用
- .isDarkTheme(true) //是否啟用暗色主題 .borderRadius(10) //為彈窗設置圓角,默認是15,對內置彈窗生效
- .autoDismiss(false) //操作完畢后是否自動關閉彈窗,默認為true;比如點擊ConfirmPopup的確認按鈕,默認自動關閉;如果為false,則不會關閉
- .setPopupCallback(new SimpleCallback() { //設置顯示和隱藏的回調
- @Override public void onCreated(BasePopupView basePopupView) {
- // 彈窗內部onCreate執行完調用
- }
- @Override
- public void beforeShow(BasePopupView basePopupView) {
- // 每次show之前都會執行
- }
- @Override
- public void onShow(BasePopupView basePopupView) {
- // 完全顯示的時候執行
- }
- @Override
- public void onDismiss(BasePopupView basePopupView) {
- // 完全隱藏的時候執行
- }
- // 如果你自己想攔截返回按鍵事件,則重寫這個方法,返回true即可
- @Override
- public boolean onBackPressed(BasePopupView basePopupView) {
- new ToastDialog(getContext()).setText("我攔截的返回按鍵,按返回鍵XPopup不會關閉了").show();
- return true; //默認返回false
- }
- //監聽彈窗拖拽,適用于能拖拽的彈窗
- @Override
- public void onDrag(BasePopupView popupView, int value, float percent,boolean upOrLeft) {
- }
- })
- .asXXX() //所有的設置項都要寫在asXXX()方法調用之前
5. 下載鏈接
5.1 IDE下載鏈接
https://developer.harmonyos.com/cn/develop/deveco-studio#download
5.2 源碼鏈接
https://gitee.com/openharmony-tpc/XPopup