Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Toolbar is hidden in nested PreferenceScreen

I use PreferenceFragment in ActionBarActivity from support-v7 library.
In the Activity I have Toolbar. Everything goes okay, until I open a nested PreferenceScreen.
In the opened screen the Toolbar is hidden.

Maybe somebody know a workaround for this issue?

Preferences xml-file:

<?xml version="1.0" encoding="utf-8"?>
    <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <PreferenceCategory android:title="Main category" >

        <EditTextPreference
            android:defaultValue="defaultValue"
            android:key="key_global_setting"
            android:title="Global title" />        

    </PreferenceCategory>

    <PreferenceCategory android:title="Nested screens" >        

        <PreferenceScreen
            android:persistent="false"
            android:title="@string/settings_facility_title" >

        <CheckBoxPreference
            android:defaultValue="false"
            android:key="nested_screen_1_1"
            android:title="Nested screen 1.1 check box" />

        <CheckBoxPreference
            android:defaultValue="true"
            android:key="nested_screen_1_2"
            android:title="Nested screen 1.2 check box" />
        </PreferenceScreen>

        <PreferenceScreen
            android:persistent="false"
            android:title="@string/settings_menu_screen_title" >

         <CheckBoxPreference
            android:defaultValue="true"
            android:key="nested_screen2"
            android:title="Nested screen 2 check box" />
        </PreferenceScreen>        

    </PreferenceCategory>    

</PreferenceScreen> 

Activity layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"    
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".SettingsScreen" >

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        style="@style/Toolbar" />

    <FrameLayout
        android:id="@+id/contentSettings"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>
like image 430
yurezcv Avatar asked Jan 09 '15 14:01

yurezcv


2 Answers

I found the solution on my own. I used a small work-around of all this nested PreferenceScreen's. I simply made a separation to different xml-preference files, created an additional Fragment which extends PreferenceFragment and there I show an appropriate nested preference screen.
Maybe somebody would found this useful.

Github sources link.

Some code examples below:

main_preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <PreferenceCategory android:title="Main category" >

        <EditTextPreference
            android:defaultValue="defaultValue"
            android:key="key_global_setting"
            android:title="Global title" />

    </PreferenceCategory>

    <PreferenceCategory android:title="Nested screens" >

        <Preference
            android:key="NESTED_KEY1"
            android:persistent="false"
            android:title="Nested screen #1" />

        <Preference
            android:key="NESTED_KEY2"
            android:persistent="false"
            android:title="Nested screen #2" />

    </PreferenceCategory>

</PreferenceScreen> 

nested_screen1_preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    android:title="Nested screen #1" >

    <CheckBoxPreference
        android:defaultValue="false"
        android:key="nested_screen_1_1"
        android:title="Nested screen 1.1 check box" />

    <CheckBoxPreference
        android:defaultValue="true"
        android:key="nested_screen_1_2"
        android:title="Nested screen 1.2 check box" />
</PreferenceScreen>

nested_screen2_preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    android:title="Nested screen #2">

    <CheckBoxPreference
        android:defaultValue="true"
        android:key="nested_screen2"
        android:title="Nested screen 2 check box" />
</PreferenceScreen>

SettingsActivity.java

public class SettingsActivity extends ActionBarActivity implements MyPreferenceFragment.Callback {

    private static final String TAG_NESTED = "TAG_NESTED";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_settings);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        if (toolbar != null) {
            setSupportActionBar(toolbar);
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        }

        if (savedInstanceState == null) {
            getFragmentManager().beginTransaction()
                    .add(R.id.contentSettings, new MyPreferenceFragment())
                    .commit();
        }
    }

    @Override
    public void onBackPressed() {
        // this if statement is necessary to navigate through nested and main fragments
        if (getFragmentManager().getBackStackEntryCount() == 0) {
            super.onBackPressed();
        } else {
            getFragmentManager().popBackStack();
        }
    }

    @Override
    public void onNestedPreferenceSelected(int key) {
        getFragmentManager().beginTransaction().replace(R.id.contentSettings, NestedPreferenceFragment.newInstance(key), TAG_NESTED).addToBackStack(TAG_NESTED).commit();
    }    
}

