वहाँ एक तरीका है जब NewNontroller के साथ BottomNavigationView का उपयोग कर टुकड़े को जीवित रखने का है?


101

मैं नए नेविगेशन घटक का उपयोग करने का प्रयास कर रहा हूं। मैं नेवीकंट्रोलर के साथ एक बॉटनवीगेशन व्यू का उपयोग करता हूं: नेवीगेशनयूसेटअप विथ निथावनकंट्रोलर (बॉटनवीगेशन, नेकॉन्ट्रोलर)

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

क्या हमारे बचे हुए मुख्य अंशों को हमारे बॉटमवेशन व्यू के साथ जोड़कर रखना है?


3
जारीकर्ता की प्रति टिप्पणी के अनुसार। URLissues/80029773 यह प्रतीत होता है कि यह अंततः हल हो जाएगा। मैं भी उत्सुक हो सकता हूँ अगर लोगों को एक सस्ता काम है कि इस काम में अंतरिम करने के लिए पुस्तकालय का परित्याग शामिल नहीं है।
जिमी अलेक्जेंडर

जवाबों:


71

इसे इस्तेमाल करे।

नाविक

कस्टम नेविगेटर बनाएँ।

@Navigator.Name("custom_fragment")  // Use as custom tag at navigation.xml
class CustomNavigator(
    private val context: Context,
    private val manager: FragmentManager,
    private val containerId: Int
) : FragmentNavigator(context, manager, containerId) {

    override fun navigate(destination: Destination, args: Bundle?, navOptions: NavOptions?) {
        val tag = destination.id.toString()
        val transaction = manager.beginTransaction()

        val currentFragment = manager.primaryNavigationFragment
        if (currentFragment != null) {
            transaction.detach(currentFragment)
        }

        var fragment = manager.findFragmentByTag(tag)
        if (fragment == null) {
            fragment = destination.createFragment(args)
            transaction.add(containerId, fragment, tag)
        } else {
            transaction.attach(fragment)
        }

        transaction.setPrimaryNavigationFragment(fragment)
        transaction.setReorderingAllowed(true)
        transaction.commit()

        dispatchOnNavigatorNavigated(destination.id, BACK_STACK_DESTINATION_ADDED)
    }
}

NavHostFragment

कस्टम NavHostFragment बनाएँ।

class CustomNavHostFragment: NavHostFragment() {
    override fun onCreateNavController(navController: NavController) {
        super.onCreateNavController(navController)
        navController.navigatorProvider += PersistentNavigator(context!!, childFragmentManager, id)
    }
}

navigation.xml

खंड टैग के बजाय कस्टम टैग का उपयोग करें।

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/navigation"
    app:startDestination="@id/navigation_first">

    <custom_fragment
        android:id="@+id/navigation_first"
        android:name="com.example.sample.FirstFragment"
        android:label="FirstFragment" />
    <custom_fragment
        android:id="@+id/navigation_second"
        android:name="com.example.sample.SecondFragment"
        android:label="SecondFragment" />
</navigation>

गतिविधि लेआउट

NavHostFragment के बजाय CustomNavHostFragment का उपयोग करें।

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/nav_host_fragment"
        android:name="com.example.sample.CustomNavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/navigation" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/navigation" />

</androidx.constraintlayout.widget.ConstraintLayout>

अपडेट करें

मैंने सैंपल प्रोजेक्ट बनाया। संपर्क

मैं कस्टम NavHostFragment नहीं बनाता। मैं उपयोग करता हूं navController.navigatorProvider += navigator


