I usually project development necessary framework

  1. The strongest network request Net on Android
  2. The strongest list on Android (including StateLayout) BRV
  3. Android’s strongest default page StateLayout
  4. JSON and long text log printing tool LogCat
  5. Supports asynchronous and global customization of the toast tool Tooltip
  6. Develop the debugging window tool DebugKit
  7. One line of code creates the transparent StatusBar StatusBar

Basically every app has a Settings (preferences) interface, and Google actually provides the default Settings interface implementation. introduce

Preference The class has multiple direct or indirect subclasses that can form a Preference interface for different content. Different from the normal interface

Key categories:

  • The Preference of ordinary
    • RingtonePreference ringtone
      • CheckBoxPreference Selects a button
      • SwitchPreference Indicates the switch button
    • PreferenceGroup(Abstract class)
      • PreferenceCategory classification
      • PreferenceScreen Indicates the preference interface
    • DialogPreference (Abstract Class)
      • ListPreference list
      • EditTextPreference input box
      • MultiSelectListPreference multi-select
  • PreferenceActivity Indicates the preference interface
  • PreferenceFragment indicates a PreferenceFragment
  • PreferenceViewHolder

preferences

You can control the display of a preference interface content by creating an XML file in the RES/XML directory, typically named prefer.xml.

PreferenceActivity

On android3.0, you should use PreferenceActivity inheritance (since fragments came after 3.0), but you must use this method if you want to use multi-panel mode

public class MainActivity extends PreferenceActivity {

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main); General layout is not allowedaddPreferencesFromResource(R.xml.preference); }}Copy the code

PreferenceFragment

On Android3.0 or above, it should be in the form of Fragment, which is more flexible and efficient than Activity. Use the same method as normal fragments.

public static class SettingsFragment extends PreferenceFragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); }... }Copy the code

attribute

The following describes the attributes that are common to all Preference tags

  • android:key

    Equivalent to the key value in SharePreference, this property can be left out for preferences that do not need to store data (such as PreferenceCategory and PreferenceScreen)

  • android:title

    Provide a title visible to the user

  • android:defaultValue

    Default value in SharePreference

  • android:summary

    Descriptive text

  • android:icon

    icon

The sample

Demonstrate all tags

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:key="@string/app_name">
    <CheckBoxPreference android:title="CheckBoxPreference"/>
    <SwitchPreference android:title="SwitchPreference"/>
    <PreferenceCategory android:title="PreferenceCategory"/>
    <ListPreference android:title="ListPreference"/>
    <EditTextPreference android:title="EditTextPreference"/>
    <MultiSelectListPreference android:title="MultiSelectListPreference"/>
    <RingtonePreference android:title="RingtonePreference"/>
    <Preference android:title="Preference"/>
</PreferenceScreen>
Copy the code

PreferenceScreen

Represents a preference interface (the preference layout must have this label as the root label)

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    
</PreferenceScreen>
Copy the code

PreferenceCategory

Categories in the preferences screen, whose color defaults to theme ColorAccount

The Preference does not have a partition line. If you want to remove the partition line, you can customize the PreferenceCategory

ListPreference

A list of preferences

The list requires two mandatory options. If not, Crash

  • List key (Title)
  • The list of values
<ListPreference
        android:entries="@array/setting_list"
        android:entryValues="@array/setting_list_values"
        android:title="ListPreference"/>
Copy the code

The list dialog box can also be modified, as long as any subclass of DialogPreference supports these properties.

These properties correspond to the properties of the dialog

  1. icon
  2. layout
  3. Messages (just like traditional dialogs, if messages are set, no list is used)
  4. The title

EditTextPreference

Enter preferences

void onSetInitialValue (boolean restoreValue, 
                Object defaultValue)
Copy the code

SwitchPreference

The switch describes the property, which CheckBoxPreference also supports

    <SwitchPreference
        android:summaryOff="Closed"
        android:summaryOn="Open"
        android:title="SwitchPreference"/>
Copy the code

The listener

Click on the event

getPreferenceScreen().setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
  @Override public boolean onPreferenceClick(Preference preference) {
    return false; }});Copy the code

