एंड्रॉइड में किसी अन्य टुकड़े पर नेविगेट करने के बाद नेविगेशन स्टैक को कैसे साफ़ करें


121

मैं एंड्रॉइड में नए नेविगेशन आर्किटेक्चर घटक का उपयोग कर रहा हूं और मैं एक नए टुकड़े पर जाने के बाद नेविगेशन स्टैक को साफ करने में फंस गया हूं।

उदाहरण: मैं लॉगिनफ्रीगमेंट में हूं और मैं चाहता हूं कि जब मैं घर के टुकड़े पर नेविगेट करूं तो यह स्टैक से साफ हो जाए ताकि उपयोगकर्ता वापस लॉगिन पर वापस नहीं आएगा जब वह बैक बटन दबाएगा।

मैं नेविगेट करने के लिए एक सरल NavHostFragment.findNavController (टुकड़ा) का उपयोग कर रहा हूं । नेविगेट करने के लिए (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 का उपयोग करने की कोशिश की , लेकिन बैक बटन अभी भी मुझे लॉगिनफ्रीगमेंट में वापस भेज रहा है

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

आप बैकस्टैक प्रदान करने के लिए उपयोग कर सकते हैं popBackStackया नहीं जोड़ सकते हैं और इसे नए के साथ बदल सकते हैंLoginFragmentnulladdToBackStack(null);Fragment
युपी

कृपया अपनी पोस्ट को संपादित करें और उस कोड को जोड़ें जिसे आप अब नेविगेट करने के लिए उपयोग कर रहे हैं
बार्न्स

मैंने अपना प्रश्न संपादित किया और अपना कोड
यूसुफ एल बेहि

मुझे लगता है कि @ युपी ने एक अच्छा सुझाव दिया है। या आप इस navigate()तरह की विधि का उपयोग कर सकते हैं navigate(int resId, Bundle args, NavOptions navOptions)और NavOptionsअपने सीनेरियो को सबसे अच्छा फिट प्रदान कर सकते हैं
बार्न्स

मैंने The NavOptions का उपयोग करने की कोशिश की, लेकिन पिछला बटन अभी भी मुझे लॉगिन में वापस भेज रहा है
Youssef El

जवाबों:


179

सबसे पहले, विशेषताएँ 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)


1
ClearTask के रूप में सर्वश्रेष्ठ उत्तर अब Android नेविगेशन घटक के नए संस्करणों में पदावनत किया गया है!
मिचेल जाइब्रो

14
कोई भी एक्शन की आईडी का उपयोग कर सकता है जैसे किfindNavController(fragment).navigate(R.id.action_signInFragment_to_usersFragment)
कैलिन

1
बहुत बढ़िया! हालाँकि, अब मेरे पास बैक अप ग्लिफ़ है, लेकिन इसे दबाने से कुछ नहीं होता है। इसे हटाने के लिए एक साफ तरीका क्या है?
दानिश खान

6
मुझे लगता है कि इस उत्तर की कुंजी इसमें निहित है कि "popUpTo" (जो आपके वर्तमान टुकड़े के बीच के सभी टुकड़ों को हटा देता है और आईडी की पहली घटना जो आप इस तर्क से गुजरते हैं) को नेविगेशन ग्राफ की आईडी पर सेट कर दिया जाता है । प्रभावी रूप से बैकस्टैक को पूरी तरह से साफ़ करना। केवल इस टिप्पणी को जोड़ने के कारण मैंने इसे ठीक से इस तरह समझाया नहीं देखा है, और यह वही है जो मैं खोज रहा था। +1!
स्कॉट ओ'टोल

7
नोट : ऐसा नहीं है कि "निर्देश" वर्ग उत्पन्न नहीं होगा यदि आपने सुरक्षित-आर्गन को शामिल नहीं किया है। अधिक जानकारी के लिए यहाँ देखें
Jaydip Kalkani

28

मुझे लगता है कि आपका प्रश्न विशेष रूप से पॉप व्यवहार / पॉप टू / ऐप का उपयोग करने से संबंधित है: popUpTo (xml में)

प्रलेखन में,
नेविगेट करने से पहले किसी दिए गए गंतव्य तक पॉप करें। यह बैक-स्टैक से सभी गैर-मिलान वाले गंतव्यों को तब तक पॉप करता है जब तक कि यह गंतव्य नहीं मिल जाता।

उदाहरण (सिंपल जॉब हंटिंग ऐप)
मेरा 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"/>

XML के बजाय इस प्रोग्राम को कैसे करें?
इगोरगानापोलस्की

28

मेरे मामले में मुझे एक नया टुकड़ा खोलने से पहले बैक स्टैक में सब कुछ हटाने की आवश्यकता थी इसलिए मैंने इस कोड का उपयोग किया

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

