Markdown版本筆記 | 我的GitHub首頁 | 我的博客 | 我的微信 | 我的郵箱 |
---|---|---|---|---|
MyAndroidBlogs | baiqiantao | baiqiantao | bqt20094 | baiqiantao@sina.com |
QMUI UI庫 控件 彈窗 列表 工具類
目錄
簡介
使用步驟
基本組成
彈窗相關組件
列表相關
頂部欄相關
TextView相關
Span相關
其他
工具類
演示案例
QMUIDialog
QMUIBottomSheet 和 QMUITipDialog 和 QMUIPopup
QMUITabSegment
簡介
Android UI 解決方案
QMUI Android 的設計目的是用於輔助快速搭建一個具備基本設計還原效果
的 Android 項目,同時利用自身提供的豐富控件及兼容處理,讓開發者能專注於業務需求而無需耗費精力在基礎代碼的設計上。
不管是新項目的創建,或是已有項目的維護,均可使開發效率和項目質量得到大幅度提升。
特點
全局 UI 配置
:只需要修改一份配置表
就可以調整 App 的全局樣式
,包括組件顏色、導航欄、對話框、列表
等。一處修改,全局生效。豐富的 UI 控件
:提供豐富常用的 UI 控件,例如 BottomSheet、Tab、圓角ImageView、下拉刷新等,使用方便靈活,並且支持自定義控件的樣式。高效的工具方法
:提供高效的工具方法,包括設備信息、屏幕信息、鍵盤管理、狀態欄管理等,可以解決各種常見場景並大幅度提升開發效率。
使用步驟
引入庫
最新的庫會上傳到 JCenter 倉庫上,請確保配置了 JCenter 倉庫源,然后直接引用:
compile 'com.qmuiteam:qmui:1.0.6'
配置主題
把項目的 theme 的 parent 指向 QMUI.Compat
或 QMUI
,至此,QMUI 可以正常工作。
覆蓋組件的默認表現
你可以通過在項目中的 theme 中用 <item name="(name)">(value)</item>
的形式來覆蓋 QMUI 組件的默認表現。具體可指定的屬性名請參考 @style/QMUI.Compat
或 @style/QMUI
中的屬性。
基本組成
彈窗相關組件
QMUIDialog
提供了一系列常用的對話框,解決了使用系統默認對話框時在不同 Android 版本上的表現不一致的問題。使用不同的 Builder 來構建不同類型的對話框,這些 Builder 都擁有設置 title 和添加底部按鈕的功能,不同的 Builder 特有的作用如下:
MessageDialogBuilder
:消息類型的對話框 Builder。通過它可以生成一個帶標題、文本消息、按鈕的對話框。ConfirmMessageDialogBuilder
:帶 Checkbox 的消息確認框 Builder。EditTextDialogBuilder
:帶輸入框的對話框 Builder。MenuDialogBuilder
:菜單對話框 Builder。CheckableDialogBuilder
:單選類型的對話框 Builder。MultiCheckableDialogBuilder
:多選類型的對話框 Builder。CustomDialogBuilder
:自定義對話框內容區域的 Builder。AutoResizeDialogBuilder
:隨鍵盤升降自動調整 Dialog 高度的 Builder
QMUITipDialog
提供一個浮層展示在屏幕中間,提供了以下兩種樣式:
- 使用
QMUITipDialog.Builder
生成,提供了一個圖標和一行文字的樣式, 其中圖標有 Loading、成功、失敗等類型可選。 - 使用
QMUITipDialog.CustomBuilder
生成,支持傳入自定義的 layoutResId。
QMUIBottomSheet
在 Dialog 的基礎上重新定制了 show() 和 hide() 時的動畫效果, 使 Dialog 在界面底部升起和降下。提供了以下兩個面板樣式:
- 列表樣式:使用
QMUIBottomSheet.BottomListSheetBuilder
生成。 - 宮格類型:使用
QMUIBottomSheet.BottomGridSheetBuilder
生成。
QMUIPopup
提供一個浮層,支持自定義浮層的內容,支持在指定 View 的任一方向旁邊展示該浮層,支持自定義浮層出現/消失的動畫。
QMUIListPopup
繼承自 QMUIPopup,在 QMUIPopup 的基礎上,支持顯示一個列表。
QMUIProgressBar
一個進度條控件,通過顏色變化顯示進度,支持環形和矩形兩種形式,主要特性如下:
- 支持在進度條中以文字形式顯示進度,支持修改文字的顏色和大小。
- 可以通過 xml 屬性修改進度背景色,當前進度顏色,進度條尺寸。
- 支持限制進度的最大值。
列表相關
QMUIGroupListView
通用的列表,常用於 App 的設置界面,注意其父類不是 ListView 而是 LinearLayout,所以一般要配合 ScrollView 使用。提供了 Section 的概念,用來將列表分塊。 配合 QMUIGroupListView.Section
, QMUICommonListItemView
和 QMUIGroupListSectionHeaderFooterView
使用。
QMUIWrapContentListView
支持高度值為 wrap_content 的 ListView,解決原生 ListView 在設置高度為 wrap_content 時高度計算錯誤的 bug。
QMUIAnimationListView
使 ListView 支持添加/刪除 Item 的動畫,支持自定義動畫效果。
QMUICommonListItemView
用作通用列表 QMUIGroupListView 里的 Item,也可單獨使用。支持以下樣式:
- 展示一行文字。
- 在右側或下方增加一行說明文字。
- 在 item 右側顯示一個開關或箭頭或自定義的View
QMUIGroupListSectionHeaderFooterView
用作通用列表 QMUIGroupListView 里每個 Section 的頭部或尾部,也可單獨使用。
QMUIItemViewsAdapter
一個帶 cache 功能的“列表型數據-View”的適配器,適用於自定義 View 需要顯示重復單元 ListView 的情景,cache 功能主要是保證在需要多次刷新數據或布局的情況下(ListView 或 RecycleView 的 itemView)復用已存在的 View。QMUI 用於 QMUITabSegment 中 Tab 與數據的適配。
QMUIPullRefreshLayout
下拉刷新控件。支持自定義 RefreshView(表示正在刷新的 View),觸發刷新的位置等特性。
QMUIEmptyView
通用的空界面控件,支持顯示 loading、主標題和副標題、圖片。
QMUILoadingView
用於顯示 Loading 的 View,支持顏色和大小的設置。
QMUIObservableScrollView
可以監聽滾動事件的 ScrollView,並能在滾動回調中獲取每次滾動前后的偏移量。
頂部欄相關
QMUITopBar
通用的頂部 Bar。提供了以下功能:
- 在左側/右側添加圖片按鈕/文字按鈕/自定義View。
- 設置標題/副標題,且支持設置標題/副標題的水平對齊方式。
QMUITopBarLayout
對 QMUITopBar 的包裹類,並代理了 QMUITopBar 的方法。配合 QMUIWindowInsetLayout 使用,可使 QMUITopBar 在支持沉浸式狀態欄的界面中頂部延伸到狀態欄。
QMUIWindowInsetLayout
配合沉浸式狀態欄使用,用於協調子 View 的 fitSystemWindows。
QMUITabSegment
用於橫向多個 Tab 的布局,包含多個特性:
- 可以用 xml 或 QMUITabSegment 提供的 set 方法統一配置文字顏色、icon 位置、是否要下划線等。
- 每個 Tab 都可以非常靈活的配置,內容上支持文字和 icon 的顯示,icon 支持選中態,支持內容的排版對齊方向設置,支持顯示紅點,支持插入自定義的 View,支持監聽雙擊事件等。
- 可以通過 setupWithViewPager(ViewPager) 方法與 ViewPager 綁定。
TextView相關
QMUILinkTextView
使 TextView 能自動識別 URL、電話、郵箱地址,相比 TextView 有以下特點:
- 可以設置鏈接的樣式。
- 可以設置鏈接的點擊事件。
QMUIFontFitTextView
使 TextView 在寬度固定的情況下,文字多到一行放不下時能縮小文字大小來自適應。
QMUISpanTouchFixTextView
相比 TextView,修正了兩個常見問題:
- 修正了 TextView 與 ClickableSpan 一起使用時,點擊 ClickableSpan 也會觸發 TextView 的事件的問題。
- 修正了 TextView 默認情況下如果添加了 ClickableSpan 之后就無法把點擊事件傳遞給 TextView 的 Parent 的問題。
QMUIVerticalTextView
在 TextView 的基礎上支持文字豎排。
Span相關
QMUITouchableSpan
繼承自 ClickableSpan,支持 normal 態和 press 態時有不同的背景顏色以及字體顏色。建議配合 QMUISpanTouchFixTextView 或其子類使用,便於事件傳遞的協調。
QMUIBlockSpaceSpan
通過在段落之間設置該 span,實現段間距的效果。
QMUICustomTypefaceSpan
支持以 Typeface 的方式設置 span 的字體,實現自定義字體的效果。
QMUIAlignMiddleImageSpan
繼承自 ImageSpan,在此基礎上實現讓 span 垂直居中的效果。
QMUIMarginImageSpan
繼承自 QMUIMarginImageSpan,在此基礎上支持設置圖片的左右間距。
QMUITextSizeSpan
支持調整字體大小的 span。AbsoluteSizeSpan 可以調整字體大小,但在中英文混排下由於decent的不同,無法根據具體需求進行底部對齊或者頂部對齊。而 QMUITextSizeSpan 則可以多傳一個參數,讓你可以根據具體情況來決定偏移值。
其他
QMUIKeyboardHelper
提供更加便捷的方式針對給定的 EditText 顯示/隱藏軟鍵盤,並且提供了工具方法判斷鍵盤是否當前可見。
QMUIFloatLayout
類似 CSS 里 float: left 的浮動布局,從左到右排列子 View 並自動換行。支持以下特性:
- 控制子 View 之間的垂直/水平間距。
- 控制子 View 的水平對齊方向(左對齊/居中/右對齊)。
- 限制子 View 的個數或行數。
QMUIRadiusImageView
提供為圖片添加圓角、邊框、剪裁到圓形或其他形狀等功能。
QMUIRoundButton
對 Button 提供圓角功能,支持以下特性:
- 指定圓角的大小。
- 分別指定不同方向的圓角大小。
- 指定圓角的大小為高度的一半,並跟隨高度變化自適應圓角大小。
- 支持分別指定背景色和邊框色,指定顏色時支持使用 color 或 ColorStateList。
QMUIRoundButtonDrawable
使用該 Drawable 可以方便地生成圓角矩形/圓形 Drawable,提供設置背景色、描邊大小和顏色、圓角自適應 View 高度等特性。
QMUIQQFaceView
支持顯示表情的偽 TextView(繼續自定義 View,而不是真正的 TextView),實現了 TextView 的 maxLine、ellipsize、textSize、textColor 等基本功能。支持與 QMUITouchableSpan 配合使用實現內容可點擊。
QMUIQQFaceCompiler
:QMUIQQFaceView 的內容解析器,將文本內容解析成 QMUIQQFaceView 想要的數據格式。IQMUIQQFaceManager
:QMUIQQFaceView 資源管理接口,使用 QMUIQQFaceView 必須實現這個接口以提供表情資源。
工具類
QMUIColorHelper
顏色處理工具類,按照功能類型來划分,總共包含以下幾個特性:
- 為一個顏色設置透明度。
- 根據指定比例,在兩個顏色值之間計算出一個顏色值。
- 將顏色值轉換為字符串。
QMUIDeviceHelper
獲取設備信息的工具類,按照功能類型來划分,總共包含以下幾個特性:
- 判斷設備為手機/平板。
- 判斷設備是否為魅族手機。
- 判斷當前系統是否為 Flyme 系統。
- 判斷當前系統是否為 MIUI 系統。
- 判斷當前是否擁有懸浮窗權限。
QMUIDisplayHelper
屏幕相關的工具類,按照功能類型來划分,總共包含以下幾個特性:
- 方便地獲取一個 DisplayMetrics 實例。
- 獲取屏幕信息,包括屏幕密度、屏幕寬度和高度、狀態欄高度、ActionBar 高度等。
- 獲取設備硬件信息,包括是否有可用攝像頭、是否有硬件菜單、是否有網絡、SD Card 是否可用、當前選擇的國家語言等。
- 判斷當前是否處於全屏狀態,控制進入/退出全屏狀態。
- dp 與 px 數值的相互轉化。
QMUIDrawableHelper
- 快速繪制一張指定大小、顏色、邊框的圖片,支持形狀為圓角矩形和圓形。
- 快速繪制一張帶上分隔線或下分隔線的圖片。
- 快速繪制一張可帶圓角的漸變圖片。
- 將當前圖片的顏色換成另一個顏色。
- 將兩張圖片疊加后生成一張新的圖片。
- 對某個 View 截圖生成圖片。
QMUIPackageHelper
提供簡便的方式獲取 App 的版本信息,可以單獨獲取主版本號、次版本號以及修正版本號。
QMUIResHelper
封裝了更加便捷的方法,用於獲取當前 Theme 下的 Attr 值,支持 Float、Color、ColorStateList、Drawable 和 Dimen 類型的 Attr。
QMUISpanHelper
提供了方法使得 QMUIMarginImageSpan 能被更便捷地使用。
QMUIStatusBarHelper
狀態欄相關的工具類,按照功能類型來划分,總共包含以下幾個特性:
- 快速實現沉浸式狀態欄(支持 4.4 以上版本的 MIUI 和 Flyme,以及 5.0 以上版本的其他 Android)。
- 快速設置狀態欄為黑色或白色字體圖標(支持 4.4 以上版本 MIUI 和 Flyme,以及 6.0 以上版本的其他 Android)。
- 提供多個常用的工具方法,如獲取狀態欄高度、判斷當前是否全屏等等。
QMUIViewHelper
View 工具類,按照功能類型來划分,總共包含以下幾個特性:
- 對 ImageView 進行處理,可以按比例縮放圖片。
- 對 View 做背景顏色變化動畫,支持多個動畫參數。
- 對 View 做進退場動畫,支持透明度變化和上下位移兩種方式。
- 提供多個常用的 View 相關工具方法,如對 View 設置單個方向的 padding、從 ViewStub 中獲取一個 View、判斷 ListView 是否已經滾動到底部等等。
演示案例
QMUIDialog
public class QMUIDialogActivity extends ListActivity {
private Context mcContext;
private int mCurrentDialogStyle = R.style.QMUI_Dialog;
private boolean b;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
QMUIStatusBarHelper.setStatusBarLightMode(this);
mcContext = this;
String[] array = new String[]{
"消息類型對話框(藍色按鈕)",
"消息類型對話框(紅色按鈕)",
"消息類型對話框 (很長文案)",
"菜單類型對話框",
"帶 Checkbox 的消息確認框",
"單選菜單類型對話框",
"多選菜單類型對話框",
"多選菜單類型對話框(item 數量很多)",
"帶輸入框的對話框",
"高度適應鍵盤升降的對話框"
};
setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new ArrayList<>(Arrays.asList(array))));
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
mCurrentDialogStyle = b ? com.qmuiteam.qmui.R.style.QMUI_Dialog : R.style.DialogTheme2;
b = !b;
switch (position) {
case 0:
showMessagePositiveDialog();
break;
case 1:
showMessageNegativeDialog();
break;
case 2:
showLongMessageDialog();
break;
case 3:
showMenuDialog();
break;
case 4:
showConfirmMessageDialog();
break;
case 5:
showSingleChoiceDialog();
break;
case 6:
showMultiChoiceDialog();
break;
case 7:
showNumerousMultiChoiceDialog();
break;
case 8:
showEditTextDialog();
break;
case 9:
showAutoDialog();
break;
}
}
private void showMessagePositiveDialog() {
new QMUIDialog.MessageDialogBuilder(mcContext)
.setTitle("標題")
.setMessage("確定要發送嗎?")
.addAction("取消", (dialog, index) -> dialog.dismiss())
.addAction("確定", (dialog, index) -> {
dialog.dismiss();
Toast.makeText(mcContext, "發送成功", Toast.LENGTH_SHORT).show();
})
.create(mCurrentDialogStyle).show();
}
private void showMessageNegativeDialog() {
new QMUIDialog.MessageDialogBuilder(mcContext)
.setTitle("標題")
.setMessage("確定要刪除嗎?")
.addAction("取消", (dialog, index) -> dialog.dismiss())
.addAction(0, "刪除", QMUIDialogAction.ACTION_PROP_NEGATIVE, (dialog, index) -> {
Toast.makeText(mcContext, "刪除成功", Toast.LENGTH_SHORT).show();
dialog.dismiss();
})
.create(mCurrentDialogStyle).show();
}
private void showLongMessageDialog() {
new QMUIDialog.MessageDialogBuilder(mcContext)
.setTitle("標題")
.setMessage("這是一段很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長" +
"很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很" +
"很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很" +
"很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很" +
"長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長" +
"很長很長很長很長很很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長" +
"很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長" +
"很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長" +
"很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長" +
"很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長很長" +
"很長很長很長很長很長很長很長很長很長很長很長很長很長很長長很長的文案")
.addAction("取消", (dialog, index) -> dialog.dismiss())
.create(mCurrentDialogStyle).show();
}
private void showConfirmMessageDialog() {
new QMUIDialog.CheckBoxMessageDialogBuilder(mcContext)
.setTitle("退出后是否刪除賬號信息?")
.setMessage("刪除賬號信息")
.setChecked(true)
.addAction("取消", (dialog, index) -> dialog.dismiss())
.addAction("退出", (dialog, index) -> dialog.dismiss())
.create(mCurrentDialogStyle).show();
}
private void showMenuDialog() {
final String[] items = new String[]{"選項1", "選項2", "選項3"};
new QMUIDialog.MenuDialogBuilder(mcContext)
.addItems(items, (dialog, which) -> {
Toast.makeText(mcContext, "你選擇了 " + items[which], Toast.LENGTH_SHORT).show();
dialog.dismiss();
})
.create(mCurrentDialogStyle).show();
}
private void showSingleChoiceDialog() {
final String[] items = new String[]{"選項1", "選項2", "選項3"};
final int checkedIndex = 1;
new QMUIDialog.CheckableDialogBuilder(mcContext)
.setCheckedIndex(checkedIndex)
.addItems(items, (dialog, which) -> {
Toast.makeText(mcContext, "你選擇了 " + items[which], Toast.LENGTH_SHORT).show();
dialog.dismiss();
})
.create(mCurrentDialogStyle).show();
}
private void showMultiChoiceDialog() {
final String[] items = new String[]{"選項1", "選項2", "選項3", "選項4", "選項5", "選項6"};
final QMUIDialog.MultiCheckableDialogBuilder builder = new QMUIDialog.MultiCheckableDialogBuilder(mcContext)
.setCheckedItems(new int[]{1, 3})
.addItems(items, (dialog, which) -> {
});
builder.addAction("取消", (dialog, index) -> dialog.dismiss());
builder.addAction("提交", (dialog, index) -> {
StringBuilder result = new StringBuilder("你選擇了 ");
for (int i = 0; i < builder.getCheckedItemIndexes().length; i++) {
result.append("").append(builder.getCheckedItemIndexes()[i]).append("; ");
}
Toast.makeText(mcContext, result.toString(), Toast.LENGTH_SHORT).show();
dialog.dismiss();
});
builder.create(mCurrentDialogStyle).show();
}
private void showNumerousMultiChoiceDialog() {
final String[] items = new String[]{
"選項1", "選項2", "選項3", "選項4", "選項5", "選項6",
"選項7", "選項8", "選項9", "選項10", "選項11", "選項12",
"選項13", "選項14", "選項15", "選項16", "選項17", "選項18"
};
final QMUIDialog.MultiCheckableDialogBuilder builder = new QMUIDialog.MultiCheckableDialogBuilder(mcContext)
.setCheckedItems(new int[]{1, 3})
.addItems(items, (dialog, which) -> {
});
builder.addAction("取消", (dialog, index) -> dialog.dismiss());
builder.addAction("提交", (dialog, index) -> {
StringBuilder result = new StringBuilder("你選擇了 ");
for (int i = 0; i < builder.getCheckedItemIndexes().length; i++) {
result.append("").append(builder.getCheckedItemIndexes()[i]).append("; ");
}
Toast.makeText(mcContext, result.toString(), Toast.LENGTH_SHORT).show();
dialog.dismiss();
});
builder.create(mCurrentDialogStyle).show();
}
private void showEditTextDialog() {
final QMUIDialog.EditTextDialogBuilder builder = new QMUIDialog.EditTextDialogBuilder(mcContext);
builder.setTitle("標題")
.setPlaceholder("在此輸入您的昵稱")
.setInputType(InputType.TYPE_CLASS_TEXT)
.addAction("取消", (dialog, index) -> dialog.dismiss())
.addAction("確定", (dialog, index) -> {
CharSequence text = builder.getEditText().getText();
if (text != null && text.length() > 0) {
Toast.makeText(mcContext, "您的昵稱: " + text, Toast.LENGTH_SHORT).show();
dialog.dismiss();
} else {
Toast.makeText(mcContext, "請填入昵稱", Toast.LENGTH_SHORT).show();
}
})
.create(mCurrentDialogStyle).show();
}
private void showAutoDialog() {
QMAutoTestDialogBuilder autoTestDialogBuilder = (QMAutoTestDialogBuilder) new QMAutoTestDialogBuilder(mcContext)
.addAction("取消", (dialog, index) -> dialog.dismiss())
.addAction("確定", (dialog, index) -> {
Toast.makeText(mcContext, "你點了確定", Toast.LENGTH_SHORT).show();
dialog.dismiss();
});
autoTestDialogBuilder.create(mCurrentDialogStyle).show();
QMUIKeyboardHelper.showKeyboard(autoTestDialogBuilder.getEditText(), true);
}
class QMAutoTestDialogBuilder extends QMUIDialog.AutoResizeDialogBuilder {
private Context mContext;
private EditText mEditText;
public QMAutoTestDialogBuilder(Context context) {
super(context);
mContext = context;
}
public EditText getEditText() {
return mEditText;
}
@Override
public View onBuildContent(QMUIDialog dialog, ScrollView parent) {
LinearLayout layout = new LinearLayout(mContext);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setLayoutParams(new ScrollView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
int padding = QMUIDisplayHelper.dp2px(mContext, 20);
layout.setPadding(padding, padding, padding, padding);
mEditText = new EditText(mContext);
QMUIViewHelper.setBackgroundKeepingPadding(mEditText, QMUIResHelper.getAttrDrawable(mContext, R.attr.qmui_list_item_bg_with_border_bottom));
mEditText.setHint("輸入框");
LinearLayout.LayoutParams editTextLP = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, QMUIDisplayHelper.dpToPx(50));
editTextLP.bottomMargin = QMUIDisplayHelper.dp2px(mcContext, 15);
mEditText.setLayoutParams(editTextLP);
layout.addView(mEditText);
TextView textView = new TextView(mContext);
textView.setLineSpacing(QMUIDisplayHelper.dp2px(mcContext, 4), 1.0f);
textView.setText("觀察聚焦輸入框后,鍵盤升起降下時 dialog 的高度自適應變化。\n\n" +
"QMUI Android 的設計目的是用於輔助快速搭建一個具備基本設計還原效果的 Android 項目," +
"同時利用自身提供的豐富控件及兼容處理,讓開發者能專注於業務需求而無需耗費精力在基礎代碼的設計上。" +
"不管是新項目的創建,或是已有項目的維護,均可使開發效率和項目質量得到大幅度提升。");
textView.setTextColor(ContextCompat.getColor(mcContext, R.color.app_color_description));
textView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
layout.addView(textView);
return layout;
}
}
}
QMUIBottomSheet 和 QMUITipDialog 和 QMUIPopup
public class BottomSheet_TipDialog_PopupActivity extends ListActivity {
private Context mContext;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
String[] array = {"BottomSheet List",
"BottomSheet Grid",
"Loading 類型提示框",
"成功提示類型提示框",
"失敗提示類型提示框",
"信息提示類型提示框",
"單獨圖片類型提示框",
"單獨文字類型提示框",
"自定義內容提示框",};
setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new ArrayList<>(Arrays.asList(array))));
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
switch (position) {
case 0:
showSimpleBottomSheetList();
break;
case 1:
showSimpleBottomSheetGrid();
break;
default:
dealTipDialog(v, position - 2);
break;
}
}
private void dealTipDialog(View v, int position) {
if (position % 2 == 0) {
showListPopup(v, new Random().nextInt(3));
} else {
showNormalPopup(v, new Random().nextInt(3));
}
final QMUITipDialog tipDialog;
switch (position) {
case 0:
tipDialog = new QMUITipDialog.Builder(mContext)
.setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING)
.setTipWord("正在加載")
.create();
break;
case 1:
tipDialog = new QMUITipDialog.Builder(mContext)
.setIconType(QMUITipDialog.Builder.ICON_TYPE_SUCCESS)
.setTipWord("發送成功")
.create();
break;
case 2:
tipDialog = new QMUITipDialog.Builder(mContext)
.setIconType(QMUITipDialog.Builder.ICON_TYPE_FAIL)
.setTipWord("發送失敗")
.create();
break;
case 3:
tipDialog = new QMUITipDialog.Builder(mContext)
.setIconType(QMUITipDialog.Builder.ICON_TYPE_INFO)
.setTipWord("請勿重復操作")
.create();
break;
case 4:
tipDialog = new QMUITipDialog.Builder(mContext)
.setIconType(QMUITipDialog.Builder.ICON_TYPE_SUCCESS)
.create();
break;
case 5:
tipDialog = new QMUITipDialog.Builder(mContext)
.setTipWord("請勿重復操作")
.create();
break;
case 6:
tipDialog = new QMUITipDialog.CustomBuilder(mContext)
.setContent(R.layout.qmui_bottom_sheet_grid)
.create();
break;
default:
tipDialog = new QMUITipDialog.Builder(mContext)
.setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING)
.setTipWord("正在加載")
.create();
}
tipDialog.show();
new Handler().postDelayed(tipDialog::dismiss, 1500);
}
private void showSimpleBottomSheetList() {
new QMUIBottomSheet.BottomListSheetBuilder(mContext)
.addItem("Item 1")
.addItem("Item 2")
.addItem("Item 3")
.setOnSheetItemClickListener((dialog, itemView, position, tag) -> {
dialog.dismiss();
Toast.makeText(mContext, "Item " + (position + 1), Toast.LENGTH_SHORT).show();
})
.build()
.show();
}
private void showSimpleBottomSheetGrid() {
final int TAG_SHARE_WECHAT_FRIEND = 0;
final int TAG_SHARE_WECHAT_MOMENT = 1;
final int TAG_SHARE_WEIBO = 2;
final int TAG_SHARE_CHAT = 3;
final int TAG_SHARE_LOCAL = 4;
new QMUIBottomSheet.BottomGridSheetBuilder(mContext)
.addItem(R.mipmap.ic_launcher, "分享到微信", TAG_SHARE_WECHAT_FRIEND, QMUIBottomSheet.BottomGridSheetBuilder.FIRST_LINE)
.addItem(R.mipmap.ic_launcher, "分享到朋友圈", TAG_SHARE_WECHAT_MOMENT, QMUIBottomSheet.BottomGridSheetBuilder.FIRST_LINE)
.addItem(R.mipmap.ic_launcher, "分享到微博", TAG_SHARE_WEIBO, QMUIBottomSheet.BottomGridSheetBuilder.FIRST_LINE)
.addItem(R.mipmap.ic_launcher, "分享到私信", TAG_SHARE_CHAT, QMUIBottomSheet.BottomGridSheetBuilder.FIRST_LINE)
.addItem(R.mipmap.ic_launcher, "保存到本地", TAG_SHARE_LOCAL, QMUIBottomSheet.BottomGridSheetBuilder.SECOND_LINE)
.setOnSheetItemClickListener((dialog, itemView) -> {
dialog.dismiss();
int tag = (int) itemView.getTag();
switch (tag) {
case TAG_SHARE_WECHAT_FRIEND:
Toast.makeText(mContext, "分享到微信", Toast.LENGTH_SHORT).show();
break;
case TAG_SHARE_WECHAT_MOMENT:
Toast.makeText(mContext, "分享到朋友圈", Toast.LENGTH_SHORT).show();
break;
case TAG_SHARE_WEIBO:
Toast.makeText(mContext, "分享到微博", Toast.LENGTH_SHORT).show();
break;
case TAG_SHARE_CHAT:
Toast.makeText(mContext, "分享到私信", Toast.LENGTH_SHORT).show();
break;
case TAG_SHARE_LOCAL:
Toast.makeText(mContext, "保存到本地", Toast.LENGTH_SHORT).show();
break;
}
})
.build().show();
}
private void showNormalPopup(View v, int preferredDirection) {
QMUIPopup mNormalPopup = new QMUIPopup(mContext, QMUIPopup.DIRECTION_NONE);
TextView textView = new TextView(mContext);
textView.setLayoutParams(mNormalPopup.generateLayoutParam(QMUIDisplayHelper.dp2px(mContext, 250),
ViewGroup.LayoutParams.WRAP_CONTENT));
textView.setLineSpacing(QMUIDisplayHelper.dp2px(mContext, 4), 1.0f);
int padding = QMUIDisplayHelper.dp2px(mContext, 20);
textView.setPadding(padding, padding, padding, padding);
textView.setText("Popup 可以設置其位置以及顯示和隱藏的動畫");
textView.setTextColor(ContextCompat.getColor(mContext, R.color.app_color_description));
mNormalPopup.setContentView(textView);
mNormalPopup.setOnDismissListener(() -> Toast.makeText(mContext, "onDismiss", Toast.LENGTH_SHORT).show());
mNormalPopup.setAnimStyle(QMUIPopup.ANIM_GROW_FROM_CENTER);
mNormalPopup.setPreferredDirection(preferredDirection);//QMUIPopup.DIRECTION_TOP、DIRECTION_BOTTOM、DIRECTION_NONE
mNormalPopup.show(v);
}
private void showListPopup(View v, int preferredDirection) {
String[] array = new String[]{
"Item 1",
"Item 2",
"Item 3",
"Item 4",
"Item 5",
};
ArrayAdapter adapter = new ArrayAdapter<>(mContext, android.R.layout.simple_list_item_1, new ArrayList<>(Arrays.asList(array)));
QMUIListPopup mListPopup = new QMUIListPopup(mContext, QMUIPopup.DIRECTION_NONE, adapter);
mListPopup.create(QMUIDisplayHelper.dp2px(mContext, 250), QMUIDisplayHelper.dp2px(mContext, 200),
(adapterView, view, i, l) -> {
Toast.makeText(mContext, "Item " + (i + 1), Toast.LENGTH_SHORT).show();
mListPopup.dismiss();
});
mListPopup.setOnDismissListener(() -> Toast.makeText(mContext, "onDismiss", Toast.LENGTH_SHORT).show());
mListPopup.setAnimStyle(QMUIPopup.ANIM_GROW_FROM_CENTER);
mListPopup.setPreferredDirection(preferredDirection);
mListPopup.show(v);
}
}
QMUITabSegment
public class QMUITabSegmentActivity extends Activity {
private Context context;
private QMUITopBar topBar;
private QMUITabSegment tabSegment;
private ViewPager viewPager;
private Drawable drawable, drawable2;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_tab_viewpager_layout);
context = this;
drawable = ContextCompat.getDrawable(context, R.mipmap.ic_launcher);
drawable2 = ContextCompat.getDrawable(context, R.mipmap.ic_launcher_round);
topBar = findViewById(R.id.topbar);
tabSegment = findViewById(R.id.tabSegment);
viewPager = findViewById(R.id.contentViewPager);
initView();
}
private void initView() {
topBar.addLeftBackImageButton().setOnClickListener(v -> finish());
topBar.setTitle("QMUITabSegment");
topBar.addRightImageButton(R.mipmap.ic_launcher_round, R.id.topbar_right).setOnClickListener(v -> showBottomSheetList());
viewPager.setAdapter(new PagerAdapter() {
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@Override
public int getCount() {
return 2;
}
@NonNull
@Override
public Object instantiateItem(@NonNull final ViewGroup container, int position) {
TextView textView = new TextView(context);
textView.setGravity(Gravity.CENTER);
textView.setBackgroundColor(position == 0 ? Color.YELLOW : Color.CYAN);
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 30);
textView.setText(position == 0 ? "白乾濤" : "包青天 " + position);
container.addView(textView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
return textView;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView((View) object);
}
});
viewPager.setCurrentItem(0, false);
tabSegment.addTab(new QMUITabSegment.Tab("白乾濤"));
tabSegment.addTab(new QMUITabSegment.Tab("包青天"));
tabSegment.setupWithViewPager(viewPager, false);
tabSegment.setMode(QMUITabSegment.MODE_FIXED);
/*tabSegment.setMode(QMUITabSegment.MODE_SCROLLABLE);
tabSegment.setItemSpaceInScrollMode(QMUIDisplayHelper.dp2px(this, 16));*/
tabSegment.addOnTabSelectedListener(new QMUITabSegment.OnTabSelectedListener() {
@Override
public void onTabSelected(int index) {//當某個 Tab 被選中時會觸發
Log.i("bqt", "【onTabSelected】" + index);
tabSegment.hideSignCountView(index);//根據 index 在對應的 Tab 上隱藏紅點
}
@Override
public void onTabReselected(int index) {//當某個 Tab 處於被選中狀態下再次被點擊時會觸發
Log.i("bqt", "【onTabReselected】" + index);
tabSegment.hideSignCountView(index);//根據 index 在對應的 Tab 上隱藏紅點
}
@Override
public void onTabUnselected(int index) {//當某個 Tab 被取消選中時會觸發
Log.i("bqt", "【onTabUnselected】" + index);
}
@Override
public void onDoubleTap(int index) {//當某個 Tab 被雙擊時會觸發
Log.i("bqt", "【onDoubleTap】" + index);
}
});
}
private void showBottomSheetList() {
new QMUIBottomSheet.BottomListSheetBuilder(this)
.addItem("簡單文字")
.addItem("文字 + 底部")
.addItem("文字 + 頂部 indicator")
.addItem("文字 + indicator 長度不要跟隨內容長度")
.addItem("文字 + icon(支持四個方向) + 自動着色選中態 icon")
.addItem("顯示紅點")
.addItem("選中態更換 icon")
.addItem("不同 item,不同文字(icon)顏色")
.addItem("根據 index 更新 tab 文案")
.addItem("根據 index 完全替換 tab")
.setOnSheetItemClickListener((dialog, itemView, position, tag) -> {
dialog.dismiss();
switch (position) {
case 0:
tabSegment.reset();//1、清空已經存在的 Tab。
tabSegment.setHasIndicator(false);//設置是否需要顯示 indicator
tabSegment.addTab(new QMUITabSegment.Tab("白乾濤"));// 2、重新 addTab添加新的 Tab
tabSegment.addTab(new QMUITabSegment.Tab("包青天"));
tabSegment.notifyDataChanged();//3、通過 notifyDataChanged() 通知變動
break;
case 1:
tabSegment.reset();
tabSegment.setHasIndicator(true);
tabSegment.setIndicatorPosition(false);//true 時表示 indicator 位置在 Tab 的上方, false 時表示在下方
tabSegment.setIndicatorWidthAdjustContent(true);//設置 indicator的寬度是否隨內容寬度變化
tabSegment.addTab(new QMUITabSegment.Tab("白乾濤"));
tabSegment.addTab(new QMUITabSegment.Tab("包青天"));
tabSegment.notifyDataChanged();
break;
case 2:
tabSegment.reset();
tabSegment.setHasIndicator(true);
tabSegment.setIndicatorPosition(true);
tabSegment.setIndicatorWidthAdjustContent(true);
tabSegment.addTab(new QMUITabSegment.Tab("白乾濤"));
tabSegment.addTab(new QMUITabSegment.Tab("包青天"));
tabSegment.notifyDataChanged();
break;
case 3:
tabSegment.reset();
tabSegment.setHasIndicator(true);
tabSegment.setIndicatorPosition(false);
tabSegment.setIndicatorWidthAdjustContent(false);
tabSegment.addTab(new QMUITabSegment.Tab("白乾濤"));
tabSegment.addTab(new QMUITabSegment.Tab("包青天"));
tabSegment.notifyDataChanged();
break;
case 4:
tabSegment.reset();
tabSegment.setHasIndicator(false);
tabSegment.addTab(new QMUITabSegment.Tab(drawable, null, "白乾濤", true));
tabSegment.addTab(new QMUITabSegment.Tab(drawable2, null, "包青天", true));
tabSegment.notifyDataChanged();
break;
case 5:
QMUITabSegment.Tab tab = tabSegment.getTab(0);
tab.setSignCountMargin(0, -QMUIDisplayHelper.dp2px(context, 4));
tab.showSignCountView(context, 10086);//顯示 Tab 上的未讀數或紅點
tabSegment.notifyDataChanged();
break;
case 6:
tabSegment.reset();
tabSegment.setHasIndicator(false);
tabSegment.addTab(new QMUITabSegment.Tab(drawable, drawable2, "白乾濤", false));
tabSegment.addTab(new QMUITabSegment.Tab(drawable, drawable2, "包青天", false));
tabSegment.notifyDataChanged();
break;
case 7:
tabSegment.reset();
tabSegment.setHasIndicator(true);
tabSegment.setIndicatorWidthAdjustContent(true);
tabSegment.setIndicatorPosition(false);
QMUITabSegment.Tab tab1 = new QMUITabSegment.Tab(drawable, null, "白乾濤", true);
tab1.setTextColor(Color.GREEN, Color.RED);
QMUITabSegment.Tab tab2 = new QMUITabSegment.Tab(drawable2, null, "包青天", true);
tab2.setTextColor(Color.GREEN, Color.RED);
tabSegment.addTab(tab1);
tabSegment.addTab(tab2);
tabSegment.notifyDataChanged();
break;
case 8:
tabSegment.updateTabText(0, "動態更新文案");//改變 Tab 的文案
tabSegment.notifyDataChanged();
break;
case 9:
QMUITabSegment.Tab replaceTab = new QMUITabSegment.Tab(drawable, null, "動態更新", true);
tabSegment.replaceTab(0, replaceTab);//整個 Tab 替換
tabSegment.notifyDataChanged();
break;
default:
break;
}
})
.build()
.show();
}
}
2018-4-21