在學習這個之前,首先我們應該搞懂什麼是Preferences以及AlertDialog的詳細使用。懂的了這些之後我們在看看什麼是DialogPreference
,以及和他相關的ListPreference
,MultiSelectListPreference
。
1.ListPreference
顧名思義ListPreference就類似AlertDialog
的setSingleChoiceItems
功能,只是多了一項記憶功能。下面看一下主要代碼
@Override
protected void onPrepareDialogBuilder(Builder builder) {
super.onPrepareDialogBuilder(builder);
if (mEntries == null || mEntryValues == null) {
throw new IllegalStateException(
"ListPreference requires an entries array and an entryValues array.");
}
mClickedDialogEntryIndex = getValueIndex();
builder.setSingleChoiceItems(mEntries, mClickedDialogEntryIndex,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mClickedDialogEntryIndex = which;
/*
* Clicking on an item simulates the positive button
* click, and dismisses the dialog.
*/
ListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
dialog.dismiss();
}
});
/*
* The typical interaction for list-based dialogs is to have
* click-on-an-item dismiss the dialog instead of the user having to
* press 'Ok'.
*/
builder.setPositiveButton(null, null);
}
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult && mClickedDialogEntryIndex >= 0 && mEntryValues != null) {
String value = mEntryValues[mClickedDialogEntryIndex].toString();
if (callChangeListener(value)) {
//這裏會記錄用戶的點擊項,存儲在默認的SharedPreferences中
setValue(value);
}
}
}
2.MultiSelectListPreference
顧名思義MultiSelectListPreference就類似AlertDialog
的setMultiChoiceItems
功能,只是多了一項記憶功能。下面看一下主要代碼
@Override
protected void onPrepareDialogBuilder(Builder builder) {
super.onPrepareDialogBuilder(builder);
if (mEntries == null || mEntryValues == null) {
throw new IllegalStateException(
"MultiSelectListPreference requires an entries array and " +
"an entryValues array.");
}
boolean[] checkedItems = getSelectedItems();
builder.setMultiChoiceItems(mEntries, checkedItems,
new DialogInterface.OnMultiChoiceClickListener() {
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
if (isChecked) {
mPreferenceChanged |= mNewValues.add(mEntryValues[which].toString());
} else {
mPreferenceChanged |= mNewValues.remove(mEntryValues[which].toString());
}
}
});
mNewValues.clear();
mNewValues.addAll(mValues);
}
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult && mPreferenceChanged) {
final Set<String> values = mNewValues;
if (callChangeListener(values)) {
//這裏會記錄用戶的選擇項,存儲在默認的SharedPreferences中
setValues(values);
}
}
mPreferenceChanged = false;
}
也許我們可能覺得這些功能用起來很簡單,系統幫我們做了存儲,省去了很多工作量。但是請用戶注意這裏有一個大坑,我們繼續跟進代碼:
protected void showDialog(Bundle state) {
Context context = getContext();
mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;
mBuilder = new AlertDialog.Builder(context)
.setTitle(mDialogTitle)
.setIcon(mDialogIcon)
.setPositiveButton(mPositiveButtonText, this)
.setNegativeButton(mNegativeButtonText, this);
View contentView = onCreateDialogView();
if (contentView != null) {
onBindDialogView(contentView);
mBuilder.setView(contentView);
} else {
mBuilder.setMessage(mDialogMessage);
}
//重新該接口我們可以自定義ContentUI和TitleUI
//builder.setAdapter,setCustomTitle
onPrepareDialogBuilder(mBuilder);
getPreferenceManager().registerOnActivityDestroyListener(this);
//請注意這裏,這裏直接Create生成Dialog之後,並沒有給我們操作Dialog的機會
//所以如果此時美工提出需要圓角界面,那麼由於我們無法獲取到Window,
//只能通過AlertDialog自己實現類似功能了,之前覺得好用的的偷懶會因此付出代價
// Create the dialog
final Dialog dialog = mDialog = mBuilder.create();
if (state != null) {
dialog.onRestoreInstanceState(state);
}
if (needInputMethod()) {
requestInputMethod(dialog);
}
dialog.setOnDismissListener(this);
dialog.show();
}
從這裏可以看出,showDialog只提供了重載onPrepareDialogBuilder
修改 AlertDialog.Builder
的機會,但是卻沒有提供修改dialog
實例的機會。也就是說我們可以通過重載onPrepareDialogBuilder
,定製Content View和Title View,但是卻沒辦法獲取到Window,也就是說我們無法操作Window,導致無法實現圓角窗口。雖然這些控件看似提高了我們的工作效率,但是有些UI(圓角窗口)沒辦法實現。此時需要我們推翻之前的工作量,通過AlertDialog自定義UI實現上面控件類似功能,浪費很多時間(實際項目已採坑)。
坑坑坑:無法實現圓角窗口