繁体   English   中英

使用android导航组件获取Backstack状态

[英]Get Backstack status using android navigation component

我想实现 backpress 行为,这样当你在 backstack 为空的情况下按下时它会提示一个确认弹出窗口,否则它会弹出堆栈中的下一个片段。

我正在尝试获取 backstack 计数,但我总是从两个片段管理器中获取 0

 getSupportFragmentManager().getBackStackEntryCount();
 getFragmentManager().getBackStackEntryCount();

我想它应该可以工作,因为我检查了片段导航器的谷歌代码,它通过规范片段事务添加到后台堆栈:

FragmentNavigator.java:

 if (initialNavigation || isClearTask) {
        backStackEffect = BACK_STACK_DESTINATION_ADDED;
    } else if (isSingleTopReplacement) {
        // Single Top means we only want one instance on the back stack
        if (mBackStack.size() > 1) {
            // If the Fragment to be replaced is on the FragmentManager's
            // back stack, a simple replace() isn't enough so we
            // remove it from the back stack and put our replacement
            // on the back stack in its place
            mFragmentManager.popBackStack();
            ft.addToBackStack(Integer.toString(destId));
            mIsPendingBackStackOperation = true;
        }
        backStackEffect = BACK_STACK_UNCHANGED;
    } else {
        ft.addToBackStack(Integer.toString(destId));
        mIsPendingBackStackOperation = true;
        backStackEffect = BACK_STACK_DESTINATION_ADDED;
    }
    ft.setReorderingAllowed(true);
    ft.commit();

我也没有找到任何 API 来通过 NavController 或 Navigator 检索此信息。

谢谢

也可能对某人有帮助:

<fragment
    android:id="@+id/YOUR_NAVIGATION_HOST_ID"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="true"
    app:navGraph="@navigation/YOUR_NAVIGATION_HOST" />
val navHostFragment = supportFragmentManager.findFragmentById(R.id.YOUR_NAVIGATION_HOST_ID)
val backStackEntryCount = navHostFragment?.childFragmentManager?.backStackEntryCount

要检查导航主机片段的返回堆栈计数,您应该使用 navHostFragment 的 childFragmentManager :

navHostFragment.childFragmentManager.addOnBackStackChangedListener {
            if (navHostFragment.childFragmentManager.backStackEntryCount == 0) {
                // First fragment is open, backstack is empty
            } else {
                // there are fragments in backstack
            }
        }

我的应用程序中也有相同的用例,但我这边的场景非常复杂。 因为我做了一个基础片段,每个片段都需要继承它。否则你需要在每个片段中添加相同的代码。 所以 -

第 1 步:创建BaseFragment并添加

    public class BaseFragment extends Fragment{
    .
    .
    .
    .
     @Override
        public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
    
        
           requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(),
                    new OnBackPressedCallback(true) {
                        @Override
                        public void handleOnBackPressed() {
                           goBack();
                        }
                    });
    
        }
    private void goBack(){
     NavHostFragment navHostFragment = (NavHostFragment) this.getParentFragment();
            /**If navHostFragment has no fragment in stack that means you reach to the top most fragment on the stack and app exist popup should be shown here.Otherwise just simple pop the immediate fragment from backstack*/
            if (navHostFragment != null &&
                    navHostFragment.getChildFragmentManager().getBackStackEntryCount() == 0) {
                showAppExistPopup(); 
            } else NavHostFragment.findNavController(this).navigateUp();
    
    }
    .
    .
    .
}

第 2 步:只需简单地通过上述基本片段继承您的子片段类,例如 -

public class MyChildFragment extends BaseFragment 

我知道答案迟了。 但也许它会帮助别人。

val navHostFragment = supportFragmentManager.findFragmentById(R.id.navDrawerActivity)
val backStackEntryCount = navHostFragment?.childFragmentManager?.fragments?.size
<fragment
    android:id="@+id/navDrawerActivity"
    android:name="androidx.navigation.fragment.NavHostFragment"
    app:navGraph="@navigation/nav_item"
    app:defaultNavHost="true"
/>

在事务期间使用addToBackStack()方法可以解决问题,

FragmentTransaction tx = fragmentManager.beginTransation();
tx.replace( R.id.fragment, new MyFragment() ).addToBackStack( "tag" ).commit();


//You need to add the following line for this solution to work; 
fragment.getView().setFocusableInTouchMode(true);
fragment.getView().requestFocus();
fragment.getView().setOnKeyListener( new OnKeyListener(){
@Override
public boolean onKey( View v, int keyCode, KeyEvent event )
  {
    if( keyCode == KeyEvent.KEYCODE_BACK )
    {
        return true;
    }
    return false;
   }
 } );

嘿伙计们,如果您想删除后台堆栈,那么只需转到您的nav_graph.xml文件,然后转到您的操作标签,编写popUpToInclusive="true" ,然后编写popUpTo="@id/splashScreen" (此处传递该屏幕的 id ,您想删除它,在我的情况下它是 splashScreen)。 检查下面的代码以更好地理解..

    <fragment
        android:id="@+id/splashScreen"
        android:name="com.codingwithjks.firebase.SplashScreen"
        android:label="splash_screen"
        tools:layout="@layout/splash_screen" >
        <action
            android:id="@+id/action_splashScreen_to_showUploads"
            app:destination="@id/showUploads"
            app:popUpToInclusive="true"
            app:popUpTo="@id/splashScreen"
            app:enterAnim="@anim/nav_default_pop_enter_anim" />
    </fragment

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM