How could I use the same set of preference screens for all Android versions from 2.X to 4.X?

后端 未结 3 1966
我在风中等你
我在风中等你 2020-12-14 21:21

NOTICE: Please save yourself some time and refer to the accepted answer, no need to read all the quesiton.
You may read the rest of the question and the

3条回答
  •  南方客
    南方客 (楼主)
    2020-12-14 21:33

    If you are on the latest ADT plugin, there is an option to easily create a preference Activity that supports most older Android versions as well as all the new ones.

    Right click on your project -> Other -> Android Activity

    Then choose SettingsActivity enter image description here

    The Activity created will take take care of working with both high and low API versions since it uses if statements to choose the appropriate method of displaying the preferences.


    EDIT
    A good point was brought up: Phone-Sized devices, regardless of API version use the old PreferenceActivity methods.

    The quickest way to get API 11+ devices to use Fragments is to remove !isXLargeTablet(context); from isSimplePreferences()

    private static boolean isSimplePreferences(Context context) {
        return ALWAYS_SIMPLE_PREFS
                || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB;
    }
    

    However, now the user has more navigation to do.
    Headers as root

    This is because onBuildHeaders() is called.

    To get rid of this, we will need to make our own PreferenceFragment that adds each xml resource.

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
        public static class AllPreferencesFragment extends PreferenceFragment{
            @Override
            public void onCreate (Bundle savedInstanceState){
                super.onCreate(savedInstanceState);
                addPreferencesFromResource(R.xml.pref_general);
    
                // Add 'notifications' preferences, and a corresponding header.
                PreferenceCategory fakeHeader = new PreferenceCategory(getActivity());
                fakeHeader.setTitle(R.string.pref_header_notifications);
                getPreferenceScreen().addPreference(fakeHeader);
                addPreferencesFromResource(R.xml.pref_notification);
    
                // Add 'data and sync' preferences, and a corresponding header.
                fakeHeader = new PreferenceCategory(getActivity());
                fakeHeader.setTitle(R.string.pref_header_data_sync);
                getPreferenceScreen().addPreference(fakeHeader);
                addPreferencesFromResource(R.xml.pref_data_sync);
    
                // Bind the summaries of EditText/List/Dialog/Ringtone preferences to
                // their values. When their values change, their summaries are updated
                // to reflect the new value, per the Android Design guidelines.
                bindPreferenceSummaryToValue(findPreference("example_text"));
                bindPreferenceSummaryToValue(findPreference("example_list"));
                bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
                bindPreferenceSummaryToValue(findPreference("sync_frequency"));
            }
        }
    

    If you can determine the screen size from outside the Activity that launches the settings, you can specify a fragment for it to launch via EXTRA_SHOW_FRAGMENT

    i.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, "com.example.test.SettingsActivity$AllPreferencesFragment");
    

    Or you can have the SettingsActivity determine whether or not to show this Fragment (assuming you're happy with the isXLargeTablet() method.

    Change onBuildHeaders() to:

    @Override
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public void onBuildHeaders(List
    target) { if (!isSimplePreferences(this) && isXLargeTablet(this)) { loadHeadersFromResource(R.xml.pref_headers, target); } }

    Add this method:

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private void setupNewApiPhoneSizePreferences() {
        if (!isXLargeTablet(this) && Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB){
                getFragmentManager().beginTransaction().replace(android.R.id.content, new AllPreferencesFragment()).commit();
        }
    }
    

    And in onPostCreate() add the method call.

    setupNewApiPhoneSizePreferences();
    

    This should now use non-deprecated calls from API 11 onwards.

提交回复
热议问题