KunMinX / Smooth-Navigation

提供流畅的 Jetpack Navigation 转场体验。并解决 GitHub 上 Navigation Add Hide 修改版普遍存在的缺陷。
253 stars 25 forks source link

launchSingleTop属性跳转页面问题 #11

Open hele-jeremy opened 3 years ago

hele-jeremy commented 3 years ago

<fragment android:id="@+id/DFragment" android:name="com.jlpay.navigation_lession.navigation_demo.case3.DFragment" android:label="DFragment" tools:layout="@layout/fragment_d"> <action android:id="@+id/action_DFragment_self" app:destination="@id/DFragment" app:launchSingleTop="true" />

launchSingleTop属性跳转页面在不同的手机上有不同的 表现,某些手机会闪一下,某些机型会直接显示上一级的 页面

原因为hide隐藏的其实就是DFragment,而add添加的fragment其实也是Dfragment因此在同一个FragmentTransation中隐藏和添加同一个Fragment会有问题的,if (mBackStack.size() > 0 && mFragmentManager.getFragments().size() > 0) { Log.d("Nav"," --Hide --Add"); ft.hide(mFragmentManager.getFragments().get(mBackStack.size() - 1)); ft.add(mContainerId, frag); } 我修改了FragmentNavigator的navigate方法相当是launchsingletop的情况下,不将新创建的fragmet入栈: public NavDestination navigate(@NonNull Destination destination, @Nullable Bundle args, @Nullable NavOptions navOptions, @Nullable Navigator.Extras navigatorExtras) { if (mFragmentManager.isStateSaved()) { Log.i(TAG, "Ignoring navigate() call: FragmentManager has already"

// ft.setPrimaryNavigationFragment(frag);

    boolean isAdded;
    if (initialNavigation) {
        isAdded = true;
    } 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( // generateBackStackName(mBackStack.size(), mBackStack.peekLast()), // FragmentManager.POP_BACK_STACK_INCLUSIVE); // ft.addToBackStack(generateBackStackName(mBackStack.size(), destId)); // } isAdded = false; } else { ft.addToBackStack(generateBackStackName(mBackStack.size() + 1, destId)); isAdded = true; } if (navigatorExtras instanceof Extras && !isSingleTopReplacement) { Extras extras = (Extras) navigatorExtras; for (Map.Entry<View, String> sharedElement : extras.getSharedElements().entrySet()) { ft.addSharedElement(sharedElement.getKey(), sharedElement.getValue()); } } ft.setReorderingAllowed(true); ft.commit(); // The commit succeeded, update our view of the world if (isAdded) { mBackStack.add(destId); return destination; } else { return null; } }

hele-jeremy commented 3 years ago

原生的navigation跳转页面时replace替换Fragment的因此launchSingleTop只能工作在自己跳转自己页面的情况,因此在原生的情况下,机制是launchSingleTop每次都会新建一个新的页面fragment实例,并将上一个自己页面的fragment实例给popupbackstatck 出栈并且将新创建的fragment页面实例给入栈,而改为了hide的机制后, launchSingleTop不应该将老的上一个页面给出栈,而是应该 继续保持老的fragment页面实例在栈中

KunMinX commented 3 years ago

@hele-jeremy 感谢你的分享,经测试,上述代码可实现预期效果,且在目前已知场景下皆未产生副作用, 为此可以邀请你 pull request 上述设计吗?这可以让你的这次分享出现在贡献名单中。开源不是一个人的战斗,我们希望每位贡献者都能出现在贡献者名单。

hele-jeremy commented 3 years ago

已提交pr