J'essaie d'implémenter des préférences avec des sous-écrans en utilisant AppCompatActivity et support.v7.preference
Selon la documentation, chaque écran PreferenceScreen d'un autre écran PreferenceScreen fonctionne comme un sous-écran et le framework gérera son affichage lorsqu'il est cliqué . http://developer.Android.com/guide/topics/ui/settings. html # Sous-écrans
<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>
Cela fonctionne correctement en utilisant Activity, PreferenceFragment ... en natif, mais en utilisant AppCompatActivity et PreferenceFragmentCompat, un clic sur l'élément Préférence le met en surbrillance, mais n'ouvre pas le sous-écran.
Je n'ai rien trouvé dans cette lecture de la documentation et du code ... dois-je implémenter des rappels supplémentaires?
EDIT: juste pour être complet ...
Cela fonctionne et ouvre le sous-écran:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.replace(Android.R.id.content, new DemoPreferenceFragment())
.commit();
}
}
static public class DemoPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
}
Cela ne fonctionne pas/ouvre le sous-écran:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(Android.R.id.content, new DemoPreferenceFragment())
.commit();
}
}
static public class DemoPreferenceFragment extends PreferenceFragmentCompat {
@Override
public void onCreatePreferences(Bundle bundle, String s) {
addPreferencesFromResource(R.xml.preferences);
}
}
}
Edit: 25/01/2016
Après avoir tripoté avec support.v7.preference pendant quelques jours, j'ai résumé mes conclusions ici, espérant que cela pourrait aider les autres: Comment utiliser support.v7.preference avec AppCompat et potentiel désavantages
Cela ressemble à un bogue dans PreferenceFragmentCompat ou à une insuffisance de documents. Il a la méthode onNavigateToScreen qui est appelée lorsque vous cliquez sur l’élément PreferenceScreen.
Mais la méthode getCallbackFragment () renvoie la valeur null par défaut. Vous devez donc la remplacer dans votre fragment pour la renvoyer. Aussi, vous devez implémenter PreferenceFragmentCompat.OnPreferenceStartScreenCallback.
public class SettingsFragment extends PreferenceFragmentCompat implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
public static SettingsFragment newInstance() {
return new SettingsFragment();
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.news_settings);
}
@Override
public Fragment getCallbackFragment() {
return this;
}
@Override
public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat, PreferenceScreen preferenceScreen) {
preferenceFragmentCompat.setPreferenceScreen(preferenceScreen);
return true;
}
}
Mais cela pose un autre problème lorsque vous ne pouvez pas revenir à votre écran PreferenceScreen initial,
Une autre solution consiste à remplacer le fragment décrit ici Comment revenir en arrière du sous-écran Préférences vers l'écran principal dans PreferenceFragmentCompat?
Ceci est un exemple de travail complet, j'espère que cela sera utile à quelqu'un.Il couvre l'ouverture du sous-écran des préférences et le retour à l'écran principal des paramètres.
J'ai suivi ce problème dans Android Tracker Issue Tracker - ici
La documentation officielle ne contient pas la documentation pour le chargement des sous-écrans de préférences - Reportez-vous ici à la documentation officielle- -
L’écran principal des paramètres avancés contient 2 cases à cocher et un titre de sous-écran désactivé (paramètres de modèle personnalisés): -
Une fois que nous avons coché la case Personnalisé, le titre du sous-écran est activé .
En cliquant sur Paramètres du motif personnalisé, le sous-écran s'ouvre dans un nouvel écran.
Voici l'exemple de code avec documentation: -
Dans le fichier res/xml/preferences.xml: -
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:summary="Trying intro text">
<PreferenceCategory Android:title="Settings">
<CheckBoxPreference
Android:defaultValue="true"
Android:key="defaultPress"
Android:title="Default settings" />
<CheckBoxPreference
Android:defaultValue="false"
Android:key="customKey"
Android:title="Custom" />
<PreferenceScreen
Android:key="customPrefKey"
Android:title="Custom Pattern Settings">
<PreferenceCategory
Android:key="customSettingsKey"
Android:title="Custom Settings">
<ListPreference
Android:defaultValue="4"
Android:entries="@array/initialClickArray"
Android:entryValues="@array/initialClickValues"
Android:key="initialClicks"
Android:summary="initialClicksSummary"
Android:title="No. Of Clicks" />
<ListPreference
Android:defaultValue="5"
Android:entries="@array/initialTimeArray"
Android:entryValues="@array/initialTimeValues"
Android:key="initialTimeKey"
Android:summary="Time to complete clicks"
Android:title="Time to complete" />
</PreferenceCategory>
</PreferenceScreen>
</PreferenceCategory>
</PreferenceScreen>
MainActivity.Java doit implémenter l'interface PreferenceFragmentCompat.OnPreferenceStartScreenCallback
et ensuite remplacer la méthode-- onPreferenceStartScreen
public class MainActivity extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
private static final String TAG = MainActivity.class.getName();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = null;
if (savedInstanceState == null) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragment = new AdvancedSettingsFragment().newInstance("Advanced Setting");
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
}
@Override
public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat,
PreferenceScreen preferenceScreen) {
Log.d(TAG, "callback called to attach the preference sub screen");
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
AdvancedSettingsSubScreenFragment fragment = AdvancedSettingsSubScreenFragment.newInstance("Advanced Settings Subscreen");
Bundle args = new Bundle();
//Defining the sub screen as new root for the subscreen
args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, preferenceScreen.getKey());
fragment.setArguments(args);
ft.replace(R.id.fragment_container, fragment, preferenceScreen.getKey());
ft.addToBackStack(null);
ft.commit();
return true;
}
Pour l’écran principal Paramètres (fragment): -
public class AdvancedSettingsFragment extends PreferenceFragmentCompat {
private static final String TAG = AdvancedSettingsFragment.class.getName();
public static final String PAGE_ID = "page_id";
public static AdvancedSettingsFragment newInstance(String pageId) {
AdvancedSettingsFragment f = new AdvancedSettingsFragment();
Bundle args = new Bundle();
args.putString(PAGE_ID, pageId);
f.setArguments(args);
return (f);
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
final CheckBoxPreference customPreference = (CheckBoxPreference) findPreference("customKey");
final Preference customSettings = (Preference) findPreference("customPrefKey");
// First time loading the preference screen, we check the saved settings and enable/disable the custom settings, based on the custom check box
//get the customSettings value from shared preferences
if (getCustomSettings(getActivity())) {
customPreference.setChecked(true);
customSettings.setEnabled(true);
} else {
customPreference.setChecked(false);
customSettings.setEnabled(false);
}
customPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object selectedValue) {
Log.d(TAG, "Inside on preference change of custom checkbox selection " + selectedValue.getClass());
if ((Boolean) selectedValue) {
customSettings.setEnabled(true);
}else{
customSettings.setEnabled(false);
}
return true;
}
});
}
private boolean getCustomSettings(Context context) {
return PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean("customKey", false);
}
}
et enfin pour le chargement du sous-écran:
public class AdvancedSettingsSubScreenFragment extends PreferenceFragmentCompat {
private static final String TAG = AdvancedSettingsSubScreenFragment.class.getName();
public static final String PAGE_ID = "page_id";
public static AdvancedSettingsSubScreenFragment newInstance(String pageId) {
AdvancedSettingsSubScreenFragment f = new AdvancedSettingsSubScreenFragment();
Bundle args = new Bundle();
args.putString(PAGE_ID, pageId);
f.setArguments(args);
return (f);
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
// rootKey is the name of preference sub screen key name , here--customPrefKey
setPreferencesFromResource(R.xml.preferences, rootKey);
Log.d(TAG, "onCreatePreferences of the sub screen " + rootKey);
}
}
Une chose extrêmement importante dont vous avez besoin, vous vous en souvenez:
Votre écran Préférence doit contenir:
Android:key="name_a_unique_key"
Sinon, cela ne fonctionnera pas. J'ai passé des heures avec ça
Remplacer PreferenceFragmentCompat.OnPreferenceStartScreenCallback
et l'ajout de ce qui suit à mon fragment de préférence a sauvé ma journée
@Override
public Fragment getCallbackFragment() {
return this;
}
@Override
public boolean onPreferenceStartScreen(PreferenceFragmentCompat caller, PreferenceScreen pref) {
caller.setPreferenceScreen(pref);
return true;
}
Ma version de préférence est
compile 'com.Android.support:preference-v7:25.0.0'
Il semble que Google ait finalement décidé de supporter cela dans la nouvelle préférence AndroidX 1.1.0-alpha d'AndroidX.
Cette vidéo d'Android Dev Summit couvre quelque chose sur l'écran de préférence sous-écran.