Settings

    xiaoxiao2026-03-17  25

    app中每一个setting都是preference的子类.用的最多的子类是checkBoxPreference/ListPreference/EditTextPreference。当这些子类不能满足我们的需求时,我们可以实现preference的子类。 可以在runtime是实现preference的子类,也可以在XML 中定义preference 。这些在XML中定义的preference也可以在runtime是修改. checkBoxPreference/ListPreference/EditTextPreference 也可以用在XML中,对应xml中的标签,如: <CheckBoxPreference>。xml必须被放在res/xml中. 举例如下,一般res/xml中只能有一个xml文件. <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">     <CheckBoxPreference         android:key="pref_sync"         android:title="@string/pref_sync"         android:summary="@string/pref_sync_summ"         android:defaultValue="true" />     <ListPreference         android:dependency="pref_sync"         android:key="pref_syncConnectionType"         android:title="@string/pref_syncConnectionType"         android:dialogTitle="@string/pref_syncConnectionType"         android:entries="@array/pref_syncConnectionTypes_entries"         android:entryValues="@array/pref_syncConnectionTypes_values"         android:defaultValue="@string/pref_syncConnectionTypes_default" /> </PreferenceScreen> 需要注意的是可用 android:defaultValue 来设置默认值. 在这个例子中我们用到<ListPreference><CheckBoxPreference>标签. 如果setting 很多的话,可以考虑用group来分组 一个group中的setting可以用title 或者 subscreen来呈现. 如果要用title 来显示的话,将每个preference放到preferenceCategory中,如下所示: <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">     <PreferenceCategory         android:title="@string/pref_sms_storage_title"         android:key="pref_key_storage_settings">         <CheckBoxPreference             android:key="pref_key_auto_delete"             android:summary="@string/pref_summary_auto_delete"             android:title="@string/pref_title_auto_delete"             android:defaultValue="false"... />         <Preference             android:key="pref_key_sms_delete_limit"             android:dependency="pref_key_auto_delete"             android:summary="@string/pref_summary_delete_limit"             android:title="@string/pref_title_sms_delete"... />         <Preference             android:key="pref_key_mms_delete_limit"             android:dependency="pref_key_auto_delete"             android:summary="@string/pref_summary_delete_limit"             android:title="@string/pref_title_mms_delete" ... />     </PreferenceCategory>     ... </PreferenceScreen> 如果要用subscreen来显示的话. 将每个preference放到preferenceScreen中,如下所示 <PreferenceScreen  xmlns:android="http://schemas.android.com/apk/res/android">     <!-- opens a subscreen of settings -->     <PreferenceScreen         android:key="button_voicemail_category_key"         android:title="@string/voicemail"         android:persistent="false">         <ListPreference             android:key="button_voicemail_provider_key"             android:title="@string/voicemail_provider" ... />         <!-- opens another nested subscreen -->         <PreferenceScreen             android:key="button_voicemail_setting_key"             android:title="@string/voicemail_settings"             android:persistent="false">             ...         </PreferenceScreen>         <RingtonePreference             android:key="button_voicemail_ringtone_key"             android:title="@string/voicemail_ringtone_title"             android:ringtoneType="notification" ... />         ...     </PreferenceScreen>     ... </PreferenceScreen> 有时候想点击preference item的时候打开一个Activity而不是setting的界面。这时候可以用Intent来完成,例如打开浏览器看一个网页. 下面这个例子就会打开http://www.example.com <Preference android:title="@string/prefs_web_page" >     <intent android:action="android.intent.action.VIEW"             android:data="http://www.example.com" /> </Preference> 如果想用Activity 来呈现setting,需要实现preferenceFragment的子类 public static class SettingsFragment extends PreferenceFragment {     @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         // Load the preferences from an XML resource         addPreferencesFromResource(R.xml.preferences);     }     ... } 可以通过设定默认值PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false); 然后通过fragmentManager添加到你的Activity中. public class SettingsActivity extends Activity {     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         // Display the fragment as the main content.         getFragmentManager().beginTransaction()                 .replace(android.R.id.content, new SettingsFragment())                 .commit();     } } 需要注意的是fragmentManager,没有context这个参数,如果你需要context这个参数,可以用getActivity()得到,注意getActivity()可以会得到NULL. 在某些情况下,当用户点击setting中的每一项是都会用subscreen来显示。可以参考下面的步奏 1:首先在xml中定义每一个PreferenceFragment。这些PreferenceFragment放置在header标签下. <?xml version="1.0" encoding="utf-8"?> <preference-headers xmlns:android="http://schemas.android.com/apk/res/android">     <header         android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"         android:title="@string/prefs_category_one"         android:summary="@string/prefs_summ_category_one" />     <header         android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"         android:title="@string/prefs_category_two"         android:summary="@string/prefs_summ_category_two" >         <!-- key/value pairs can be included as arguments for the fragment. -->         <extra android:name="someKey" android:value="someHeaderValue" />     </header> </preference-headers> 然后在PreferenceFragment  子类的onCreate函数中根据settings中的不同选项加载不同的xml文件. public static class SettingsFragment extends PreferenceFragment {     @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         String settings = getArguments().getString("settings");         if ("notifications".equals(settings)) {             addPreferencesFromResource(R.xml.settings_wifi);         } else if ("sync".equals(settings)) {             addPreferencesFromResource(R.xml.settings_sync);         }     } } 在Activity中显示header public class SettingsActivity extends PreferenceActivity {     @Override     public void onBuildHeaders(List<Header> target) {         loadHeadersFromResource(R.xml.preference_headers, target);     } } Reading Preferences 在你的application内部,可以通过调用静态方法来得到key—value的设定如下所示: SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, ""); Listening for preference changes 如果用户改变setting,我们可以通过实现OnSharePreferenceChangeListner来得到通知,如下所示: public class SettingsActivity extends PreferenceActivity                               implements OnSharedPreferenceChangeListener {     public static final String KEY_PREF_SYNC_CONN = "pref_syncConnectionType";     ...     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,         String key) {         if (key.equals(KEY_PREF_SYNC_CONN)) {             Preference connectionPref = findPreference(key);             // Set summary to be the user-description for the selected value             connectionPref.setSummary(sharedPreferences.getString(key, ""));         }     } } Building a Custom Preference 系统提供的preference子类不能满足你的需求的话,可以自己实现preference的子类. 1.当用户选择setting,用户可以看到的interface. 一般先实现一个DialogPreference 的子类,提供一个对话框给用户. public class NumberPickerPreference extends DialogPreference {     public NumberPickerPreference(Context context, AttributeSet attrs) {         super(context, attrs);         setDialogLayoutResource(R.layout.numberpicker_dialog);         setPositiveButtonText(android.R.string.ok);         setNegativeButtonText(android.R.string.cancel);         setDialogIcon(null);     }     ... } 2.保存设定的值 可以调用 Preference 类的 persist*() 方法,如persistInt保存整数 @Override protected void onDialogClosed(boolean positiveResult) {     // When the user selects "OK", persist the new value     if (positiveResult) {         persistInt(mNewValue);     } } 3.初始化当前值。 当系统间你的preference添加到screen是,系统会call onSetInitialValue()来件事使用有一个persited value,如果没有的话,就设定一个默认值 @Override protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {     if (restorePersistedValue) {         // Restore existing state         mCurrentValue = this.getPersistedInt(DEFAULT_VALUE);     } else {         // Set default state from the XML attribute         mCurrentValue = (Integer) defaultValue;         persistInt(mCurrentValue);     } } 如果你通过android:defaultValue 设定了默认值,系统来call onGetDefaultValue()来取这个默认值. @Override protected Object onGetDefaultValue(TypedArray a, int index) {     return a.getInteger(index, DEFAULT_VALUE); } 可以Activity的OnSaveInstanceState()和OnRestoreInstanceState()中保存和取回setting值。 一般会用BaseSavedState 的子类来保存,如下code所示: private static class SavedState extends BaseSavedState {     // Member that holds the setting's value     // Change this data type to match the type saved by your Preference     int value;     public SavedState(Parcelable superState) {         super(superState);     }     public SavedState(Parcel source) {         super(source);         // Get the current preference's value         value = source.readInt();  // Change this to read the appropriate data type     }     @Override     public void writeToParcel(Parcel dest, int flags) {         super.writeToParcel(dest, flags);         // Write the preference's value         dest.writeInt(value);  // Change this to write the appropriate data type     }     // Standard creator object using an instance of this class     public static final Parcelable.Creator<SavedState> CREATOR =             new Parcelable.Creator<SavedState>() {         public SavedState createFromParcel(Parcel in) {             return new SavedState(in);         }         public SavedState[] newArray(int size) {             return new SavedState[size];         }     }; } @Override protected Parcelable onSaveInstanceState() {     final Parcelable superState = super.onSaveInstanceState();     // Check whether this Preference is persistent (continually saved)     if (isPersistent()) {         // No need to save instance state since it's persistent,         // use superclass state         return superState;     }     // Create instance of custom BaseSavedState     final SavedState myState = new SavedState(superState);     // Set the state's value with the class member that holds current     // setting value     myState.value = mNewValue;     return myState; } @Override protected void onRestoreInstanceState(Parcelable state) {     // Check whether we saved the state in onSaveInstanceState     if (state == null || !state.getClass().equals(SavedState.class)) {         // Didn't save the state, so call superclass         super.onRestoreInstanceState(state);         return;     }     // Cast state to custom BaseSavedState and pass to superclass     SavedState myState = (SavedState) state;     super.onRestoreInstanceState(myState.getSuperState());     // Set this Preference's widget to reflect the restored state     mNumberPicker.setValue(myState.value); }
    转载请注明原文地址: https://ju.6miu.com/read-1308064.html
    最新回复(0)