programing

Android에서 다른 조각으로 이동한 후 탐색 스택을 지우는 방법

batch 2023. 9. 13. 22:25
반응형

Android에서 다른 조각으로 이동한 후 탐색 스택을 지우는 방법

안드로이드에서 새로운 네비게이션 아키텍처 구성요소를 사용하고 있는데 새 조각으로 이동한 후 네비게이션 스택을 지우는 데 어려움을 겪고 있습니다.

예:저는 loginFragment에 있으며 홈 프래그먼트로 이동할 때 이 프래그먼트가 스택에서 지워져서 사용자가 뒤로 버튼을 누를 때 loginFragment로 되돌아가지 않기를 바랍니다.

간단한 NavHostFragment.findNavController(Fragment).navigate(R.id .homeFragment)를 사용하여 탐색하고 있습니다.

현재 코드:

mAuth.signInWithCredential(credential)
            .addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        NavHostFragment.findNavController(LoginFragment.this).navigate(R.id.homeFragment);
                    } else {
                        Log.w(TAG, "signInWithCredential:failure", task.getException());
                    }
                }
            });

탐색기()에서 NavOptions(탐색 옵션)를 사용하려고 했지만 뒤로 가기 버튼이 여전히 loginFragment(로그인 프래그먼트)로 돌아갑니다.

NavOptions.Builder navBuilder = new NavOptions.Builder();
NavOptions navOptions = navBuilder.setPopUpTo(R.id.homeFragment, false).build();   
             NavHostFragment.findNavController(LoginFragment.this).navigate(R.id.homeFragment, null, navOptions);

먼저속성추가app:popUpTo='your_nav_graph_id'그리고.app:popUpToInclusive="true"작업 태그로 이동합니다.

<fragment
    android:id="@+id/signInFragment"
    android:name="com.glee.incog2.android.fragment.SignInFragment"
    android:label="fragment_sign_in"
    tools:layout="@layout/fragment_sign_in" >
    <action
        android:id="@+id/action_signInFragment_to_usersFragment"
        app:destination="@id/usersFragment"
        app:launchSingleTop="true"
        app:popUpTo="@+id/main_nav_graph"
        app:popUpToInclusive="true" />
</fragment>

둘째, 위의 동작을 매개변수로 사용하여 대상으로 이동합니다.

findNavController(fragment).navigate(
     SignInFragmentDirections.actionSignInFragmentToUserNameFragment())

자세한 내용은 문서를 참조하십시오.

참고: 방법을 사용하여 탐색하는 경우navigate(@IdRes int resId), 원하는 결과를 얻지 못합니다.그래서 방법을 사용했습니다.navigate(@NonNull NavDirections directions).

당신의 질문은 구체적으로 Pop Behavior / Pop To / app:popUpTo (xml)를 어떻게 사용하는지에 관한 것이라고 생각합니다.

문서에서,
탐색하기 전에 지정된 대상으로 팝업이 나타납니다.이 대상을 찾을 때까지 백스택에서 일치하지 않는 대상을 모두 팝니다.

예제(Simple Job hunting 앱)
start_screen_nav 그래프는 다음과 같습니다.

startScreenFragment (start) -> loginFragment -> EmployerMainFragment

                            -> loginFragment -> JobSeekerMainFragment

내가 길을 찾고 싶다면EmployerMainFragment다음을 포함하여 모두 팝니다. startScreenFragment그러면 코드는 다음과 같습니다.

        <action
            android:id="@+id/action_loginFragment_to_employerMainFragment"
            app:destination="@id/employerMainFragment"

            app:popUpTo="@+id/startScreenFragment"
            app:popUpToInclusive="true" />

내가 길을 찾고 싶다면EmployerMainFragment를 제외하고 모두 팝니다. startScreenFragment그러면 코드는 다음과 같습니다.

        <action
            android:id="@+id/action_loginFragment_to_employerMainFragment"
            app:destination="@id/employerMainFragment"

            app:popUpTo="@+id/startScreenFragment"/>

내가 길을 찾고 싶다면EmployerMainFragment그리고 팝loginFragment그러나 그렇지는 startScreenFragment그러면 코드는 다음과 같습니다.

        <action
            android:id="@+id/action_loginFragment_to_employerMainFragment"
            app:destination="@id/employerMainFragment"

            app:popUpTo="@+id/loginFragment"
            app:popUpToInclusive="true"/>

오어

        <action
            android:id="@+id/action_loginFragment_to_employerMainFragment"
            app:destination="@id/employerMainFragment"

            app:popUpTo="@+id/startScreenFragment"/>

내 경우 새 조각을 열기 전에 백스택에 있는 모든 것을 제거해야 했기 때문에 이 코드를 사용했습니다.

navController.popBackStack(R.id.fragment_apps, true);
navController.navigate(R.id.fragment_company);

첫 번째 줄은 홈 프래그먼트이므로 모든 백스택을 완전히 제거하고 fragment_company에서 다시 클릭하면 앱을 닫습니다.

