PreferenceScreen interno non si apre con PreferenceFragmentCompat

Il mio interface preferenziale di PreferenceFragmentCompat non sta visualizzando o sembra ignorare gli events di intercettazione.

Ho creato MyPreferenceFragment che extends PreferenceFragmentCompat

  • Aggiornamenti della posizione Android in un servizio
  • Come effettuare l'avvio del dispositivo Android quando l'alimentazione è collegata?
  • Android ICS: errore JNI tentativo di utilizzare il riferimento locale stale 0x1
  • Android compila l'errore utilizzando buildozer
  • onListItemClick non funziona per listview?
  • Persistente una class di raccolta con ORMLite in android
  •  public class MyPreferenceFragment extends PreferenceFragmentCompat { @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { addPreferencesFromResource(R.xml.preferences); } } 

    poi ho cambiato il mio tema a styles.xml come

     <style name="AppTheme" parent="@style/Theme.AppCompat.Light"> <item name="preferenceTheme">@style/PreferenceThemeOverlay</item> </style> 

    E infine crea il mio file preferences.xml come

     <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <CheckBoxPreference android:title="Check Me"/> <PreferenceScreen android:title="My Screen"> <!-- This is not opening --> <EditTextPreference android:title="Edit text" /> </PreferenceScreen> </PreferenceScreen> 

    Al build.gradle ho aggiunto entrambi:

     compile 'com.android.support:appcompat-v7:23.0.1' compile 'com.android.support:preference-v7:23.0.1' 

    codice dell'attività

     public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } } 

    activity_main.xml

     <fragment xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment" android:name="com.mando.preferenceapp.MyPreferenceFragment" android:layout_width="match_parent" android:layout_height="match_parent" /> 

    Prova il codice sopra non posso aprire / entrare nella schermata di preferenza. Mi sto perdendo qualcosa? Perché questo non funziona?

  • Dichiarazione globale di variabile in android
  • Dialogo di allarme di Android con uno, due e tre pulsanti
  • Caratteri CSS su Android
  • Compilare e linkare contro libusb per android
  • Android - scrivere / salvare i file solo dal codice nativo
  • Come aggiungere il tipo di mime personalizzato?
  • 4 Solutions collect form web for “PreferenceScreen interno non si apre con PreferenceFragmentCompat”

    Dopo aver trascorso molte ore con i tentativi, cercando e grazie fortunatamente con qualche aiuto dai creatori della libreria di supporto. Sono riuscito a far funzionare.

    Fase 1. Activity

     public class MyActivity extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState == null) { // Create the fragment only when the activity is created for the first time. // ie. not after orientation changes Fragment fragment = getSupportFragmentManager().findFragmentByTag(MyPreferenceFragment.FRAGMENT_TAG); if (fragment == null) { fragment = new MyPreferenceFragment(); } FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.fragment_container, fragment, MyPreferenceFragment.FRAGMENT_TAG); ft.commit(); } } @Override public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat, PreferenceScreen preferenceScreen) { FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); MyPreferenceFragment fragment = new MyPreferenceFragment(); Bundle args = new Bundle(); args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, preferenceScreen.getKey()); fragment.setArguments(args); ft.replace(R.id.fragment_container, fragment, preferenceScreen.getKey()); ft.addToBackStack(preferenceScreen.getKey()); ft.commit(); return true; } } 

    Suggerimenti.

    • Non aggiungere il frammento in xml avrai incidenti sui cambiamenti di orientamento.
    • Gestire le ricreazioni di attività / frammento aggiungere in onCreate modo da evitare di perdere il tuo frammento quando si trova all'interno di uno schermo di preferenza.
    • L'attività host del frammento deve implementare il PreferenceFragmentCompat.OnPreferenceStartScreenCallback e ricreare frammenti della stessa istanza.

    Fase 2. PreferenceFragment

     public class MyPreferenceFragment extends PreferenceFragmentCompat { public static final String FRAGMENT_TAG = "my_preference_fragment"; public MyPreferenceFragment() { } @Override public void onCreatePreferences(Bundle bundle, String rootKey) { setPreferencesFromResource(R.xml.preferences, rootKey); } } 

    Suggerimenti.

    • Utilizzare il metodo setPreferencesFromResource e approfittare della rootKey di each schermata. In questo modo il codice verrà riutilizzato correttamente.
    • Tieni presente che se hai un codice come findPreference nel tuo frammento, dovresti avere dei controlli null come quando si trovavano negli schermi interni, questo non ti darà niente.

    La cosa che manca ora è l'implementazione della freccia posteriore nella barra di azione (azione a casa) ma questo non funziona mai da solo 😉

    Ho anche creato un'applicazione demo che avvolge tutto questo codice che puoi trovare su github .

    Lo ho fatto leggermente diverso, sto lanciando una nuova attività per each schermo. Questo sembra richiedere less hack: nessuna necessità di confusione con scambiare frammenti e colors di background. Ottieni anche l'animation di cambiamento di attività come bonus!

     public class PreferencesActivity extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback { final static private String KEY = "key"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.preferences); setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) actionBar.setDisplayHomeAsUpEnabled(true); if (savedInstanceState != null) return; Fragment p = new PreferencesFragment(); String key = getIntent().getStringExtra(KEY); if (key != null) { Bundle args = new Bundle(); args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, key); p.setArguments(args); } getSupportFragmentManager().beginTransaction() .add(R.id.preferences, p, null) .commit(); } @Override public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat, PreferenceScreen preferenceScreen) { Intent intent = new Intent(PreferencesActivity.this, PreferencesActivity.class); intent.putExtra(KEY, preferenceScreen.getKey()); startActivity(intent); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { onBackPressed(); return true; } return super.onOptionsItemSelected(item); } public static class PreferencesFragment extends PreferenceFragmentCompat implements ... { private static final String FRAGMENT_DIALOG_TAG = "android.support.v7.preference.PreferenceFragment.DIALOG"; private String key; @Override public void onCreatePreferences(Bundle bundle, String key) { setPreferencesFromResource(R.xml.preferences, this.key = key); } // this only sets the title of the action bar @Override public void onActivityCreated(Bundle savedInstanceState) { ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar(); if (actionBar != null) actionBar.setTitle((key == null) ? "Settings" : findPreference(key).getTitle()); super.onActivityCreated(savedInstanceState); } } } 

    xml:

     <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="0dp" android:orientation="vertical" android:padding="0dp" android:id="@+id/preferences"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" /> <!-- preference fragment will be inserted here programmatically --> </LinearLayout> 

    Sulla base della soluzione Intent @squirrel, ho fatto funzionare in questo modo. Richiede anche un peggioramento dell'hacking.
    Attività:

     import android.support.v7.app.AppCompatActivity; public class SettingsActivity extends AppCompatActivity { public static final String TARGET_SETTING_PAGE = "target"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SettingsFragment settingsFragment = new SettingsFragment(); Intent intent = getIntent(); if (intent != null) { String rootKey = intent.getStringExtra(TARGET_SETTING_PAGE); if (rootKey != null) { settingsFragment.setArguments(Bundler.single(TARGET_SETTING_PAGE, rootKey)); } } getFragmentManager().beginTransaction() .replace(android.R.id.content, settingsFragment) .commit(); } } 

    Frammento:

     import android.support.v14.preference.PreferenceFragment; public class SettingsFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle arguments = getArguments(); if (arguments != null && arguments.getString(TARGET_SETTING_PAGE) != null) { setPreferencesFromResource(R.xml.preferences, arguments.getString(TARGET_SETTING_PAGE)); } else { addPreferencesFromResource(R.xml.preferences); } } @Override public void onNavigateToScreen(PreferenceScreen preferenceScreen) { Intent intent = new Intent(getActivity(), SettingsActivity.class) .putExtra(TARGET_SETTING_PAGE, preferenceScreen.getKey()); startActivity(intent); super.onNavigateToScreen(preferenceScreen); } } 

    È triste che hai bisogno di tante hack nelle librerie di appcompat di supporto per qualcosa che funziona perfettamente fuori dal box in android standard.

    La soluzione è quella di avviare un altro frammento della stessa class ma con una chiave di root diversa. Nessuna azione triggersta.

     @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey){ if(getArguments() != null){ String key = getArguments().getString("rootKey"); setPreferencesFromResource(R.xml.preferences, key); }else{ setPreferencesFromResource(R.xml.preferences, rootKey); } } @Override public void onNavigateToScreen(PreferenceScreen preferenceScreen){ ApplicationPreferencesFragment applicationPreferencesFragment = new ApplicationPreferencesFragment(); Bundle args = new Bundle(); args.putString("rootKey", preferenceScreen.getKey()); applicationPreferencesFragment.setArguments(args); getFragmentManager() .beginTransaction() .replace(R.id.container, applicationPreferencesFragment) .addToBackStack(null) .commit(); } 
    L'Android è un fan Android di Google, tutto su telefoni Android, Android Wear, Android Dev e applicazioni Android Games e così via.