Skip the headers in PreferenceActivity when there's only one header

I added preference-headers to my app so that the preference screen would not look broken on Honeycomb and tablet sized ICS. However, I only have one header at the moment so you have to click through a header screen with only one entry on phone sized devices. Is there an easy way to tell android to skip the header screen when there's only one header, but to still show it on large screens?

It seems that the stock Contacts app does this successfully but I've browsed through its source and can't figure out how it is doing it.

Answers


You can skip the headers by setting one of your PreferenceFragments as default.

When you take a look at the PreferenceActivity.java source, you will find these two extras:

/**
 * When starting this activity, the invoking Intent can contain this extra
 * string to specify which fragment should be initially displayed.
 */
public static final String EXTRA_SHOW_FRAGMENT = ":android:show_fragment";

/**
 * When starting this activity, the invoking Intent can contain this extra
 * boolean that the header list should not be displayed.  This is most often
 * used in conjunction with {@link #EXTRA_SHOW_FRAGMENT} to launch
 * the activity to display a specific fragment that the user has navigated
 * to.
 */
public static final String EXTRA_NO_HEADERS = ":android:no_headers";

Now simply add these two extras to the intent which is invoking your PrefenceActivity and specify the PreferenceFragment which should be shown by default as follows:

Intent intent = new Intent( this, Preferences.class );
intent.putExtra( PreferenceActivity.EXTRA_SHOW_FRAGMENT, PreferencesFragment.class.getName() );
intent.putExtra( PreferenceActivity.EXTRA_NO_HEADERS, true );

Utilizing the EXTRA_SHOW_FRAGMENT mentioned by jenzz, you can manipulate the Activity's Intent, like so:

@Override
protected void onCreate(Bundle savedInstanceState) {
  // By default, show MainPreferences
  Intent intent = getIntent();
  if (intent.getStringArrayExtra(EXTRA_SHOW_FRAGMENT) == null) {
    getIntent().putExtra(EXTRA_SHOW_FRAGMENT, MainPreferences.class.getName());
  }

  super.onCreate(savedInstanceState);
}

You can remove this code in your activity.

     public void onBuildHeaders(List<Header> target) {
        loadHeadersFromResource(R.xml.pref_general, target);
    }

And replace your fragment :

public class SettingsActivity extends AppCompatPreferenceActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
           getFragmentManager().beginTransaction().replace(android.R.id.content,
                new GeneralPreferenceFragment()).commit();

    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static class GeneralPreferenceFragment extends PreferenceFragment {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.pref_general);

        }

    }

}

I don't know if you can specifically skip the header, but this is what I did.

I created 2 classes, one for Extra Large screen sizes, and one for the rest. EditPreferences.class loads my normal preferences.xml, and the EditPreferencesXLarge.class loads the preference-headers xml.

public boolean onOptionsItemSelected(MenuItem item) {
    final int SCREENLAYOUT_SIZE_XLARGE = 4;
    final int HONEYCOMB = 11;
    int screenSize = getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;

    switch(item.getItemId())
    {
        case R.id.item_prefs:
            if (Build.VERSION.SDK_INT < HONEYCOMB) {
                startActivity(new Intent(this, EditPreferences.class));
            }
            else if (screenSize < SCREENLAYOUT_SIZE_XLARGE) {
                startActivity(new Intent(this, EditPreferences.class));
            }
            else {
                startActivity(new Intent(this, EditPreferencesXLarge.class));
            }

            return true;
    }

    return (super.onOptionsItemSelected(item));
}

Need Your Help

UITextView starts at Bottom or Middle of the text

ios objective-c swift xcode cocoa-touch

I'll get right to it. I have a UItextView placed in my view that when needs to scroll to see all the text (when a lot of text is present in the textView) the textView starts in the middle of the text

LINQ to Entities does not recognize the method 'System.String StringConvert(System.Nullable`1[System.Double])

c# sql linq entity-framework

I can't figure out why I'm getting this error. I have used this function successfully with previous versions of Entity Framework but I've set up a new project using EF6 and it's not cooperating.