MyPreferenceFragment.java

// The main preference fragment class
public class MyPreferenceFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener {

    private Callback mCallback;

    private static final String KEY_1 = "NESTED_KEY1";
    private static final String KEY_2 = "NESTED_KEY2";

    @Override
    public void onAttach(Activity activity) {

        super.onAttach(activity);

        if (activity instanceof Callback) {
            mCallback = (Callback) activity;
        } else {
            throw new IllegalStateException("Owner must implement Callback interface");
        }
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.main_preferences);

        // add listeners for non-default actions
        Preference preference = findPreference(KEY_1);
        preference.setOnPreferenceClickListener(this);

        preference = findPreference(KEY_2);
        preference.setOnPreferenceClickListener(this);
    }

    @Override
    public boolean onPreferenceClick(Preference preference) {
        // here you should use the same keys as you used in the xml-file
        if (preference.getKey().equals(KEY_1)) {
            mCallback.onNestedPreferenceSelected(NestedPreferenceFragment.NESTED_SCREEN_1_KEY);
        }

        if (preference.getKey().equals(KEY_2)) {
            mCallback.onNestedPreferenceSelected(NestedPreferenceFragment.NESTED_SCREEN_2_KEY);
        }

        return false;
    }

    public interface Callback {
        public void onNestedPreferenceSelected(int key);
    }
}

NestedPreferencesFragment.java

public class NestedPreferenceFragment extends PreferenceFragment {

    public static final int NESTED_SCREEN_1_KEY = 1;
    public static final int NESTED_SCREEN_2_KEY = 2;

    private static final String TAG_KEY = "NESTED_KEY";

    public static NestedPreferenceFragment newInstance(int key) {
        NestedPreferenceFragment fragment = new NestedPreferenceFragment();
        // supply arguments to bundle.
        Bundle args = new Bundle();
        args.putInt(TAG_KEY, key);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        checkPreferenceResource();
    }

    private void checkPreferenceResource() {
        int key = getArguments().getInt(TAG_KEY);
        // Load the preferences from an XML resource
        switch (key) {
            case NESTED_SCREEN_1_KEY:
                addPreferencesFromResource(R.xml.nested_screen1_preferences);
                break;

            case NESTED_SCREEN_2_KEY:
                addPreferencesFromResource(R.xml.nested_screen2_preferences);
                break;

            default:
                break;
        }
    }

}
like image 55
yurezcv Avatar answered Oct 25 '22 21:10

yurezcv


Here comes my solution, which is inspired by the original answer but not that complicated. Maybe it'll help someone...

layout/settings.xml:

    <RelativeLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <include
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            layout="@layout/toolbar" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/content"
            android:layout_below="@+id/toolbar"/>

    </RelativeLayout>

Classes:

public class SettingsActivity extends ActionBarActivity {
  @Override
  protected void onCreate( Bundle savedInstanceState ) {
    setContentView( R.layout.settings );
    super.onCreate( savedInstanceState ); 
    initializeSupportActionBar();
    getFragmentManager().beginTransaction().replace( R.id.content, new MainFragment() ).commit();
  }

  @Override
  public void onBackPressed() {
    if( !getFragmentManager().popBackStackImmediate() ) super.onBackPressed();
  }
}

public class MainFragment extends PreferenceFragment {

  public MainFragment() {}

  @Override
  public void onCreate( Bundle savedInstanceState ) {
    super.onCreate( savedInstanceState );
    addPreferencesFromResource( R.xml.pref_main );
    // "nested" is the <Preference android:key="nested" android:persistent="false"/>`
    findPreference( "nested" ).setOnPreferenceClickListener( new OnPreferenceClickListener() {
      @Override public boolean onPreferenceClick( Preference preference ) {
        getFragmentManager().beginTransaction().replace( R.id.content, new NestedFragment() ).addToBackStack( NestedFragment.class.getSimpleName() ).commit();
        return true;
      }
    } );
  }

public class NestedFragment extends PreferenceFragment {
  ...
}

I tested it on 4.3 and 5.0.2 and no limitation on nesting levels applies

like image 7
injecteer Avatar answered Oct 25 '22 21:10

injecteer