पहली पंक्ति बैक स्टैक को हटाती है जब तक कि यह मेरे मामले में निर्दिष्ट टुकड़े तक नहीं पहुंचता है यह घर का टुकड़ा है, इसलिए यह सभी बैक स्टैक को पूरी तरह से हटा देता है, और जब उपयोगकर्ता वापस टुकड़े में क्लिक करता है तो वह ऐप बंद कर देता है।


1
क्या है fragment_apps??
इगोरगानापोलस्की

1
वर्तमान टुकड़ा। यह ऐसा है जैसे अगर आप अंश पर हैं और आप जाना चाहते हैं, तो आपको भी आवश्यकता है navController.popBackStack (R.id.fragmentOne, true) का उपयोग करें; navController.navigate (R.id.fragmentTwo);
बबेनी

14

नोट: स्पष्ट कार्य पदावनत है, आधिकारिक विवरण है

यह विधि पदावनत है। NavController के ग्राफ की आईडी के साथ setPopUpTo (int, बूलियन) का उपयोग करें और सही पर समावेशी सेट करें।

पुराना उत्तर

आप कोड के सभी कि फ़ज़्ज़ के माध्यम से जाना नहीं चाहता, तो आप बस की जांच कर सकते Clear Taskमें Launch Optionsकार्रवाई के गुणों में।

विकल्प लॉन्च करें

संपादित करें: एंड्रॉइड स्टूडियो 3.2 बीटा 5 के रूप में, लॉन्च टास्क विंडो में क्लियर टास्क अब दिखाई नहीं देता है, लेकिन आप इसे अभी भी नेविगेशन के XML कोड में, एक्शन टैग में जोड़कर उपयोग कर सकते हैं

app:clearTask="true"

आपको ग्राफ़ के मूल की आईडी का उपयोग करना चाहिए बजाय इसके कि क्लीयरटस्क xml एट्रिब्यूशन संदेश कहता है: "popUpTo को अपने ग्राफ के मूल में सेट करें और popUpToInclusive का उपयोग करें"। मैंने इसे इस तरह से किया है और findNavController () के साथ एक ही वांछित व्यवहार हासिल किया है। नेविगेट करें (@IdRes resId, बंडल)
आर्टनेस्ट

PopUpTo और popUpToInclusive को सेट करने के अनुशंसित दृष्टिकोण का उपयोग करना उन गंतव्यों के बीच की क्रियाओं के लिए काम नहीं करता है, जो आरंभिक गंतव्य हैं: जारीकर्ता। UIissues
116831650

मैं वास्तव में एक मुद्दे का सामना कर रहा हूं, जहां यह शुरुआत गंतव्य के साथ काम नहीं करता है, निराशा होती है।
मेल

यदि आप उस टुकड़े को नहीं जानते हैं जिसे आप पॉप करना चाहते हैं? उदाहरण के लिए मेरे पास एक टुकड़ा है जो एक नया आइटम बनाता है। बनाने के बाद मैं इस आइटम का विवरण दृश्य दिखाना चाहता हूं। लेकिन मैं यह नहीं चाहता कि उपयोगकर्ता बाद में खंड में, लेकिन पिछले दृश्य में वापस पॉप करे। यह या तो उन सभी वस्तुओं की सूची या अलग आइटम हो सकता है, जिस पर नया आधारित था। क्या तब केवल विकल्प साफ़ करें?
Findusl

नहीं, इसका वास्तव में उपयोग नहीं किया जाना चाहिए। इसके बजाय आपको समावेशी रूप से पॉपअप का उपयोग करना चाहिए। मैं अपने पॉपअप उपयोग के निष्कर्षों के साथ बहुत जल्द उत्तर को अपडेट करूंगा।
मेल

5

मैं अंत में यह पता लगाता हूं कि नए नेविगेशन आर्किटेक्चर कंपोनेंट के साथ कुछ अंशों के लिए नेविगेशन में यूपी को अक्षम कैसे करें?

मुझे एक नेविगेट के रूप में .setClearTask (सच) निर्दिष्ट करना था।

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());

                    }

                }
            });

2
खुशी है कि आप मेरे उपयोग के सुझाव को लागू करने में सक्षम थे navigate(int resId, Bundle args, NavOptions navOptions)औरNavOptions
बार्न्स

हाँ। धन्यवाद @ बार्न्स
यूसुफ एल

14
हाँ "सेटक्लेयरटस्क" पदावनत है, लेकिन इसके बजाय आप उपयोग कर सकते हैं:val navOptions = NavOptions.Builder().setPopUpTo(R.id.my_current_frag, true).build() findNavController().navigate(R.id.my_next_frag, null, navOptions)
पाब्लो रेयेस

1
@ सी-ए यह काम करना चाहिए। संभवतः आप एक गलत गंतव्य अंश का उपयोग कर रहे हैं (उदाहरण के R.id.my_next_fragलिए लॉगिन या स्प्लैश स्क्रीन की तरह हो सकता है); अगर आप सिर्फ एक को पॉपबैक करना चाहते हैं, तो आप इसका उपयोग कर सकते हैं NavHostFragment.findNavController(this).popBackStack():।
पाब्लो रेय्स

