开发者

How to navigate to nested PreferencesScreen

开发者 https://www.devze.com 2023-02-15 07:44 出处:网络
in my app I have nested PreferencesScreen\'s <PreferencesScreen> <PreferencesScreen and开发者_Go百科roid:key=\"application\">

in my app I have nested PreferencesScreen's

<PreferencesScreen>
    <PreferencesScreen and开发者_Go百科roid:key="application">

    </PreferencesScreen>
</PreferencesScreen>

Now I want to fire Intent to take me from currrent Activity directly to application preferences subscreen. How can I do this?


In my application I have the similar task to show second-level PreferencesScreen programmatically. What I did:

  1. In preferences.xml I assigned a key to PreferencesScreen I want to show (as shown in the question).

  2. To show PreferencesScreen I wrote:

    final Intent preferencesActivity = new Intent(getBaseContext(), MyPreferencesActivity.class);
    preferencesActivity.putExtra("PREFERENCE_SCREEN_KEY", "key_of_preference_screen_to_show");
    startActivity(preferencesActivity);
    
  3. Then in my PreferenceActivity class in method onCreate the following code was added:

    final Intent intent = getIntent();
    final String startScreen = intent.getStringExtra("PREFERENCE_SCREEN_KEY");
    if (startScreen != null) {
        getIntent().removeExtra("PREFERENCE_SCREEN_KEY");
        final Preference preference = findPreference(startScreen);
        final PreferenceScreen preferenceScreen = getPreferenceScreen();
        final ListAdapter listAdapter = preferenceScreen.getRootAdapter();
        final int itemsCount = listAdapter.getCount();
        int itemNumber;
        for (itemNumber = 0; itemNumber < itemsCount; ++itemNumber) {
            if (listAdapter.getItem(itemNumber).equals(preference)) {
                preferenceScreen.onItemClick(null, null, itemNumber, 0);
                break;
            }
        }
    }
    

One remark... Not only second-level PreferencesScreen, but the whole preferences hierarchy was loaded here. So, if you press Back button, the first (parent) PreferencesScreen will appear. In my case that was exactly what I needed. Not sure about yours.


Here is a way of handling the problem by grabbing the child-screen up front:

public class MyChildPreferenceActivity extends PreferenceActivity {

    private String screenKey = "myChildScreenKey";

    @Override
    public PreferenceScreen getPreferenceScreen() {
        PreferenceScreen root = super.getPreferenceScreen();
        if (root != null) {
            PreferenceScreen match = findByKey(root, screenKey);
            if (match != null) {
                return match;
            } else {
                throw new RuntimeException("key " + screenKey + " not found");
            }
        } else {
            return null;
        }
    }

    private PreferenceScreen findByKey(PreferenceScreen parent, String key) {
        if (key.equals(parent.getKey())) {
            return parent;
        } else {
            for (int i = 0; i < parent.getPreferenceCount(); i++) {
                Preference child = parent.getPreference(i);
                if (child instanceof PreferenceScreen) {
                    PreferenceScreen match = findByKey((PreferenceScreen) child, key);
                    if (match != null) {
                        return match;
                    }
                }
            }
            return null;
        }
    }

    // ...


I resolved your exact same issue this way.

In your preference activity:

@Override
protected void onResume() {
    super.onResume();       

    int startingPage = getIntent().getIntExtra(Constants.PREFS_STARTING_PAGE, 0);

    switch (startingPage) {
        case Constants.MY_PREF_SCREEN_1:
            setPreferenceScreen((PreferenceScreen)findPreference(getString(R.string.PREF_SCREEN_1)));
            break;
        case Constants.MY_PREF_SCREEN_2:
            setPreferenceScreen((PreferenceScreen)findPreference(getString(R.string.PREF_SCREEN_2)));
            break;
        default:
            // Nothing to do, but read the warning below.
    }
}

Then you can open the inner preference screen with something like this:

    Intent prefIntent = new Intent(ctx, MyPreferenceActivity.class);
    prefIntent.putExtra(Constants.PREFS_STARTING_PAGE, Constants.MY_PREF_SCREEN_1);
    startActivity(prefIntent);

Beware that this works as long as the activity instances are different: one instance for the main preference screen and another for the inner screen. In this way, when you start the activity without "launch" parameter, you always fall into the default switch case and never need to set the main preference screen. The problem here is that if you first run the activity starting with an inner pref screen and then lauch the SAME activity (with the flag singleInstance, for example) asking for the general (root) pref screen, you're not able to call findPreference() to find the root preference screen from inside a child preference screen.

Well, hope to have not made too much confusion ;-)


The way I use is to put nested PreferenceScreen into a separate XML file and use it in other PreferenceActivity. In this case you'll be able to navigate to this screen from preferences using Preference.setIntent() and start this Activity in a usual way from another Activity.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号