Android 导航弹出窗口和弹出窗口';他没有收拾残局

Android 导航弹出窗口和弹出窗口';他没有收拾残局,android,kotlin,navigation,android-jetpack,fragment-backstack,Android,Kotlin,Navigation,Android Jetpack,Fragment Backstack,我是Android Jetpack导航架构的新手。我正在一个新的应用程序上试用。有一个活动和几个片段,其中两个是登录屏幕和电子邮件登录屏幕。我在导航XML中定义了这些片段。应用程序的流程如下所示: 登录屏幕→ 电子邮件登录屏幕 我想要的是,在导航到电子邮件登录屏幕后,当我按back时,应用程序退出。这意味着登录屏幕的后台堆栈被删除。我知道登录屏幕不应该这样工作,但我仍然在想办法 我遵循了谷歌网站上的文档。它说,使用app:popUpTo和apppopuptinclusive=“true”应该可以

我是Android Jetpack导航架构的新手。我正在一个新的应用程序上试用。有一个活动和几个片段,其中两个是登录屏幕和电子邮件登录屏幕。我在导航XML中定义了这些片段。应用程序的流程如下所示:

登录屏幕
→ <代码>电子邮件登录屏幕

我想要的是,在导航到电子邮件登录屏幕后,当我按back时,应用程序退出。这意味着登录屏幕的后台堆栈被删除。我知道登录屏幕不应该这样工作,但我仍然在想办法

我遵循了谷歌网站上的文档。它说,使用
app:popUpTo
apppopuptinclusive=“true”
应该可以清除backbackback,但当我在电子邮件登录屏幕上按back时,它仍然返回登录,而不是退出

所以,我已经试过了

nav_main.xml

<fragment android:id="@+id/loginFragment"
          android:name="com.example.myapp.ui.main.LoginFragment"
          android:label="@string/login"
          tools:layout="@layout/fragment_login" >

    <action
        android:id="@+id/action_login_to_emailLoginFragment"
        app:destination="@id/emailLoginFragment"
        app:popEnterAnim="@anim/slide_in_right"
        app:popExitAnim="@anim/slide_out_right"
        app:popUpTo="@+id/emailLoginFragment"
        app:popUpToInclusive="true"/>

</fragment>

<fragment android:id="@+id/emailLoginFragment"
          android:name="com.example.myapp.ui.main.EmailLoginFragment"
          android:label="EmailLoginFragment"
          tools:layout="@layout/fragment_login_email" />
我给了一个按钮一个点击事件。在其中,我使用导航控制器导航到电子邮件登录屏幕,给它提供操作ID。在
中,有
app:popUpTo
app:popuptinclusive=“true”

在反复阅读文档以及大量StackOverflow问题之后,我发现这些属性应该将我的登录屏幕从后堆栈中移除。但他们没有。该按钮确实导航到电子邮件登录屏幕,但当我按back时,它仍然返回到登录屏幕,而不是退出应用程序。我遗漏了什么?


<action
        android:id="@+id/action_login_to_emailLoginFragment"
        app:destination="@id/emailLoginFragment"
        app:popEnterAnim="@anim/slide_in_right"
        app:popExitAnim="@anim/slide_out_right"
        app:popUpTo="@+id/loginFragment"
        app:popUpToInclusive="true"/>
您的弹出窗口将返回到电子邮件登录,然后由于包含而弹出它。
如果您将弹出窗口更改为您的登录片段,它将被导航回,并由于包含标志而弹出,这将导致您所需的行为。

这两行代码使技巧起作用:

如果您想从A转到B并希望完成A:

您需要通过此操作呼叫B:

    <fragment
        android:id="@+id/fragmentA"            
        tools:layout="@layout/fragment_a">

        <action
            android:id="@+id/action_call_B"
            app:destination="@+id/fragmentB"
            app:popUpTo="@id/fragmentA"
            app:popUpToInclusive="true" />

    </fragment>

    <fragment
        android:id="@+id/fragmentB"
        tools:layout="@layout/fragment_b">


    </fragment>


如果将日志放在片段中,您可以看到,通过此操作调用fragmentB后,fragmentA被销毁。

您可以使用XML执行此操作,就像这样,也可以通过编程方式执行此操作:

NavOptions navOptions = new NavOptions.Builder().setPopUpTo(R.id.loginRegister, true).build();
Navigation.findNavController(mBinding.titleLogin).navigate(R.id.login_to_main, null, navOptions);

假设您的应用程序有三个目的地—A、B和C—以及从A到B、B到C、C回到A的操作。相应的导航图如图所示

每个导航操作都会将目标添加到后堆栈中。如果要在该流中重复导航,那么后堆栈将包含每个目的地的多个集合(A、B、C、A、B、C、A等等)。为了避免这种重复,可以在将您从目标C带到目标A的操作中指定app:popUpTo和app:popuptinclusive,如下例所示:

<fragment
android:id="@+id/c"
android:name="com.example.myapplication.C"
android:label="fragment_c"
tools:layout="@layout/fragment_c">

<action
    android:id="@+id/action_c_to_a"
    app:destination="@id/a"
    app:popUpTo="@+id/a"
    app:popUpToInclusive="true"/>


到达目的地C后,后堆栈包含每个目的地(A、B、C)的一个实例。当导航回目的地A时,我们也会弹出A,这意味着我们在导航时会从堆栈中删除B和C。使用app:popuptinclusive=“true”,我们还从堆栈中弹出第一个A,有效地清除它。请注意,如果您不使用app:poputpinclusive,您的后堆栈将包含两个目标A的实例

谢谢,我感谢您的帮助。但是Rito已经给出了答案,我认为你的答案基本上是一样的。记住,如果你有一个片段链a->B->C->D,那么你需要在弹出操作参数中传递下面的内容,以使backPress行为退出。app:popUpTo=“@id/A”,app:popUpTo=“@id/B”,app:popUpTo=“@id/C”我认为这与接受的答案相同,但是通过编程完成的。不过很好。有一天我可能需要它。你能帮我做这个吗:,谢谢。。。。。我试图理解这个答案,但我不能。有人能给我解释清楚吗?@Fugogugo当你创建一个动作时,你可以添加
poputo
值。当您使用此操作导航到目的地并返回导航时,导航将带您返回到
poputo
片段,对于上面的代码示例,这就是
loginfracent
。设置
popuptinclusive=“true”
会告诉操作“当您返回导航时,请同时删除
popUpTo
中的片段”,因此它也会删除
loginFragment
。这有帮助吗?对我来说是有效的,但仍然有一个小故障,即在B片段上我仍然看到“向上arror按钮”-什么是不期望的?你能帮我做到这一点吗:,谢谢。记录在案。可以像使用它们一样使用登录片段。我不明白为什么“登录屏幕不应该以这种方式工作”@PanosGr你指的是“例如,如果你的应用程序有一个初始登录流,一旦用户登录,你应该从后台堆栈中弹出所有与登录相关的目的地,这样“后退”按钮就不会将用户带回登录流”?在我的例子中,用户还没有登录。它只是打开了一个不同的登录方法。通常,应允许用户返回主登录屏幕并选择不同的登录方法。
<fragment
android:id="@+id/c"
android:name="com.example.myapplication.C"
android:label="fragment_c"
tools:layout="@layout/fragment_c">

<action
    android:id="@+id/action_c_to_a"
    app:destination="@id/a"
    app:popUpTo="@+id/a"
    app:popUpToInclusive="true"/>