위의 내용들 중 어느 것도 제게 도움이 되지 않았기 때문에 여기에 또 다른 답변을 덧붙이겠습니다.탐색 그래프가 여러 개 있습니다.

findNavController().navigate(R.id.dashboard_graph,null,NavOptions.Builder().setPopUpTo(findNavController().graph.startDestination, true).build())

이것이 제가 전체 백스택을 성공적으로 클리어할 수 있는 유일한 방법이었습니다.구글은 정말로 이것을 더 간단하게 만들 필요가 있습니다.

참고: Clear task는 더 이상 사용되지 않습니다. 공식 설명은 다음과 같습니다.

이 메서드는 더 이상 사용되지 않습니다.NavController의 그래프 ID와 함께 setPopUpTo(int, boolean)를 사용하고 포함을 true로 설정합니다.

오래된 대답

코드의 모든 퍼지를 겪고 싶지 않다면, 당신은 그냥 확인해 볼 수 있습니다.Clear Task인에Launch Options그 행위의 성질상

Launch Options

편집: Android Studio 3.2 Beta 5 이후로 작업 지우기가 실행 옵션 창에 더 이상 표시되지 않지만 다음을 추가하여 내비게이션의 XML 코드, 작업 태그에 사용할 수 있습니다.

app:clearTask="true"
    NavController navController 
    =Navigation.findNavController(requireActivity(),          
    R.id.nav_host_fragment);// initialize navcontroller

    if (navController.getCurrentDestination().getId() == 
     R.id.my_current_frag) //for avoid crash
  {
    NavDirections action = 
    DailyInfoSelectorFragmentDirections.actionGoToDestionationFragment();

    //for clear current fragment from stack
    NavOptions options = new 
    NavOptions.Builder().setPopUpTo(R.id.my_current_frag, true).build();
    navController.navigate(action, options);
    }

네비게이션 아키텍처 구성요소로 일부 조각에 대해 네비게이션에서 UP을 비활성화하는 방법 덕분에 드디어 알게 되었습니다.

탐색 옵션으로 .setClearTask(true)를 지정해야 했습니다.

mAuth.signInWithCredential(credential)
            .addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "signInWithCredential:success");


                        NavOptions.Builder navBuilder = new NavOptions.Builder();
                        NavOptions navOptions = navBuilder.setClearTask(true).build();
                        NavHostFragment.findNavController(LoginFragment.this).navigate(R.id.homeFragment,null,navOptions);
                    } else {
                        Log.w(TAG, "signInWithCredential:failure", task.getException());

                    }

                }
            });

이 코드를 사용합니다.

navController.navigateUp();

그런 다음 새 프래그먼트 안드로이드 버전 4.1.2를 호출합니다.

제가 하는 방법은 이렇습니다.

 //here the R.id refer to the fragment one wants to pop back once pressed back from the newly  navigated fragment
 val navOption = NavOptions.Builder().setPopUpTo(R.id.startScorecardFragment, false).build()

//now how to navigate to new fragment
Navigation.findNavController(this, R.id.my_nav_host_fragment)
                    .navigate(R.id.instoredBestPractice, null, navOption)

위해서

// Navigation library
    def nav_version = "2.3.5"
    implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
    implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

이 솔루션은 저에게 적합합니다.

 
findNavController().popBackStack(R.id.<Current Fragment Id In NavGraph>, true)

 
findNavController().navigate(R.id.< Your Destination Fragment  in NavGraph>)

Navigation View(메뉴 드로어)와 함께 Navigation 구성 요소를 사용한 경우:

1.

mNavController.popBackStack(R.id.ID_OF_FRAGMENT_ROOT_TO_POP, true)
    mNavController.navigate(
      R.id.DESTINATION_ID,
      null,
      NavOptions.Builder()
                .setPopUpTo(R.id.POP_TO_DESTINATION_ID, true)
                .build()
    )

사이드 메뉴 드로어에서 로그아웃을 클릭한 후 스택을 지우고 싶었습니다.누군가에게 도움이 되었기를!

다음과 같이 기본 작업의 백 프레스를 재정의할 수 있습니다.

override fun onBackPressed() {

  val navigationController = nav_host_fragment.findNavController()
  if (navigationController.currentDestination?.id == R.id.firstFragment) {
    finish()
  } else if (navigationController.currentDestination?.id == R.id.secondFragment) {
    // do nothing
  } else {
    super.onBackPressed()
  }

}

위의 어떤 해결책도 제게 도움이 되지 않습니다.몇 시간을 들인 후 해결책은 다음과 같습니다.

참고: 여러 개가 있습니다.nav_graphs서로 다른 조각들 사이에서 전환하는 것.nav_graphs.

  1. xml에서 아래와 같이 작업을 정의합니다.
<action
    android:id="@id/your_action_id"
    app:destination="@id/the_fragment_id_you_want_to_navigate_to"
    app:popUpTo="@id/nav_graph_which_contains_destination_fragment"
    app:popUpToInclusive="true" />
  1. Java/Kotlin 코드에서 위의 작업을 사용하여 탐색합니다.
findNavController(R.id.your_nav_name)?.apply {
    navigate(R.id.your_action_id)
    backQueue.clear()
}

