Inner PreferenceScreen n'est pas ouvert avec PreferenceFragmentCompat

Mon préféré interne L'écran de préférenceFragmentCompat ne s'affiche pas ou semble ignorer les événements de saisie.

J'ai créé MyPreferenceFragment qui extends PreferenceFragmentCompat

  • Android AutocompleteTextView utilisant ArrayAdapter et Filter
  • Comment donner des notifications sur Android à un moment précis?
  • Obtenir le nom de l'application à partir du nom du package
  • Android Market - Cette application est-elle disponible pour plus de 0 périphériques?
  • Exécuter la commande shell à partir d'Android
  • Jeton Firebase FCM - Quand envoyer au serveur?
  •  public class MyPreferenceFragment extends PreferenceFragmentCompat { @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { addPreferencesFromResource(R.xml.preferences); } } 

    Alors j'ai changé ma thème à styles.xml comme

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

    Et enfin, créez mes fichiers preferences.xml comme

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

    Au build.gradle j'ai ajouté les deux:

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

    Code de l'activité

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

    En testant le code ci-dessus, je ne peux pas ouvrir / accéder à l'écran de préférences. Est-ce que je manque quelque chose? Pourquoi cela ne fonctionne pas?

  • Texte noir sur fond sombre sur le nougat (android.R.layout.simple_spinner_item)
  • Android: Est-il possible de faire une copie d'une vue?
  • Utilisation d'outils de développement Google Chrome sur Android (émulateur)
  • Envoyer la demande d'application à tous les amis de Facebook en utilisant 'Dialogues de requêtes' dans Android
  • Butterknife est incapable de se lier dans ma classe d'adaptateur
  • Comment détecter un processeur dual-core sur un périphérique Android à partir du code?
  • 3 Solutions collect form web for “Inner PreferenceScreen n'est pas ouvert avec PreferenceFragmentCompat”

    Après avoir passé de nombreuses heures avec des essais, la recherche et heureusement avec l'aide des créateurs de la bibliothèque de soutien. J'ai réussi à le faire fonctionner.

    Étape 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; } } 

    Conseils.

    • N'ajoutez pas le fragment par xml vous aurez des collisions sur les modifications d'orientation.
    • Utilisez les récréations d'activité / fragment ajoutées dans le onCreate de onCreate afin d'éviter de perdre votre fragment dans un écran de préférences.
    • L'activité hôte du fragment doit implémenter PreferenceFragmentCompat.OnPreferenceStartScreenCallback et recréer des fragments d'une même instance.

    Étape 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); } } 

    Conseils.

    • Utilisez la méthode setPreferencesFromResource et profitez de la rootKey de chaque écran. De cette façon, votre code sera réutilisé correctement.
    • Gardez à l'esprit que si vous avez un code comme findPreference dans votre fragment, il devrait avoir null contrôles null , car, lorsque vous étiez dans des écrans intérieurs, cela ne vous donnera rien.

    Ce qui manque maintenant, c'est la mise en œuvre de la flèche arrière dans la barre d'action (action à la maison), mais cela ne fonctionne jamais seul 😉

    J'ai également créé une application de démonstration qui enveloppe tout ce code que vous pouvez trouver sur github .

    Je l'ai fait différemment, je lance une nouvelle activité pour chaque écran. Cela semble nécessiter moins de hacks: il n'est pas nécessaire de faire du mal à échanger des fragments et des couleurs d'arrière-plan. Vous obtenez également une animation de changement d'activité en 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> 

    Basé sur la solution @squirrel Intent, je l'ai fait fonctionner de cette façon. Il nécessite encore moins de piratage.
    Activité:

     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(); } } 

    Fragment:

     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); } } 

    Il est triste que vous ayez besoin de trop de hacks dans les bibliothèques appcompat de soutien pour quelque chose qui fonctionne parfaitement sans préavis dans l'Android standard.

    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.