web-dev-qa-db-fra.com

Composant d'architecture de navigation - Écran d'accueil

J'aimerais savoir comment implémenter un écran de démarrage à l'aide du composant d'architecture de navigation.

Jusqu'à présent, j'ai quelque chose comme ça

 enter image description here

Un utilisateur doit configurer son profil dans ProfileFragment pour la première fois et peut modifier son profil depuis ChatFragment

Mon problème est que je ne sais pas comment supprimer SplashFragment de la pile après la navigation. J'ai vu navigation conditionnelle mais je n'ai pas bien compris. 

9
Yaswant Narayan

Je suivrais la réponse de @Sander, si vous avez besoin d’un écran Splash, vous devez le faire correctement - comme décrit ici avec le thème de l’application Splash et sansSplashFragment. Pour le mettre en œuvre, vous devez disposer d’un minimum de 2 La première activité est SplashActivity et la seconde est une activité qui hébergera votre NavHostFragment. Dans Manifest cela ressemblera à ceci:

    <activity Android:name=".ui.SplashActivity"
              Android:theme="@style/SplashTheme">
        <intent-filter>
            <action Android:name="Android.intent.action.MAIN"/>
            <category Android:name="Android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>

    <activity Android:name=".ui.MainActivity"/>

Votre SplashActivity n'aura qu'une méthode

class SplashActivity : AppCompatActivity() {

 override fun onStart() {
     super.onStart()
     startActivity<MainActivity>()
     finishAfterTransition() // use this instead of finish() to prevent flickering when SplashActivity has been finished but MainActivity stil hasnt been initialized
 }
}

Après cela, vous accédez à votre activité avec le composant de navigation et cette activité sera la nouvelle racine de votre tâche d'application. Un clic sur Précédent fermera donc l'application . </ S>

J'ai supprimé la solution avec SplashActivity car elle est redondante, nous pouvons faire tout ce dont nous avons besoin avec une seule activité. Pour mettre en place un écran Splash approprié, suivez this le tutoriel pointé par @Sander . En un mot, pour mettre en place un écran Splash, vous avez besoin de SplashTheme comme ceci:

<style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="Android:windowBackground">@drawable/splash_background</item>
</style>

splash_background drawable devrait être comme ceci:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android"
        Android:opacity="opaque"> <!-- Android:opacity="opaque" should be here -->
    <item>
        <!--this is your background, you can use color, gradient etc.-->
        <color Android:color="@color/colorPrimary"/>
        <!--<shape>
              <gradient
                   Android:angle="315"
                   Android:endColor="#1a82ff"
                   Android:startColor="#2100d3"
                   Android:type="linear"/>
        </shape> -->
    </item>
    <item>
        <bitmap Android:src="@drawable/ic_logo"
                Android:gravity="center"/>
    </item>
</layer-list>

Dans la Manifest, ajoutez simplement SplashTheme à votre activité:

<activity Android:name=".ui.MainActivity"
              Android:theme="@style/SplashTheme">

Puis, dans MainActivity pour revenir à votre AppTheme habituelle, faites ceci dans onCreate avant l'appel super:

