以前使用android.preference包里面的類(lèi)創(chuàng)建出來(lái)的偏好設(shè)置界面是沒(méi)有兼容低版本的,后來(lái)發(fā)現(xiàn)com.android.support:preference庫(kù)有對(duì)低版本做兼容悲关,在低版本上面也可以有Material Design風(fēng)格袒哥,于是對(duì)其作了一番研究秕脓。
1、應(yīng)用的主題需要繼承自Theme.AppCompat系列:
<style name="AppBaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
</style>
2、在build.gradle中添加以下依賴(lài):
compile 'com.android.support:preference-v7:26.1.0'
compile 'com.android.support:preference-v14:26.1.0'
3、在應(yīng)用的主題里面添加:
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
4侦另、編寫(xiě)my_pref.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="preference_screen_settings"
android:title="settings">
<android.support.v7.preference.PreferenceCategory android:title="Category">
<android.support.v7.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="key_1"
android:summary="Summary"
android:title="Title" />
<android.support.v7.preference.EditTextPreference
android:defaultValue="default_value"
android:dialogMessage="dialog_message"
android:key="key_2"
android:summary="Summary"
android:title="Title" />
<android.support.v7.preference.CheckBoxPreference
android:defaultValue="true"
android:key="key_3"
android:summary="Summary"
android:title="Title" />
<android.support.v7.preference.ListPreference
android:defaultValue="2"
android:entries="@array/list_preference_entries"
android:entryValues="@array/list_preference_entry_values"
android:key="key_4"
android:summary="Summary"
android:title="Title" />
<android.support.v7.preference.SeekBarPreference
android:defaultValue="20"
android:key="key_5"
android:max="1000"
android:min="0"
android:summary="Summary"
android:title="Title" />
</android.support.v7.preference.PreferenceCategory>
</android.support.v7.preference.PreferenceScreen>
5、編寫(xiě)承載偏好設(shè)置的Fragment尉共,這里繼承自PreferenceFragmentCompat類(lèi):
public class PreferenceFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.my_pref);
}
}
效果圖:
6褒傅、對(duì)Preference節(jié)點(diǎn)進(jìn)行刪除、添加和修改:
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.my_pref);
PreferenceCategory category = (PreferenceCategory) findPreference("category");
category.removePreference(findPreference("key_3"));
ListPreference listPreference = new ListPreference(getContext());
listPreference.setEntries(new String[]{"A", "B", "C", "D"});
listPreference.setEntryValues(new String[]{"A", "B", "C", "D"});
listPreference.setSummary("Summary");
listPreference.setTitle("Title");
listPreference.setDialogTitle("DialogTitle");
listPreference.setKey("key_6");
listPreference.setDefaultValue("C");
category.addPreference(listPreference);
Preference preference1 = findPreference("key_1");
preference1.setTitle("AAAAA");
}
7袄友、修改某個(gè)Preference的點(diǎn)擊事件:
Preference preference2 = findPreference("key_2");
preference2.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
//TODO
return false;
}
});
8殿托、自定義ListPreference,可以自定義一個(gè)attrs剧蚣,從XML文件中把屬性值傳進(jìn)來(lái)支竹;重寫(xiě)onBindViewHolder方法可以通過(guò)holder拿到對(duì)應(yīng)的itemView,這樣便可以對(duì)itemView里面的內(nèi)容進(jìn)行修改鸠按,這里我的itemView是自定義的唾戚,布局通過(guò)android:layout="@layout/item_view"進(jìn)行設(shè)置:
public class MyListPreference extends ListPreference {
private String titleText;
public MyListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyListPreference);
titleText = typedArray.getString(R.styleable.MyListPreference_title_text);
typedArray.recycle();
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
View view = holder.itemView;
TextView tvTitle= (TextView) view.findViewById(R.id.tv_title_text);
tvTitle.setText(titleText);
}
}
9、對(duì)CheckBoxPreference和SwitchPreference的自定義類(lèi)似待诅,如果只想修改右邊的控件(將Switch修改成自定義的View)可以在對(duì)應(yīng)的Preference中添加android:widgetLayout="@layout/switch_layout",再自定義一個(gè)類(lèi)繼承自SwitchPreferenceCompat:
public class MySwitchPreferenceCompat extends SwitchPreferenceCompat {
private AppCompatImageView imageView;
public MySwitchPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public MySwitchPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MySwitchPreferenceCompat(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MySwitchPreferenceCompat(Context context) {
super(context);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
imageView = holder.itemView.findViewById(R.id.preference_img);
setState(imageView);
}
@Override
protected void onClick() {
super.onClick();
setState(imageView);
}
private void setState(AppCompatImageView appCompatImageView) {
Drawable drawable = getContext().getResources().getDrawable(
getSharedPreferences().getBoolean(getKey(), false) ?
R.drawable.ic_arrow_upward_black_24dp : R.drawable.ic_arrow_downward_black_24dp);
appCompatImageView.setImageDrawable(drawable);
}
}
10熊镣、在自定義EditTextPreference時(shí)總感覺(jué)很奇怪卑雁,不知道為什么默認(rèn)的EditTextPreference彈窗這么不好看(Google自己的規(guī)范上面都說(shuō)Dialog內(nèi)容到左右的邊距為24dp):
默認(rèn)的EditTextPreference
public class MyEditTextPreference extends EditTextPreference {
public MyEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public MyEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MyEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyEditTextPreference(Context context) {
super(context);
}
@Override
protected void onClick() {
View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_rename_layout, null);
final EditText editText = view.findViewById(R.id.rename_dialog_edit);
editText.setHint("");
editText.setText(getSharedPreferences().getString(getKey(), ""));
editText.setSelectAllOnFocus(true);
AlertDialog.Builder dialogBuild = new AlertDialog.Builder(getContext());
AlertDialog renameDialog = dialogBuild.setTitle(R.string.main_rename)
.setView(view)
.setTitle(getTitle())
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String string = editText.getText().toString().trim();
getSharedPreferences().edit().putString(getKey(), string).apply();
dialog.dismiss();
}
}).setNegativeButton(R.string.cancel, null).show();
}
}
11、如果有需求需要在MyEditTextPreference中拿到MainActivity的方法或變量绪囱,則需要在Fragment里面?zhèn)鬟M(jìn)來(lái)测蹲,在這里用getContext拿到的Context是ContextThemeWrapper,MainActivity mainActivity = (MainActivity) getContext();這樣強(qiáng)轉(zhuǎn)是會(huì)報(bào)錯(cuò)的鬼吵。
//Fragment中set進(jìn)來(lái)
MyEditTextPreference editTextPreference = (MyEditTextPreference) findPreference("key_8");
editTextPreference.setActivity(getActivity());
12扣甲、修改Preference的樣式:
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textColorPrimary">#FFFF00FF</item>
<item name="android:textColorSecondary">#FF666666</item>
<item name="textColorAlertDialogListItem">#FF00FFFF</item>
13、自定義EditTextPreference在低版本手機(jī)中碰到過(guò)選中文字背景顏色不是你設(shè)置的顏色的情況:
<item name="android:textColorHighlight">#FF0000FF</item>