Show up-Button in actionBar in subscreen preferences

user1567896 picture user1567896 · Jan 29, 2014 · Viewed 7.7k times · Source

I've implemented my preferences like shown in the official guidelines.

I have a PreferenceActivity which creates the PreferenceFragment like this:

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

      Bundle extras = getIntent().getExtras();
      if (extras != null) 
      {
          Bundle bundle = new Bundle();
          _widgetID = extras.getInt(GlobalSettings.EXTRA_WIDGET_ID); 
          bundle.putInt(GlobalSettings.EXTRA_WIDGET_ID, _widgetID);

          WidgetSettingsFragment fragment = new WidgetSettingsFragment();
          fragment.setArguments(bundle);

          getFragmentManager().beginTransaction().replace(android.R.id.content,
                        fragment).commit();
      }

 }

The PreferenceFragment loads the preferences from the resources and they contain a preference subscreen like this:

<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>

This works well so far, but now I'd like to have an up-Button in the actionBar when the preferences subscreen is shown. Any idea how to accomplish that?

I have tried to set setDisplayHomeAsUpEnabled(true) in my activity but then the up-Button is only shown in the main preferences (where it should not) and not in the subscreen.

I'm wondering that even in the official docs the subscreen is shown without an active up-Button: Setting subscreens

Link to the docs: Settings

Any help is really welcome

Answer

user1567896 picture user1567896 · Feb 8, 2014

I finally got it to work :D. It's quite hacky but it works.

The problem is, that using subscreens in xml-layouts results in some 'code magic'. A new activity/dialog is started for the subscreen and you don't have direct access to it.

To get access to the actionbar and the OnClickListener of the home/up-button you need to get a reference to your PreferenceScreen and get its parent Dialog in order to access the actionbar and its home/up button.

This is how it is done inside my PreferenceFragment:

 @Override
 public void onCreate(Bundle savedInstanceState) 
 {
...

 final PreferenceScreen preferenceScreen = (PreferenceScreen) findPreference(getString(R.string.keyPrefScreenDynamicWidgetDetails));
  preferenceScreen.setOnPreferenceClickListener(new OnPreferenceClickListener() 
  {
       public boolean onPreferenceClick(Preference preference) 
       {
           preferenceScreen.getDialog().getActionBar().setDisplayHomeAsUpEnabled(true);
           final Dialog dialog = preferenceScreen.getDialog();

           View homeBtn = dialog.findViewById(android.R.id.home);
           if (homeBtn != null) 
           {
               OnClickListener dismissDialogClickListener = new OnClickListener()
               {
                   @Override
                   public void onClick(View v) 
                   {
                      dialog.dismiss();
                   }
               };

               // Prepare yourselves for some hacky programming
               ViewParent homeBtnContainer = homeBtn.getParent();

               // The home button is an ImageView inside a FrameLayout
               if (homeBtnContainer instanceof FrameLayout) {
                   ViewGroup containerParent = (ViewGroup) homeBtnContainer.getParent();

                   if (containerParent instanceof LinearLayout) {
                       // This view also contains the title text, set the whole view as clickable
                       ((LinearLayout) containerParent).setOnClickListener(dismissDialogClickListener);
                   } else {
                       // Just set it on the home button
                       ((FrameLayout) homeBtnContainer).setOnClickListener(dismissDialogClickListener);
                   }
               } else {
                   // The 'If all else fails' default case
                   homeBtn.setOnClickListener(dismissDialogClickListener);
               }                   
           }
           return true;
       }
  });
...

}

Following link gave me the final hints and code to solve my problem:

Action Bar Home Button not functional with nested PreferenceScreen