override fun onCreate(savedInstanceState: Bundle?) {
    setTheme(R.style.AppTheme)
    super.onCreate(savedInstanceState)
    .....
1
Lemberg

Les écrans de démarrage ont toujours été étranges sur Android. Vous souhaitez uniquement afficher un écran de démarrage entre le fait de cliquer sur l'icône de l'application et la création de la première Activity. Si votre écran de démarrage est une Fragment, l'utilisateur verra toujours le fond blanc jusqu'à la création de la première Activity et le temps de démarrage de votre application augmentera, car un splash Fragment devra être créé et supprimé. La meilleure pratique consiste à utiliser une variable AppTheme, comme l'explique Ian Lake (ingénieur du cadre Android) dans cet article .

En ce qui concerne la navigation, votre application doit avoir une destination fixe qui est le premier et le dernier écran qu'un utilisateur voit lors de son entrée et de sa sortie, comme expliqué dans les principes de navigation . Dans votre cas, il serait logique de définir ChatFragment comme destination fixe. Dans la onCreate de la ChatFragment, vous devriez vérifier si l'utilisateur a déjà un profil et les rediriger vers la ProfileFragment à l'aide de navigation conditionnelle si ce n'est pas le cas.

12
Sander

Vous pouvez essayer ceci, cela fonctionne actuellement pour moi:

 <action
        Android:id="@+id/action_splashFragment_to_profileFragment"
        app:destination="@id/signInFragment"
        app:launchSingleTop="true"
        app:popUpTo="@id/splashFragment"
        app:popUpToInclusive="true" />

Il suffit de définir popUpTo (la destination actuelle) et popUpToInclusive (true) pour que tous les autres écrans s'affichent jusqu'à ce qu'ils atteignent la destination spécifiée. Indiquez également la destination si popUpToInclusive () est défini sur true avant de naviguer vers la nouvelle destination.

4
Po10cio

Voici deux façons de résoudre la situation ci-dessus.

One : Dans le NavHostFragment's Activity, remplacez la méthode onBackPress(), et si la NavDestination courante est MainFragment, alors finish() la Activity.

@Override
public void onBackPressed() {
    NavDestination navDestination = mNavController.getCurrentDestination();
    if (navDestination != null
            && navDestination.getId() == R.id.mainFragment) {
        finish();
        return;
    }
    super.onBackPressed();
}

Two: Définissez l'action sur MainFragment dans Navigation_graph app:popUpTo="@id/nav_graph" et app:popUpToInclusive="true"

<?xml version="1.0" encoding="utf-8"?>
<navigation
    Android:id="@+id/nav_graph"
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    app:startDestination="@id/splashFragment">

    <fragment
        Android:id="@+id/splashFragment"
        Android:name="xxx.fragment.splash.SplashFragment"
        Android:label="fragment_splash"
        tools:layout="@layout/fragment_splash">
        <action
            Android:id="@+id/action_splashFragment_to_mainFragment"
            app:destination="@id/mainFragment"
            app:enterAnim="@anim/anim_right_in"
            app:exitAnim="@anim/anim_left_out"
            app:popEnterAnim="@anim/anim_left_in"
            app:popExitAnim="@anim/anim_right_out"
            app:popUpTo="@id/nav_graph"
            app:popUpToInclusive="true"/>
        <action
            Android:id="@+id/action_splashFragment_to_guideFragment"
            app:destination="@id/guideFragment"
            app:enterAnim="@anim/anim_right_in"
            app:exitAnim="@anim/anim_left_out"
            app:popEnterAnim="@anim/anim_left_in"
            app:popExitAnim="@anim/anim_right_out"
            app:popUpTo="@id/nav_graph"
            app:popUpToInclusive="true"/>
    </fragment>

    <fragment
        Android:id="@+id/guideFragment"
        Android:name="xxx.fragment.guide.GuideFragment"
        Android:label="GuideFragment"
        tools:layout="@layout/fragment_guide">
        <action
            Android:id="@+id/action_guideFragment_to_mainFragment"
            app:destination="@id/mainFragment"
            app:enterAnim="@anim/anim_right_in"
            app:exitAnim="@anim/anim_left_out"
            app:popEnterAnim="@anim/anim_left_in"
            app:popExitAnim="@anim/anim_right_out"
            app:popUpTo="@id/nav_graph"
            app:popUpToInclusive="true"/>
    </fragment>

    <fragment
        Android:id="@+id/mainFragment"
        Android:name="xxx.fragment.main.MainFragment"
        Android:label="fragment_main"
        tools:layout="@layout/fragment_main">

    </fragment>

</navigation>

Souhait de l'aide!

Attention: ceci est obsolète. Dans Navigation alpha08, la balise clearTask est supprimée: Supprime les indicateurs clearTask et launchDocument déconseillés de NavOptions

Dans mon projet, je teste l'application: clearTask = "true" dans l'action, et cela fonctionne bien. ~~~

<fragment
    Android:id="@+id/splashFragment"
    Android:name="xxx.SplashFragment"
    Android:label="fragment_splash"
    tools:layout="@layout/fragment_splash">
    <action
        Android:id="@+id/action_splashFragment_to_mainFragment"
        app:destination="@id/mainFragment"
        app:enterAnim="@anim/anim_right_in"
        app:exitAnim="@anim/anim_left_out"
        app:popEnterAnim="@anim/anim_left_in"
        app:popExitAnim="@anim/anim_right_out"
        app:clearTask="true"/>
</fragment>
1
peerless2012

Vous pouvez essayer cette astuce, ça marche très bien pour moi . Créez votre écran de démarrage en tant qu’écran de lancement à partir du fichier de manifeste et démarrez votre activité d’hôte à partir de cet écran.

Manifest file code

`<activity Android:name=".SplashScreen"
          Android:theme="@style/Theme.AppCompat.Light.NoActionBar">
          <intent-filter>
              <action Android:name="Android.intent.action.MAIN" />
              <category Android:name="Android.intent.category.LAUNCHER" />
          </intent-filter>
</activity>`

Dans votre fichier Java 

         `new Handler().postDelayed(new Runnable(){
                    @Override
                    public void run() {
                        /* Create an Intent that will start the Navigation Host activity . */
                        Intent mainIntent = new Intent(getApplicationContext(), MainActivity.class);
                        startActivity(mainIntent);
                        finish();
                    }
                }, 5000);`

Code XML de votre activité d'accueil

`<?xml version="1.0" encoding="utf-8"?>
    Android.support.constraint.ConstraintLayout 
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    tools:context=".MainActivity">
          <fragment
                Android:id="@+id/nav_Host_fragment"
                Android:name="androidx.navigation.fragment.NavHostFragment"
                Android:layout_width="0dp"
                Android:layout_height="0dp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"
                app:defaultNavHost="true"
                app:navGraph="@navigation/navigation_graph" />
</Android.support.constraint.ConstraintLayout>`

Et votre navigation sera comme ça 

`<?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"
        xmlns:tools="http://schemas.Android.com/tools"
        Android:id="@+id/navigation_graph"
        app:startDestination="@id/homeFragment"
        >
      <fragment
         Android:id="@+id/homeFragment"
         Android:name="com.devgenesis.breaker.ice.navigationmproject.HomeFragment"
         Android:label="fragment_home"
         tools:layout="@layout/fragment_home" />
    </navigation>`
1
Arvind Rajput