attribute

android:title / / title

android:summary / / subtitle

android:enabled // Whether it is available

android:selectable // Whether it is selectable. If it is not selectable, there is no splitter line and it is not available

android:icon / / icon

android:key // sharepreference key

android:defaultValue / / the default value

android:order // Sort the order

android:shouldDisableView // If it is not available, whether it is "grey"

android:persistent // Whether to persist (i.e. store to SharePreference)

android:fragment / / no results
Copy the code

The custom

Custom view

void setLayoutResource (int layoutResId)

void setWidgetLayoutResource (int widgetLayoutResId)

void setDialogLayoutResource (int dialogLayoutResId)
Copy the code

I mentioned earlier that you can’t setContent in onCreate otherwise you’re going to get a null pointer, just because you can’t find an id

@Override protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  setContentView(R.layout.activity_setting);
  addPreferencesFromResource(R.xml.demo);
}
Copy the code

layout/activity_setting.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:navigationIcon="@drawable/ic_action_back"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        app:popupTheme="@style/Theme.AppCompat.Light"
        app:theme="@style/Theme.AppCompat" />

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="15dp" >

        <ListView
            android:id="@android:id/list"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
      
    </FrameLayout>

</LinearLayout>
Copy the code

rewrite

This section describes an official rewriting example: Custom DialogPreference

Custom DialogPreference can use the following constructors to declare the layout and specify text for the default affirmative and negative dialog buttons:

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); }... }Copy the code

Or you can rewrite it

    @Override protected View onCreateDialogView(a) {

        View view = View.inflate(getContext(), R.layout.dialog_preference, null);

        return view;
    }
Copy the code

Save the set value

If the value is set to an integer or persistBoolean(), it can be stored at any time by calling one of the persist*() methods of the Preference class, such as persistInt().

** Note: ** Each Preference can hold only one data type, so you must use the persist*() method that is appropriate for the data type used by the custom Preference.

When you choose to keep the Settings may depend on the Preference class you are extending. If you extend DialogPreference, this value can only be retained if the dialog box is closed due to a positive result (the user selects the OK button).

The onDialogClosed() method is called when DialogPreference is closed. The method includes a Boolean parameter that specifies whether the user result is “positive”; If the value is true, the user selected the affirmative button and you should save the new value. Such as:

@Override
protected void onDialogClosed(boolean positiveResult) {
    // Save data when click OK
    if(positiveResult) { persistInt(mNewValue); }}Copy the code

About Default Values

First you need to set a default value

Override onGetDefaultValue to find the default value and return

@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
    return a.getInteger(index, 0);
}
Copy the code

Override onSetInitialValue to determine whether to restore data or initialize the default value.

If the above method is not implemented defaultValue is null. This method is not called back when restorePersistedValue is false

    / * * *@paramRestorePersistedValue Whether there is recoverable data *@paramDefaultValue the defaultValue */
@Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
    if (restorePersistedValue) {
        // Restore data
        mCurrentValue = this.getPersistedInt(DEFAULT_VALUE);
    } else {
        // Initialize the default valuemCurrentValue = (Integer) defaultValue; persistInt(mCurrentValue); }}Copy the code

attribute

Rely on

You can rely on it by filling in the title of another Preference. The attributes are synchronized if the Preference is the same, and if they are different, their availability is synchronized.

android:dependency="notifications_new_message"
Copy the code

Custom view

Having covered code customization earlier, LET’s take a look at XML Attributes

Android: Layout // Custom display content Android :widgetLayout // also custom display contentCopy the code

Distinguish between:

layout

  		<img src="https://ws1.sinaimg.cn/large/006tNc79gy1fi3vx983pdj30u01hc3zw.jpg" width="250"/> 
Copy the code

widgetLayout

You can see that Layout is fully custom, while widgetLayou is still constrained by margins. The dividing line has both

More and more

The default value

As mentioned earlier, the Preference tag has a defaultValue attribute that sets a defaultValue for a Preference.

In addition to setting it in XML, you also need to reset the default value in the Application or main Activity(optional)

PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);
Copy the code

