android - studio - La barra de herramientas está oculta en PreferenceScreen anidado
preferencescreen android tutorial (4)
Aquí viene mi solución, que está inspirada en la respuesta original pero no tan complicada. Tal vez ayude a alguien ...
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>
Clases:
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 {
...
}
Lo probé en 4.3
y 5.0.2
y no se aplica ninguna limitación en los niveles de anidamiento
Uso PreferenceFragment
en ActionBarActivity
de la biblioteca support-v7.
En la actividad tengo Toolbar
. Todo va bien, hasta que abro una PreferenceScreen
anidada.
En la pantalla abierta la Toolbar
está oculta.
Tal vez alguien sabe una solución para este problema?
Preferencias de archivo 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" >
<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>
Diseño de la actividad:
<?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>
Como el problema proviene de la parte en la que aún se encuentra en la misma actividad / fragmento y la pantalla de preferencias anidada es solo un cuadro de diálogo, puede hacer lo siguiente:
- Puede establecer preferencia escucha clic
Obtenga la vista raíz desde el cuadro de diálogo:
(PreferenceScreen)preference).getDialog().getWindow() .getDecorView().getRootView());
Busque de forma recursiva hasta encontrar una vista de código auxiliar (hay una, desafortunadamente no conozco
android.R.id.xxxxx
) y establezca qué diseño necesita como título, que se verá como la barra de herramientas (puede inflar la barra de herramientas):private Toolbar toolbar; public void findViewStub(ViewGroup viewGroup) { int childCount = viewGroup.getChildCount(); for (int i = 0; i < childCount; i++) { View childView = viewGroup.getChildAt(i); if( childView instanceof ViewStub){ ((ViewStub)childView).setLayoutResource(R.layout.your_title_layout); toolbar = ((ViewStub)childView).inflate(); } if (childView instanceof ViewGroup) { findViewStub((ViewGroup) childView); } } } toolbar.setNavigationIcon(); toolbar.setNavigationOnClickListener(); toolbar.setTitle();
En el diseño solo se puede poner una barra de herramientas. Y establece el icono de volver. Regístrese para hacer clic en él y haciendo referencia al fragmento, al hacer clic en este botón puede cerrar el diálogo. Has puesto título y etc.
En mi solución solo necesita una AppCompatActivity
y una PreferenceFragement
, pero varios archivos XML, cada uno con un solo nivel de PreferenceScreens
.
Lista de archivos XML
- PreferenceScreen de nivel superior
- PreferenceScreen 0 de segundo nivel
- PreferenceScreen 1 de segundo nivel
- PreferenceScreen 2 de segundo nivel
- ...
Este código es para un subnivel (por simplicidad y para tener una idea), pero puede extenderlo fácilmente para tener subniveles arbitrarios de PreferenceScreens
.
SettingsFragment.java
public class SettingsFragment extends PreferenceFragment
{
private int xmlId;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
xmlId = R.xml.preferences;
addPreferencesFromResource(xmlId);
}
public void changePrefScreen(int xmlId, int titleId)
{
this.xmlId = xmlId;
((AppCompatActivity)getActivity()).getSupportActionBar().setTitle(getActivity().getResources().getString(titleId));
getPreferenceScreen().removeAll();
addPreferencesFromResource(xmlId);
}
// will be called by SettingsActivity (Host Activity)
public void onUpButton()
{
if(xmlId == R.xml.preferences) // in top-level
{
// Switch to MainActivity
Intent intent = new Intent(getActivity(), MainActivity.class);
startActivity(intent);
}
else // in sub-level
{
changePrefScreen(R.xml.preferences, R.string.settings);
}
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)
{
String key = preference.getKey();
//
// Top level PreferenceScreen
//
if(key.equals("top_key_0"))
{
changePrefScreen(R.xml.download_preference_screen, R.string.download_database); // descend into second level
}
// ...
//
// Second level PreferenceScreens
//
if (key.equals("second_level_key_0"))
{
// do something...
}
// ...
}
ConfiguraciónActividad.java
public class SettingsActivity extends AppCompatActivity
{
SettingsFragment settingsFragment;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
settingsFragment = new SettingsFragment();
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
.replace(android.R.id.content, settingsFragment)
.commit();
}
//
// Handle what happens on up button
//
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case android.R.id.home:
settingsFragment.onUpButton();
return true;
}
return true;
}
// ...
}
Técnicamente debería funcionar para todas las versiones de Android para las que está disponible PreferenceFragment
.
Encontré la solución por mi cuenta. Utilicé una pequeña solución de todos estos PreferenceScreen''s
anidados. Simplemente hice una separación a diferentes archivos de xml-preference
, creé un Fragment
adicional que extiende PreferenceFragment
y allí muestro una pantalla de preferencias anidada apropiada.
Tal vez alguien encontraría esto útil.
Algunos ejemplos de código a continuación:
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>
ConfiguraciónActividad.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;
}
}
}