3
जबकि यह समाधान काम करता है ( fragmentsपुन: उपयोग नहीं किया जाता है), नेविगेशन के साथ एक समस्या है। प्रत्येक menuitemको bottomnavigationviewप्राथमिक माना जाता है - इस प्रकार, जब BACKदबाया जाता है, तो ऐप खत्म हो जाता है (या शीर्ष घटक पर जाता है)। एक बेहतर समाधान YouTube ऐप की तरह ही व्यवहार करना होगा: (1) होम टैप करें; (२) टैप ट्रेंडिंग; (3) इनबॉक्स टैप करें; (4) टैप ट्रेंडिंग; (5) टैप BACK- इनबॉक्स में जाता है; (6) टैप BACK- होम पर जाता है; (7) टैप BACK- ऐप मौजूद है। सारांश में, BACK" menuitems" के बीच YouTube कार्यक्षमता आइटमों को दोहराए बिना, सबसे हाल ही में वापस जाती है।
मिगेल

3
बटन की कार्यक्षमता कैसे रखें? बैक बटन दबाने पर ऐप खत्म हो रहा है।
फ्रांसिस

5
@ jL4, मेरे पास एक ही मुद्दा था, शायद आप app:navGraphअपनी गतिविधि के NavHostFragment से निकालना भूल गए ।
पॉल चेर्नेंको

7
Google इस कार्यक्षमता को बॉक्स से बाहर क्यों नहीं करता है?
आर्सेनियस

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

24

Google नमूने लिंक अपने आवेदन में केवल नेविगेशनएक्स्टेंशन कॉपी करें और उदाहरण के लिए कॉन्फ़िगर करें। बहुत अच्छा काम करता है।


1
लेकिन यह केवल निचले नेविगेशन के लिए काम करता है। यदि आपके पास एक सामान्य नेविगेशन है, तो आपके पास एक समस्या है
जॉर्जी चेबटारेव

मैं एक ही मुद्दे का सामना कर रहा हूं और हर समाधान जो मैं जांचता हूं उसमें कोटलिन कोड शामिल है लेकिन मुझे डर है कि मैं अपने प्रोजेक्ट में जावा का उपयोग करता हूं। क्या कोई मेरी मदद कर सकता है कि इस मुद्दे को जावा में कैसे ठीक किया जाए।
कोडरेड इनोवेशन

@CodeREDInnovations मुझे भी, हालांकि मैं कोशिश की थी और kotlin फ़ाइल के साथ संकलित sucesfull इस तरह नेविगेशन रहता है: imgur.com/a/DcsKqPr यह "प्रतिस्थापित" नहीं करता है, उसके बगल में, ऐसा लगता है कि ऐप भारी और अटक गया है।
एकौआ पिटा

@ AcauãPitta आपने जावा में एक समाधान खोजा?
विकासबर्ग

@CodeREDInnovations हम java फ़ाइल में kotlin के साथ एक्सटेंशन फ़ंक्शंस का उपयोग कर सकते हैं। ऐसा करने के लिए, आपको कोटलिन को ग्रेडेल में कॉन्फ़िगर करने की आवश्यकता है, ऐसा लगता है कि यह सबसे इष्टतम तरीका है।
झखर रोडियनोव

11

कई घंटों के शोध के बाद मुझे इसका समाधान मिला। यह सब हमारे सामने सही समय था :) एक फ़ंक्शन है: popBackStack(destination, inclusive)जो बैकस्टैक में पाए जाने पर दिए गए गंतव्य पर नेविगेट करता है। यह बूलियन को लौटाता है, इसलिए हम वहां मैन्युअल रूप से नेविगेट कर सकते हैं यदि नियंत्रक को टुकड़ा नहीं मिलेगा।

if(findNavController().popBackStack(R.id.settingsFragment, false)) {
        Log.d(TAG, "SettingsFragment found in backStack")
    } else {
        Log.d(TAG, "SettingsFragment not found in backStack, navigate manually")
        findNavController().navigate(R.id.settingsFragment)
    }

1
यह कैसे और कहाँ उपयोग करें? अगर मैं फ्रैगमेंट ए से बी में नेविगेट करता हूं, तो बी से ए तक मैं oncraeteView () और onViewCreated () विधियों को कॉल किए बिना कैसे जा सकता हूं, संक्षेप में खंड ए को फिर से शुरू किए बिना
किशन सोलंकी