Parameters:

  • Context Context

  • Preferences XML

  • A value in the preference XML with a key of KEY_HAS_SET_DEFAULT_VALUES indicates whether a default value has been set.

    This third argument, if true, initializes the reset regardless of whether the default value has been set, and if false, determines whether the default value has been set.

Subscreen display

It’s not uncommon to see the detailed Settings of an application not in the main preferences screen but in a subscreen that needs to open for more detailed Settings

Header: Use headers to control multiple fragments as sub-screens by setting preference-headers as the root label

<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
    <header android:fragment="com.tianyachuanmei.preperence.AboutFragment" android:title="About" />
    <header android:fragment="com.tianyachuanmei.preperence.MoreFragment" android:title="More"/>
</preference-headers>
Copy the code

This method cannot be loaded by the following method, which is also deprecated.

addPreferencesFromResource(R.xml.pref_headers);
Copy the code

Load XML by overriding the PreferenceActivity method. You do not need to override this method if it is not headers.

    @Override @TargetApi(Build.VERSION_CODES.HONEYCOMB) public void onBuildHeaders(List<Header> target) {
        loadHeadersFromResource(R.xml.pref_general, target);
    }
Copy the code

LoadHeadersFromResource cannot load non-HeadersXML files, otherwise Crash.

Click the event **: Implements the subscreen by specifying the Activity to jump to in Preference

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <Preference
        android:title="@string/prefs_category_one"
        android:summary="@string/prefs_summ_category_one"  >
        <intent
            android:targetPackage="com.example.prefs"
            android:targetClass="com.example.prefs.SettingsActivity"
            android:action="com.example.prefs.PREFS_ONE" />
    </Preference>
    <Preference
        android:title="@string/prefs_category_two"
        android:summary="@string/prefs_summ_category_two" >
        <intent
            android:targetPackage="com.example.prefs"
            an droid:targetClass="com.example.prefs.SettingsActivity"
            android:action="com.example.prefs.PREFS_TWO" />
    </Preference>
</PreferenceScreen>
Copy the code

More panel

Multiple panels need to be implemented using PreferenceActivity, enabling the multi-panel mode by overriding onIsMultiPane to return true

    @Override public boolean onIsMultiPane(a) {
      // The following is to determine whether the current device is a large screen
        return (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
    }
Copy the code

Intentions (Intent)

<PreferenceScreen
                  android:summary="summary_intent_preference"
                  android:title="title_intent_preference" >

  <intent
          android:action="android.intent.action.VIEW"
          android:data="http://www.android.com" />
</PreferenceScreen>
Copy the code

You can create implicit and explicit intents with the following attributes:

  • android:action

    The action to assign (follow the setAction() method).

  • android:data

    The data to allocate (according to the setData() method).

  • android:mimeType

    The MIME type to assign (follow the setType() method).

  • android:targetClass

    The class part of the component name (follow the setComponent() method).

  • android:targetPackage

    The package part of the component name (follow the setComponent() method).

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <Preference
        android:title="prefs_category_one"
        android:summary="prefs_summary_category_one">
        <! Android :targetClass is the Context of the application, and the path of android:targetClass is under the sub-package Settings -->
        <! - if the android: targetPackage = "com. Demo. Artshell. Uidemo. Settings" runtime can't find the Activity -- - >
        <intent
            android:action="prefs_category_action_ONE"
            android:targetPackage="com.demo.artshell.uidemo"
            android:targetClass="com.demo.artshell.uidemo.settings.SupportOldVersionAndReusedActivityOrFragment$ReusedActivity">
            <! GetIntent ().getStringExtra("reused_key") -->
            <extra
                android:name="reused_key"
                android:value="reused_fragment_two"/>
        </intent>
    </Preference>

    <Preference
        android:title="prefs_category_two"
        android:summary="prefs_summary_category_two">
        <intent
            android:action="prefs_category_action_TWO"
            android:targetPackage="com.demo.artshell.uidemo"
            android:targetClass="com.demo.artshell.uidemo.settings.SupportOldVersionAndReusedActivityOrFragment$ReusedActivity"/>
    </Preference>
</PreferenceScreen>
Copy the code