35

我想知道如何使用导航架构组件实现启动画面。

直到现在我有这样的东西

在此处输入图像描述

用户必须ProfileFragment第一次设置他的个人资料,并且可以从 编辑他们的个人资料ChatFragment

我的问题是我不知道如何SplashFragment在导航后从堆栈中删除。我看过条件导航,但不太明白。

4

5 回答 5

43

当初始屏幕显示给用户几秒钟时,通常会误用启动屏幕,并且用户正在浪费时间查看启动屏幕,而他们已经可以与应用程序交互。取而代之的是,您应该尽快将它们带到可以与应用程序交互的屏幕上。因为之前的 Splash screen 在 android 上被认为是反模式。但后来谷歌意识到在用户点击图标和你的第一个应用屏幕准备好交互之间仍然存在短暂的窗口,在此期间你可以显示一些品牌信息。这是实现启动画面的正确方法。

因此,要以正确的方式实现 Splash screen,您不需要单独的 Splash Fragment,因为它会在 App 加载中引入不必要的延迟。要做到这一点,你只需要特殊的主题。理论上,App 主题可以应用于 UI 并在您的 App UI 初始化并变得可见之前变得可见。所以简而言之,你只需要SplashTheme这样:

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

splash_background可绘制应该是这样的:

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

无论如何,您的片段将托管在某些活动中,我们称之为MainActivty。在Manifest刚刚添加SplashTheme到您的活动中(从用户单击应用程序图标的那一刻起,它将显示启动屏幕主题):

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

然后在调用之前MainActivity返回您的常规AppTheme执行此操作:onCreatesuper

override fun onCreate(savedInstanceState: Bundle?) {
    setTheme(R.style.AppTheme)
    super.onCreate(savedInstanceState)
    .....
于 2019-02-18T22:50:11.620 回答
28

你可以试试这个,它目前对我有用:

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

只需设置popUpTo(the current destination)and popUpToInclusive(true),这将弹出所有其他屏幕,直到它到达指定的目的地 - 如果popUpToInclusive()设置为,也会弹出目的地true- 在导航到新目的地之前。

于 2018-10-02T14:48:07.747 回答
16

启动画面在 Android 上一直很奇怪。您只想在单击应用程序图标和创建第一个Activity. 如果您的启动画面是一个Fragment,用户在Activity创建第一个屏幕之前仍然会看到白色背景,并且您的应用程序的启动时间将增加,因为Fragment必须创建和删除启动画面。最佳实践是使用AppThemeIan Lake(Android 框架工程师)在这篇文章中解释的 Splash 。

至于导航,您的应用程序应该有一个固定的目的地,即用户在进入和退出您的应用程序时看到的第一个和最后一个屏幕,如导航原理中所述。ChatFragment在您的情况下,制作固定目的地是有意义的。在其中onCreateChatFragment您应该检查用户是否已经拥有个人资料,如果没有,则将他们重定向到ProfileFragment使用条件导航。

于 2018-07-05T11:39:23.507 回答
8

这里有两种方法可以解决上述情况。

:在NavHostFragment's Activity,重写onBackPress()方法,adn如果当前NavDestinationMainFragment那么finish()Activity.

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

:在 Navigation_graph 中设置到 MainFragment 操作app:popUpTo="@id/nav_graph"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>

希望得到帮助!

警告:这已被弃用。在 Navigation alpha08 中,删除了 clearTask 标记:Remove the deprecated clearTask and launchDocument flags from NavOptions

在我的项目中,我在action中测试了app:clearTask="true",效果很好~~~

<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>
于 2018-12-06T10:01:01.713 回答
2

你可以试试这个技巧,它对我来说绝对没问题。从清单文件中将您的启动屏幕设置为启动器屏幕,并从启动屏幕启动您的主机活动。

清单文件代码

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

在你的 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);

您的主机活动的 XML 代码

<?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:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/navigation_graph" />

</android.support.constraint.ConstraintLayout>

你的导航会是这样的

<?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>
于 2019-01-28T18:59:49.483 回答