Jetpack 구성요소 ❤️

navHostController.navigate(Routes.HOME) {
                            this.popUpTo(Routes.ONBOARDING) {
                                this.inclusive = true
                            }
                     }

나는 백 버튼이 내 시작 조각으로 돌아가는 것을 막기 위해 한동안 애를 먹었습니다. 그것은 내 경우에는 한 번만 나타나야 하는 인트로 메시지였습니다.

쉬운 해결책은 사용자가 머물러야 할 목적지를 가리키는 글로벌 액션을 만드는 것이었습니다.설정해야 합니다.app:popUpTo="..."올바르게 - 팝업할 대상으로 설정합니다.저 같은 경우는 제 인트로 메시지였습니다.세트도app:popUpToInclusive="true"

저 같은 경우에는 각자의 탐색 그래프가 있는 두 가지 활동을 사용하고 있습니다.저의 첫 번째 활동은 "nav_graph"의 호스트이며 인증을 다루는 프래그먼트를 가지고 있고 두 번째 활동은 "nav_graph_home"의 호스트입니다.nav_graph에 대한 설정을 확인하실 수 있습니다.

nav_graph 예제

1

로그인 프래그먼트에 대한 코드를 다시 입력하면 다음과 같이 적을 수 있습니다.

findNavController().navigate(R.id.action_logInFragment_to_nav_graph_home)

사용자가 로그인한 후 뒤로 버튼을 누르면 앱이 닫힙니다.팝업을 포함하지 않고 로그인 조각이 포함된 현재 탐색 그래프로 팝업이 뜨도록 설정해야 합니다.

편집: 이 후에도 위쪽 단추가 위쪽 막대에 계속 나타납니다.이러한 행동을 피하기 위해서는 첫 번째 활동에서 어떤 단편이 최상위 수준으로 간주되는지를 알려주어야 합니다.이렇게 하려면 첫 번째 탐색 그래프와 두 번째 탐색 그래프의 홈 조각 집합을 포함하는 앱바 구성을 탐색 호스트 조각과 함께 "setupActionBarWithNavController()" 메서드의 매개 변수 목록에 추가하면 됩니다.코드는 다음과 같습니다.

class MainActivity : AppCompatActivity(R.layout.activity_main) {
private lateinit var navController: NavController

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // Retrieve NavController from the NavHostFragment
    val navHostFragment = supportFragmentManager
        .findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    navController = navHostFragment.navController

    // Set up the action bar for use with the NavController
    setupActionBarWithNavController(navController, AppBarConfiguration(setOf(R.id.logInFragment,R.id.homeFragment)))
}

/**
 * Handle navigation when the user chooses Up from the action bar.
 */
override fun onSupportNavigateUp(): Boolean {
    return navController.navigateUp() || super.onSupportNavigateUp()
}

}

이것은 제 생애 첫 기부입니다. 이것이 도움이 되기를 바랍니다.

위해서androidx.compose버전 1.2.0+

하위 버전에 몇 가지 문제가 있었지만 1.2 플러스(이 글을 쓸 당시 베타)는 완벽하게 작동합니다.

구성에서 navGraph에 대한 구문 개선:

navController.navigate(item.name) {

    navController.graph.startDestinationRoute?.let { route ->
        // use saveState = false to NOT save the state for the popped route
        popUpTo(route) { saveState = true }
    }

    launchSingleTop = true

    restoreState = true
}

버튼을 사용하여 다른 fragment로 이동하고 있으므로 각 버튼에서 이 작업을 수행합니다.

 val navOptions = NavOptions.Builder().setLaunchSingleTop(true).setPopUpTo(R.id.homeFragment, false).build()
 findNavController(R.id.mainNavHostFragment).navigate(R.id.destination, null, navOptions)

프로그래밍 방식으로 작업을 수행할 때는 다음과 같은 방법으로 작업을 계속할 수 있습니다.

           findNavController().navigate(

                //your navigation direction
                R.id.action_fragmentB_to_fragmentC,

                //pass arguments if you have, else null
                null,

                //Pass the fragment id where you want to land on the back press at fragmentC,
                //true/false, in case you want to remove the fragmentA from the back stack use the TRUE and vice versa 
                NavOptions.Builder().setPopUpTo(R.id.fragmentA, true).build() 
            )

또한 아래 스크린샷과 같이 네비게이션 그래프 XML에서 다음과 같은 방법으로 달성할 수 있습니다.

enter image description here

베스트 프랙티스는 아니지만 나에게는 효과가 있습니다 (Kotlin/Fragment)

while (findNavController().navigateUp()){findNavController().popBackStack()}
findNavController().navigate(R.id.other_fragment)

다음과 같이 간단하게 수행할 수 있습니다.

getFragmentManager().popBackStack();

카운트를 확인하려면 다음 작업을 수행할 수 있습니다.

getFragmentManager().getBackStackEntryCount()

언급URL : https://stackoverflow.com/questions/50514758/how-to-clear-navigation-stack-after-navigating-to-another-fragment-in-android

반응형