-
Notifications
You must be signed in to change notification settings - Fork 223
BottomDialog&BottomMenu_tc
🌐 View English Document | 简体中文文档
底部對話框 BottomDialog 提供從底部彈出顯示的對話框樣式,可設置標題、提示文本和自定義佈局,使用 Material 主題時還會提供向下滑動關閉和向上滑動展開的功能。
底部菜單 BottomMenu 則是底部對話框 BottomDialog 的擴展組件,在底部對話框的基礎上額外提供了菜單功能,菜單可設置菜單內容/菜單圖標/單選功能,在不同的主題下還可以提供“取消”關閉按鈕(註:因 Material 直接可以下滑關閉因此 Material 主題不提供額外的“取消”關閉按鈕)
使用以下代碼顯示一個對話框:
BottomDialog.show("標題", "這裏是對話框內容。");
請注意,Material 主題的底部對話框默認是通過下滑操作來進行關閉的,不同主題處理邏輯可能不同,例如在iOS主題中,則是提供“取消”按鈕來進行關閉。
在其他主題中你可以通過.setCancelButton(...)
方法來設置取消按鈕的文字和事件
BottomDialog.show("標題", "這裏是對話框內容。")
.setCancelButton("取消", new OnDialogButtonClickListener<BottomDialog>() {
@Override
public boolean onClick(BottomDialog baseDialog, View v) {
//...
return false;
}
});
底部菜單是基於底部對話框擴展實現的一個快速選擇菜單對話框,你可以通過傳入List<String>
、String[] menuList
、List<CharSequence> menuList
或者CharSequence[] menuList
來快速顯示一個菜單:
BottomMenu.show("新標籤頁中打開", "稍後閱讀", "複製鏈接網址")
.setMessage("這裏是標題")
.setOnMenuItemClickListener(new OnMenuItemClickListener<BottomMenu>() {
@Override
public boolean onClick(BottomMenu dialog, CharSequence text, int index) {
toast(text);
return false;
}
});
上述代碼中,OnMenuItemClickListener
回調是菜單的點擊事件回調,其中 text 為菜單文本,index 為菜單的索引。
單選菜單也可以輕鬆設置菜單圖標,我們盡可能的省去編寫 Adapter 適配器的麻煩,要設置菜單圖標可以直接指定,對於某一項菜單不需要圖標的可以直接傳入 0:
.setIconResIds(R.mipmap.img_dialogx_demo_add, R.mipmap.img_dialogx_demo_edit...)
圖標是否根據亮暗色主題進行染色處理可通過以下方法調整:
.setAutoTintIconInLightOrDarkMode(boolean)
底部菜單也提供“已選擇”功能,你可以設置一個已選擇的 index 索引,那麼在 BottomMenu 顯示時,相應位置的菜單會被選中,不同主題的選擇效果略有不同。
private int selectMenuIndex;
BottomMenu.show("拒絕", "詢問", "始終允許", "僅在使用中允許")
.setMessage("這裏是權限確認的文本說明,這是一個單選的演示菜單")
.setTitle("獲得權限標題")
.setOnMenuItemClickListener(new OnMenuItemClickListener<BottomMenu>() {
@Override
public boolean onClick(BottomMenu dialog, CharSequence text, int index) {
//記錄已選擇值
selectMenuIndex = index;
toast(text);
return false;
}
})
.setSelection(selectMenuIndex); //指定已選擇的位置
同樣的,當您在OnMenuItemClickListener
中返回值設置return true
時,點擊菜單後不會自動關閉。
或者使用實現一個回調setOnIconChangeCallBack(...)
的方式:
BottomMenu.show("添加", "查看", "編輯", "刪除")
.setOnIconChangeCallBack(new OnIconChangeCallBack(true) { //參數代表是否根據亮色/暗色模式對圖標染色
@Override
public int getIcon(BottomMenu bottomMenu, int index, String menuText) {
switch (menuText) {
case "添加":
return R.mipmap.img_dialogx_demo_add;
case "查看":
return R.mipmap.img_dialogx_demo_view;
case "編輯":
return R.mipmap.img_dialogx_demo_edit;
case "刪除":
return R.mipmap.img_dialogx_demo_delete;
}
return 0; //返回0代表不顯示圖標
}
})
.setOnMenuItemClickListener(new OnMenuItemClickListener<BottomMenu>() {
@Override
public boolean onClick(BottomMenu dialog, CharSequence text, int index) {
toast(text);
return false;
}
});
上述代碼中,OnIconChangeCallBack 存在一個參數(boolean)autoTintIconInLightOrDarkMode
用於識別是否需要將圖標進行相應的染色,以適應亮色和暗色模式的變化,設置為 true 時代表,處於亮暗色模式下,菜單圖標會自動根據文字顏色進行染色,當使用非多彩圖標的線性/面性圖標時,建議開啟此功能。
在 0.0.50.beta27 版本更新後,你還可以通過網絡異步加載菜單圖標,此功能需要使用全新的 MenuIconAdapter 來實現,具體方法如下:
.setOnIconChangeCallBack(new MenuIconAdapter<BottomMenu>(false) {
String[] urls = {
"http://www.kongzue.com/test/res/dialogx/ic_menu_add.png",
"http://www.kongzue.com/test/res/dialogx/ic_menu_read_later.png",
"http://www.kongzue.com/test/res/dialogx/ic_menu_link.png"
};
@Override
public boolean applyIcon(BottomMenu dialog, int index, String menuText, ImageView iconImageView) {
Glide.with(MainActivity.this).load(urls[index]).into(iconImageView); //演示通過 Glide 加載網絡資源到菜單圖標中
return true;
}
});
回調方法 applyIcon 中會暴露菜單圖標的 ImageView iconImageView,你可以通過任意異步框架完成圖標資源的加載,返回值 true 表示該菜單項的圖標需要顯示,返回 false 該菜單項的圖標將隱藏。
如果你需要選中菜單但不立即關閉對話框,而是保持選中狀態,等待用戶確認或取消操作再進行處理,那麼此時可以通過單選狀態回調 OnMenuItemSelectListener#onOneItemSelect
來實現對菜單實時選中狀態的監聽:
.setOnMenuItemClickListener(new OnMenuItemSelectListener<BottomMenu>() {
@Override
public void onOneItemSelect(BottomMenu dialog, CharSequence text, int index, boolean select) {
//index 即用戶點擊的菜單項索引
}
})
//開啟單選模式,以下方式二選一:
.setSelection(selectMenuIndex) //開啟單選模式,並指定一個已選項
.setSingleSelection() //開啟單選模式,但不指定已選項
此時,用戶點擊菜單後對話框不會立即消失,而是等待用戶可能再次修改選擇。
要在對話框關閉時,或之後再獲取用戶已選擇的菜單項,可以通過 .getSelectionIndex()
方法獲取用戶當前選中的菜單索引,另可通過 .getMenuList()
獲取所有的菜單文本。
要開啟多選菜單,你可以通過以下代碼實現,使用多選菜單狀態回調實時獲取選中項:
.setOnMenuItemClickListener(new OnMenuItemSelectListener<BottomMenu>() {
@Override
public void onMultiItemSelect(BottomMenu dialog, CharSequence[] text, int[] index) {
//index[] 數組是所有已選中菜單項的索引集合,text[] 是所有已選中菜單項文本的集合
}
})
//開啟多選模式,以下方式二選一:
.setSelection(selectMenuIndexArray); //開啟多選模式,並指定一個已選中的索引數組
.setMultiSelection() //開啟多選模式,但不指定已選項
此時,用戶點擊菜單後對話框不會立即消失,而是等待用戶可能再次修改或繼續其他選擇。
要在對話框關閉時,或之後再獲取用戶已選擇的菜單項,可以通過 .getSelectionIndexArray()
方法獲取用戶當前選中的菜單索引集合,通過 .getSelectTextArray()
獲取已選中的菜單文本集合,另可通過 .getMenuList()
獲取所有的菜單文本。
BottomDialog 和 BottomMenu 和 MessageDialog 一樣,也支持設置 OK、Cancel、Other 按鈕的顯示,但請注意,部分主題可能不支持額外的 Cancel 和 Other 兩個按鈕。
要設置按鈕和回調,與 MessageDialog 類似,使用以下代碼進行設置:
.setOkButton("OK", new OnDialogButtonClickListener<BottomDialog>() {
@Override
public boolean onClick(BottomDialog dialog, View v) {
//...
return false;
}
})
.setCancelButton("Cancel", new OnDialogButtonClickListener<BottomDialog>() {
@Override
public boolean onClick(BottomDialog dialog, View v) {
//...
return false;
}
})
.setOtherButton("Other", new OnDialogButtonClickListener<BottomDialog>() {
@Override
public boolean onClick(BottomDialog dialog, View v) {
//...
return false;
}
})
回調中有一個返回值,若return true
則可以點擊後不自動關閉對話框。
另外,DialogX 還提供了多種設置回調和按鈕文本的方法:
//只設置按鈕文本
.setOkButton("確定")
//只設置按鈕點擊回調
.setOkButton(new OnDialogButtonClickListener<BottomDialog>() {
@Override
public boolean onClick(BottomDialog dialog, View v) {
toast("點擊確定按鈕");
return false;
}
});
//設置按鈕文本並設置回調
.setOkButton("確定", new OnDialogButtonClickListener<BottomDialog>() {
@Override
public boolean onClick(BottomDialog dialog, View v) {
toast("點擊確定按鈕");
return false;
}
});
//隱藏按鈕
.setOkButton(null)
請依據個人喜好隨意使用。
如果你的業務流程中,並不需要對用戶操作立即進行處理,但需要知道用戶選擇了哪個按鈕,你也可以通過持有對話框句柄,在後續獲取選擇的狀態,例如:
private BottomDialog dialog;
//業務流程模擬,創建並顯示了一個對話框,但不立即處理點擊事務
dialog = BottomDialog.show(...);
//需要時可根據 getButtonSelectResult() 方法獲取用戶點擊了哪個按鈕選項
BUTTON_SELECT_RESULT result = dialog.getButtonSelectResult();
BUTTON_SELECT_RESULT 是一個枚舉,它包含以下類型:
NONE, //未做出選擇
BUTTON_OK, //選擇了確定按鈕
BUTTON_CANCEL, //選擇了取消按鈕
BUTTON_OTHER //選擇了其他按鈕
你可以根據它的狀態判斷用戶點擊了哪個按鈕。
基於這個特性,如果業務流程中針對用戶的選擇,無論選擇哪個選項都有相同部分的代碼需要執行,那麼開發者也可以在用戶選擇後,例如在 DialogLifecycle#onDismiss
對話框的關閉事件中對用戶的選擇進行統一處理,減少重複代碼量;
想要監控對話框的生命週期,可以實現其 .setDialogLifecycleCallback(...)
接口,建議使用build()
方法構建對話框:
BottomMenu.build()
.setDialogLifecycleCallback(new DialogLifecycleCallback<BottomMenu>() {
@Override
public void onShow(BottomMenu dialog) {
//對話框啟動時回調
}
@Override
public void onDismiss(BottomMenu dialog) {
//對話框關閉時回調
}
})
.show();
BottomDialog/BottomMenu 也支持 Lifecycle,你可以使用 .getLifecycle()
獲取 Lifecycle 對象。
對於可滑動的 BottomDialog/BottomMenu(受限於主題),可以使用增強型的 DialogLifecycleCallback 實現 BottomDialogSlideEventLifecycleCallback,它可以提供關於滑動過程以及滑動關閉的擴展事件處理和回調:
.setDialogLifecycleCallback(new BottomDialogSlideEventLifecycleCallback<BottomDialog>() {
@Override
public boolean onSlideClose(BottomDialog dialog) {
log("滑動關閉對話框觸發");
return false; //默認返回 false,當返回 true 時表示攔截操作,對話框不會繼續關閉;
}
@Override
public boolean onSlideTouchEvent(BottomDialog dialog, View v, MotionEvent event) {
log("#滑動過程觸發: action="+ event.getAction() + " y="+event.getY());
return false; //默認返回 false,當返回 true 時表示攔截操作,對話框不會處理滑動流程,可實現觸摸事件接管;
}
})
你也可以通過使用 new 構建實例時,override 的生命週期事件的方式來處理生命週期事務,例如:
//複寫事件演示
new BottomDialog() {
@Override
public void onShow(BottomDialog dialog) {
//...
tip("onShow");
}
@Override
public void onDismiss(BottomDialog dialog) {
//...
tip("onDismiss");
}
}
你也可以使用方法 .onShow(DialogXRunnable)
和 .onDismiss(DialogXRunnable)
,來處理生命週期事務,例如:
BottomDialog.show(...)
.onShow(new DialogXRunnable<BottomDialog>() {
@Override
public void run(BottomDialog dialog) {
//BottomDialog show!
}
})
.onDismiss(new DialogXRunnable<BottomDialog>() {
@Override
public void run(BottomDialog dialog) {
//BottomDialog dismiss!
}
});
BottomDialog 原生參數支持自定義佈局,你可以通過如下代碼自定義底部對話框佈局:
BottomDialog.show("標題", "這裏是對話框內容。\n底部對話框也支持自定義佈局擴展使用方式。",
new OnBindView<BottomDialog>(R.layout.layout_custom_view) {
@Override
public void onBind(BottomDialog dialog, View v) {
//v.findViewById...
}
});
BottomMenu 菜單需要使用如下代碼加入自定義佈局:
BottomMenu.show("新標籤頁中打開", "稍後閱讀", "複製鏈接網址")
.setMessage("菜單標題")
.setOnMenuItemClickListener(new OnMenuItemClickListener<BottomMenu>() {
@Override
public boolean onClick(BottomMenu dialog, CharSequence text, int index) {
toast(text);
return true;
}
})
.setCustomView(new OnBindView<BottomDialog>(R.layout.layout_custom_view) {
@Override
public void onBind(BottomDialog dialog, View v) {
//v.findViewById...
}
});
回調參數中,v
為您給定的佈局文件的實例化組件,您可以通過 v.findViewById(resId)
來實例化其他子佈局組件,並在 onBind
方法中設置其功能和事件回調。
使用 ViewBinding 的話也可以更換為 OnBindingView 來實現直接通過 binding 獲取佈局實例:
BottomDialog.show("標題", "這裏是對話框內容。\n底部對話框也支持自定義佈局擴展使用方式。",
new OnBindingView<BottomDialog, LayoutCustomViewBinding>() {
@Override
public void onBind(BottomDialog dialog, View view, LayoutCustomViewBinding binding) {
//View childView = binding.childView
}
});
//設置菜單項目(無級)
.setMenus("添加", "編輯", "刪除", "分享"...);
//設置圖標(無級)
.setIconResIds(R.mipmap.img_dialogx_demo_add, R.mipmap.img_dialogx_demo_edit...)
//設置菜單項目(列表或集合)
.setMenuList(list);
//強制重新刷新界面
.refreshUI();
//關閉對話框
.dismiss();
//是否允許點擊外部區域或返回鍵關閉
.setCancelable(boolean);
//設置標題文字樣式
.setTitleTextInfo(TextInfo);
//設置消息文字樣式
.setMessageTextInfo(TextInfo);
//設置按鈕文字樣式
.setCancelTextInfo(TextInfo);
//設置返回按鍵回調
.setOnBackPressedListener(OnBackPressedListener);
//獲取對話框實例化對象,您可以通過此方法更深度的訂製Dialog的功能
.getDialogImpl()
//獲取自定義佈局實例
.getCustomView()
//設置背景顏色,強行對對話框背景進行染色,請注意參數為int類型的顏色值而非R.color的索引
.setBackgroundColor(ColorInt);
//設置菜單文本樣式
.setMenuTextInfo(TextInfo)
//設置對話框圓角(會裁切內容顯示,此設置在 BottomDialog 和 BottomMenu 中只影響左上、右上兩個角的圓角)
.setRadius(float px)
//隱藏對話框(無動畫),恢復顯示請執行非靜態方法的 .show()
.hide();
//隱藏對話框(模擬關閉對話框的動畫),恢復顯示請執行非靜態方法的 .show()
.hideWithExitAnim();
//是否允許滑動關閉(僅對 Material 主題有效)
.setAllowInterceptTouch(boolean)
//是否處於顯示狀態
.isShow()
//置頂對話框
.bringToFront()
//指定對話框顯示層級
.setThisOrderIndex(int)
BottomDialog 支持修改背景遮罩,這是為了豐富擴展性。如果需要背景遮罩,您可以自行使用如下代碼設置:
bottomDialog.setMaskColor(colorInt);
請注意,傳入參數為 ColorInt 值,您可以使用 Color.parseColor("#4D000000")
設置一個 HEX 色值,或使用 getResources().getColor(R.color.black30)
設置一個顏色的資源值。
TextInfo 用於存儲基礎文本樣式設置,其包含一系列屬性和響應的 get/set 方法,例如方法解釋如下:
屬性 | 解釋 | 默認值 |
---|---|---|
fontSize | 字號大小,值為-1時使用默認樣式,單位:dp | -1 |
gravity | 對齊方式,值為-1時使用默認樣式,取值可使用Gravity.CENTER 等對齊方式 |
-1 |
fontColor | 文字顏色,值為1時使用默認樣式,取值可以用Color.rgb(r,g,b)等方式獲取 | 1 |
bold | 是否粗體 | false |
請注意,fontColor 為 ColorInt 值,您可以使用 Color.parseColor("#4D000000")
設置一個 HEX 色值,或使用資源 getResources().getColor(R.color.black30)
設置一個顏色的資源值,請勿直接傳入資源 ID,它可能會無效。
在使用 Material 主題風格且底部對話框,默認是可滑動關閉的,且當 cancelable
值為 true 時,會在對話框頂部顯示一個 “滑動提示條”,若依據您的需求需要隱藏其顯示,可通過以下方式關閉:
禁用向下滑動對話框以關閉 BottomDialog 可以隱藏滑動提示條。
.setAllowInterceptTouch(false)
借助 DialogX 暴露內部元素的特性,刪除 tab 佈局。
BottomDialog.show("標題", "這裏是對話框內容。\n底部對話框也支持自定義佈局擴展使用方式。",
new OnBindView<BottomDialog>(R.layout.layout_custom_view) {
@Override
public void onBind(BottomDialog dialog, View v) {
if (dialog.getDialogImpl().imgTab != null) {
((ViewGroup) dialog.getDialogImpl().imgTab.getParent()).removeView(dialog.getDialogImpl().imgTab);
}
//...
}
});
手動創建一個 layout_dialogx_bottom_material
的佈局(暗色對應 layout_dialogx_bottom_material_dark
),內容請參考 layout_dialogx_bottom_material.xml(暗色對應 layout_dialogx_bottom_material_dark.xml)
修改刪除其中 <ImageView id="@+id/img_tab">
的佈局:
<ImageView
android:id="@+id/img_tab"
android:layout_width="30dp"
android:layout_height="4dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:src="@drawable/rect_dialogx_material_dialogtap" />
此方案利用的是對資源的重寫方式完成修改,請無需擔心空指針,DialogX 內部有做對應處理。
若你的 App 引入了多種主題,在特定場景下需要使對話框顯示為某種非全局的主體樣式,可使用 .build()
構建對話框,然後使用 .setStyle(style)
來指定主題樣式,在最後執行 .show()
命令顯示對話框,例如:
BottomDialog.build()
//或直接使用 .build(IOSStyle.style())
.setStyle(IOSStyle.style())
.setTitle("Title")
.setMessage("Message content.")
.setOkButton("OK")
.show();