@UsamaSaeedUS: क्या आप कृपया कोड साझा कर सकते हैं, इसका उपयोग कैसे करें? जैसा किशन ने बताया।
कोड_लाइफ

2

यदि आपको तर्क पास करने में परेशानी होती है:

fragment.arguments = args

क्लास में KeepStateNavigator


1

अब तक उपलब्ध नहीं है।

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

आप अपने डेटा को जीवनचक्र के प्रति जागरूक करने के लिए LiveData का उपयोग कर सकते हैं


2
यह वास्तव में सच है, और डेटा> दृश्य लेकिन समस्या यह है कि जब आप व्यू स्टेट भी रखना चाहते हैं, जैसे कई पेज लोड किए गए हैं और उपयोगकर्ता ने नीचे स्क्रॉल किया है :)।
जोकिम ले

1

मैंने @STAR_ZERO द्वारा दिए गए लिंक का उपयोग किया है और यह ठीक काम करता है। जिन लोगों को बैक बटन की समस्या है, आप इसे इस तरह की गतिविधि / नेवी होस्ट में संभाल सकते हैं।

override fun onBackPressed() {
        if(navController.currentDestination!!.id!=R.id.homeFragment){
            navController.navigate(R.id.homeFragment)
        }else{
            super.onBackPressed()
        }
    }

बस जांचें कि क्या वर्तमान गंतव्य आपकी जड़ / घर का टुकड़ा है (आमतौर पर नीचे नेविगेशन दृश्य में पहला वाला), यदि नहीं, तो बस वापस टुकड़े पर नेविगेट करें, यदि हां, तो केवल ऐप से बाहर निकलें या जो चाहें करें।

Btw, इस सॉल्यूशन को Keep_state_fragment का उपयोग करके STAR_ZERO द्वारा प्रदान किए गए समाधान लिंक के साथ मिलकर काम करने की आवश्यकता है ।


1
idk क्यों लेकिन करंटडेंटिनेशन !!। id मुझे हमेशा सभी 3 अंशों के लिए समान मान दे रही है
अविषेक दास

1

@ Piotr-prus द्वारा प्रदान किए गए समाधान ने मेरी मदद की, लेकिन मुझे कुछ वर्तमान गंतव्य जांच को जोड़ना पड़ा:

if (navController.currentDestination?.id == resId) {
    return       //do not navigate
}

इस चेक के बिना वर्तमान गंतव्य को फिर से बनाना है यदि आप गलती से इसे नेविगेट करते हैं, क्योंकि यह बैक स्टैक में नहीं मिलेगा।


मुझे खुशी है कि मेरे समाधान ने आपके लिए काम किया। BottomNavigationView.setOnNavigationItemSelectedListener: मैं वास्तव में backStack से टुकड़ा बुला उपयोग करने से पहले bottomNavigationView में वर्तमान MENUITEM जाँच कर रहा हूँ
पिओर प्रस

-1

Android प्रलेखन के अनुसार ,

जब FragmentContainerView का उपयोग करके NavHostFragment बना रहा है या यदि मैन्युअल रूप से एक FragmentTransaction के माध्यम से अपनी गतिविधि में NavHostFragment जोड़ रहा है, तो नेविगेशन (onCreate) के माध्यम से एक गतिविधि के onCreate () (@IdRes int) में NavController को पुनः प्राप्त करने का प्रयास करेगा। आपको इसके बजाय सीधे NavHostFragment से NavController को पुनः प्राप्त करना चाहिए।

अपने nav_host_fragment को -> FragmentContainerView में बदलें और navController को फिर से बनाएँ

    val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController

आप इस दृष्टिकोण का उपयोग करके नेविगेशन घटकों के साथ टुकड़ा स्थिति को संरक्षित कर सकते हैं

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