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

时间:2018-09-24 14:40:10

标签: android android-architecture-components android-architecture-navigation

我要实现backpress行为,以便在您将backstack清空时按回车时会提示确认弹出窗口,否则它将弹出堆栈中的下一个片段。

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

main()

我想这应该可行,因为我检查了片段导航器的google代码,并且通过规范的片段事务将其添加到了堆栈中。

FragmentNavigator.java:

template <typename P = void>
class A {
public:
    void f1() {}
};

template<typename C>
void g() {}


int main() {
    A<> a;       // works
    A aa;        // works
    g<A<>>();    // works
    g<A>();      // fails
    return 0;
}

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

谢谢

6 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分:1)

也可能对某人有所帮助

<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

答案 2 :(得分:1)

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

第 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 

答案 3 :(得分:0)

我知道答案很晚。但这可能会帮助别人。

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

答案 4 :(得分:0)

在交易期间使用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;
   }
 } );

答案 5 :(得分:0)

嘿伙计们,如果您想删除 backstack,那么只需转到您的 nav_graph.xml 文件,然后转到您的 action 标签,写入 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