2
@PabloReyes यह सही उत्तर है। केवल यह निर्दिष्ट करें कि कौन सा टुकड़ा निकालने के लिए अंतिम है: मान लें कि आपके पास यह स्टैक है: Fragment_1 Fragment_2 Fragment_3 अब आप Fragment_3 पर हैं और Fragment_4 पर नेविगेट करना चाहते हैं और अन्य सभी टुकड़े साफ़ करें। बस नेविगेशन xml में निर्दिष्ट करें: ऐप: popUpTo = "@ id / Fragment_1" ऐप: popUpToInclusive = "true"
user3193413

5

यहाँ है कि मैं इसे कैसे कर रहा हूँ।

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

आपका समावेशी झंडा क्यों है false?
इगोरगानापोलस्की

2
प्रलेखन के अनुसार inclusive boolean: true to also pop the given destination from the back stack , इसलिए, मैंने समावेशी को झूठा सेट किया क्योंकि मैं वर्तमान खंड को स्टैक से पॉप नहीं करना चाहता।
अब्दुल रहमान शायर

4
    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);
    }

1

आप इस तरह आधार गतिविधि के पीछे दबाया ओवरराइड कर सकते हैं:

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()
  }

}

1

नोट: यह वास्तविक प्रश्न से संबंधित नहीं हो सकता है।

यह दृष्टिकोण उपयोगी होगा यदि नेविगेशन में बनाए रखने के लिए किसी खंड के एकल उदाहरण की आवश्यकता होती है ।

// imports
import androidx.navigation.navOptions

// navigate to fragment
navController.navigate(R.id.nav_single_instance_fragment, null,
                            navOptions {
                                popUpTo = R.id.nav_single_instance_fragment
                                launchSingleTop = true
                            })

यहां, navOptionsDSL है और आयात करने की आवश्यकता है। इस उत्तर के समय में मैं नेविगेशन UI के निम्न ग्रेड संस्करणों का उपयोग कर रहा हूं ।

    def nav_version = "2.2.0"
    implementation "androidx.navigation:navigation-ui:$nav_version"
    implementation "androidx.navigation:navigation-fragment:$nav_version"
    implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
    implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

0

मैं बैक बटन को अपनी शुरुआत के टुकड़े में वापस जाने से रोकने के लिए कुछ समय तक संघर्ष करता रहा, जो मेरे मामले में एक इंट्रो संदेश था जो केवल एक बार दिखाई देना चाहिए।

इसका आसान समाधान यह था कि उपयोगकर्ता को जिस स्थान पर रहना चाहिए, उसकी ओर इशारा करते हुए एक वैश्विक कार्रवाई का निर्माण करना चाहिए। आपको app:popUpTo="..."सही तरीके से सेट करना होगा - इसे उस स्थान पर सेट करें जहां आप पॉपअप करना चाहते हैं। मेरे मामले में यह मेरा परिचय संदेश था। भी निर्धारित किया हैapp:popUpToInclusive="true"


0

मैं इसे छोटे उदाहरण के माध्यम से समझा सकता हूं। मेरे पास दो टुकड़े कर्मचारी सूची हैं और कर्मचारी को हटा दें। हटाए गए कर्मचारी में, मेरे पास दो क्लिक ईवेंट रद्द करने और हटाने के लिए हैं। यदि मैं रद्द करता हूं, तो यह केवल कर्मचारियों की सूची स्क्रीन पर वापस आ जाता है और यदि मैं हटाता हूं तो मैं पिछले सभी बैकस्टैक को साफ करना चाहता हूं और कर्मचारियों की सूची स्क्रीन पर जाता हूं।

पिछली स्क्रीन पर जाने के लिए:

<action
        android:id="@+id/action_deleteEmployeeFragment_to_employeesListFragment2"
        app:destination="@id/employeesListFragment"/>


    btn_cancel.setOnClickListener {
                it.findNavController().popBackStack()
            }

पिछले सभी बैकस्ट को साफ़ करने और नई स्क्रीन पर जाने के लिए:

<action
        android:id="@+id/action_deleteEmployeeFragment_to_employeesListFragment2"
        app:destination="@id/employeesListFragment"
        app:popUpTo="@id/employeesListFragment"
        app:popUpToInclusive="true"
        app:launchSingleTop="true" />


 btn_submit.setOnClickListener {
                   it.findNavController().navigate(DeleteEmployeeFragmentDirections.actionDeleteEmployeeFragmentToEmployeesListFragment2())
        }

अधिक संदर्भ के लिए: जेटपैक नेविगेशन उदाहरण


0

आप के रूप में सरल कर सकते हैं:

getFragmentManager().popBackStack();

यदि आप उस गणना को जांचना चाहते हैं जो आप कर सकते हैं:

getFragmentManager().getBackStackEntryCount()
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.