web-dev-qa-db-fra.com

Navigation vers le fragment de préférence à l'aide du composant de navigation

J'essaie de migrer mon application de taille moyenne vers le nouveau composant Android navigation.

Actuellement, mon application se compose de single activity et je prévois de garder les mêmes (d'ailleurs); Donc, je suis confronté à ce problème dans lequel j'ai un fragment de paramètres (PreferenceFragment) qui peut être parcouru, essentiellement, à partir de tous les autres fragments. Cette navigation se fait via un menu dans la barre d'application, donc onOptionsItemSelected (contenant cette navigation) est dans l'activité principale.

Navigation graph

J'ai du mal à déterminer quelle est la bonne façon de connecter le settingsFragment aux autres. Le connecter à tous les autres me semble être un spaghetti.

  1. settingsFragment doit-il être connecté à tout autre fragment?

  2. Dois-je abandonner l'architecture d'application à activité unique, car Google ne donne pas suffisamment de raisons (ou aucune raison) pour la prendre en charge?

12
San Mo

Pour résoudre votre problème, vous pouvez utiliser global actions. Pour les utiliser, vous devez définir une action à l'intérieur de <navigation> tag, pas à l'intérieur <fragment> comme d'habitude. Votre graphique de navigation contiendra le code suivant

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto">

    <!--Your other fragments-->


    <!--Settings fragment-->
    <fragment
        Android:id="@+id/settingsFragment"
        Android:name="com.example.oleksii.stackoverflow.SettingsFragment"/>

    <!--Global action-->
    <action Android:id="@+id/open_settings_fragment"
        app:destination="@id/settingsFragment"/>
</navigation>

Dans l'éditeur de graphique, il sera affiché de la manière suivante (juste une flèche à gauche de destination):

enter image description here

Plus de détails: https://developer.Android.com/topic/libraries/architecture/navigation/navigation-global-action

10
Alexey Denysenko

mais si vos préférences sont hiérarchiques, vous obtenez Fragment <insert fragment name here> declared target fragment <guid> that does not belong to this FragmentManager! lorsque vous cliquez sur une préférence enfant.

je n'ai pas encore trouvé de solution à cela.

2
Simon Kenyon

Je peux naviguer vers un autre fragment ou fragment de préférence en utilisant l'approche suivante:

Fragment des paramètres globaux:

<PreferenceCategory
    app:title="@string/global_settings_header">
    <Preference
        app:key="fragment_a"
        app:title="A"
        app:fragment="....settings.SettingsFragmentA" />
    <Preference
        app:key="fragment_b"
        app:title="B"
        app:fragment=".....settings.SettingsFragmentB" />
</PreferenceCategory>

Mis en œuvre PreferenceFragmentCompat.OnPreferenceStartFragmentCallback en activité.

public class MainActivity extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
....

@Override
public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) {
    NavController navController = Navigation.findNavController(MainActivity.this, R.id.nav_Host_fragment);
    if (pref.getKey().equals("fragment_a")) {
        navController.navigate(R.id.nav_settings_fragment_a);
    } else if (pref.getKey().equals("fragment_b")) {
        navController.navigate(R.id.nav_settings_fragment_b);
    }
    return true;
}

....
}

Je peux également naviguer vers n'importe quel fragment défini dans le graphique de navigation à l'aide de NavController.

Tout fragment peut être utilisé dans app:fragment=".....settings.SettingsFragment". L'idée est de déclencher le callback onPreferenceStartFragment.

0
Patriotic

Pour s'appuyer sur la réponse de @Alexey, pour appeler l'action globale, vous pouvez utiliser du code comme celui-ci:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId();
    if (id == R.id.action_settings) {
        Navigation.findNavController(this, R.id.nav_Host_fragment).navigate(R.id.settingsFragment);
    }
    return super.onOptionsItemSelected(item);
}
0
jon