Navigation配合BottomNavigationView作Home页面,当点击底部同一导航按钮,界面会发生闪烁,问题原因在于:
在Navigation框架中,每次Fragment的navigate跳转,都是采用replace方法,这将导致界面闪烁。
源代码如下:FragmentNavigator.class
我们期望的是,如果目标页面跟当前页面一致,就不加载新的页面实例。这也是我们今天所要解决的问题。
这种解决办法有很多:
一、从BottomNavigationView入手
包括以下2种方案:
1.1、设置OnNavigationItemReselectedListener监听
从源代码入手分析:
//代码在BottomNavigationView的构造方法中
this.menu.setCallback(
new MenuBuilder.Callback() {
@Override
public boolean onMenuItemSelected(MenuBuilder menu, @NonNull MenuItem item) {
if (reselectedListener != null && item.getItemId() == getSelectedItemId()) {
reselectedListener.onNavigationItemReselected(item);
return true; // item is already selected
}
return selectedListener != null && !selectedListener.onNavigationItemSelected(item);
}
@Override
public void onMenuModeChange(MenuBuilder menu) {}
});
这里可以发现,只要让reselectedListener
不等于空,重复点击BottomNavigationView时,事件将不会传递给selectedListener
的onNavigationItemSelected
方法,也就不会让Navigation发生跳转。
这是我最推荐的方案,代码入侵最小:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mNavTab = findViewById(R.id.nav_tab)
controller = findNavController(R.id.nav_host)
mNavTab.setupWithNavController(controller)
//加这一句
mNavTab.setOnNavigationItemReselectedListener { }
}
1.2、重写setOnNavigationItemSelectedListener方法
仿造NavigationUI.setupWithNavController(bottomNavigationView, navController)
方法,在OnNavigationItemSelectedListener
监听事件中,增加一个判断逻辑。
二、配合ViewModel使用
这种方式是Google所推崇的,它能保证Fragment被销毁后,数据依然有效,只要将数据展示在新的Fragment上,就能让用户觉得一切都未改变。虽然这种方式,能够解决数据重复加载的问题,但界面闪烁,列表当前位置丢失等问题,也没有实质性的改变。
三、修改FragmentNavigator
这种方式又分两种:
3.1、重写navigate方法
将replace修改成hide、show方法,实现过程较为复杂。这里就不详细展开了。
3.2、重写instantiateFragment方法
如果当前Fragment跟目标Fragment类型一致,就不创建新的实例,而是直接返回当前Fragment。
实现过程如下:
1、主布局中去掉graphId,因为我们后续会手动添加
2、创建FixedFragmentNavigator类
@Navigator.Name("fragment")
public class FixedFragmentNavigator extends FragmentNavigator {
private final int mContainerId;
public FixedFragmentNavigator(@NonNull Context context, @NonNull FragmentManager manager, int containerId) {
super(context, manager, containerId);
mContainerId = containerId;
}
@NonNull
@Override
public Fragment instantiateFragment(@NonNull Context context, @NonNull FragmentManager fragmentManager, @NonNull String className, @Nullable Bundle args) {
Fragment fragment = fragmentManager.findFragmentById(mContainerId);
if (fragment != null) {
String name = fragment.getClass().getName();
if (className.equals(name)) {
return fragment;
}
}
return super.instantiateFragment(context, fragmentManager, className, args);
}
}
3、将FixedFragmentNavigator替换掉默认的FragmentNavigator,再设置navGraph。
四、修改FragmentFactory
这种方法一般是用来配合Dagger2或Hilt实现依赖注解,其原理是将Fragment创建交到自己手里。
修改代码如下:
public class FixNavHostFragment extends NavHostFragment {
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
FragmentManager childFragmentManager = getChildFragmentManager();
childFragmentManager.setFragmentFactory(new ReuseFragmentFactory(childFragmentManager));
}
static class ReuseFragmentFactory extends FragmentFactory {
private final FragmentManager mFragmentManager;
ReuseFragmentFactory(FragmentManager fragmentManager) {
this.mFragmentManager = fragmentManager;
}
@NonNull
@Override
public Fragment instantiate(@NonNull ClassLoader classLoader, @NonNull String className) {
Fragment primaryFragment = mFragmentManager.getPrimaryNavigationFragment();
if (primaryFragment != null && className.equals(primaryFragment.getClass().getName())) {
return primaryFragment;
}
return super.instantiate(classLoader, className);
}
}
}
然后在布局文件中,将NavHostFragment替换为FixNavHostFragment即可。
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/19458,转载请注明出处。
评论0