ViewPager刷新遇到的坑

今天写了个ViewPager+Fragment,切换,刷新Fragment数据的demo,写的吐血

1.

for (int i = 0; i < mCategoryEntityList.size(); i++) {
    DefualInfoFragment meFragment = new DefualInfoFragment();
    Bundle bundle = new Bundle();
    bundle.putString(Constant.CHANNEL_CODE, mCategoryEntityList.get(i).toString());
    meFragment.setArguments(bundle);
    fragments.add(meFragment);
}
adapter = new NewsPagerAdapter(getChildFragmentManager(), fragments);
mViewPager.setAdapter(adapter);

循环四个Fragment加到list中,到这里都没问题


这时候,我准备点击加号,改变Fragment的顺序


然后调用

notifyDataSetChanged()

我去,竟然没有用

百度发现,出现这种原因,是因为ViewPager具有缓存作用,他默认会缓存三个Fragment,当前,左边,右边

而且在adapter生成Fragment时,会给Fragment加上name


这样的作用就是,当你再点击这个Fragment时,它会去寻找它的name是否存在,如果没有就生成,存在就不会刷新

所以我改变的Fragment中List的顺序,并不能起到刷新的作用

知道原因,就可以很好的找到方法了

解决:

1.在adapter中修改

private int mChildCount = 0;

@Override
public void notifyDataSetChanged() {
    // 重写这个方法,取到子Fragment的数量,用于下面的判断,以执行多少次刷新
    mChildCount = getCount();
    super.notifyDataSetChanged();
}
@Override
public int getItemPosition(Object object) {
    if ( mChildCount > 0) {
        // 这里利用判断执行若干次不缓存,刷新
        mChildCount --;
        // 返回这个是强制ViewPager不缓存,每次滑动都刷新视图
        return POSITION_NONE;
    }
    // 这个则是缓存不刷新视图
    return super.getItemPosition(object);
}

这样每次都会刷新

2.在显示界面中

if (mViewPager.getAdapter() != null) {
    FragmentManager fm = getChildFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    List<Fragment> fragments = fm.getFragments();
    if (fragments != null && fragments.size() > 0) {
        for (int i = 0; i < fragments.size(); i++) {
            ft.remove(fragments.get(i));
        }
    }
    ft.commit();
}

fragments.clear();
for (int i = 0; i < mCategoryEntityList.size(); i++) {
    DefualInfoFragment meFragment = new DefualInfoFragment();
    Bundle bundle = new Bundle();
    bundle.putString(Constant.CHANNEL_CODE, mCategoryEntityList.get(i).toString());
    meFragment.setArguments(bundle);
    fragments.add(meFragment);
}

把缓存的Fragment去掉

注意:当布局是Fragment套Fragment时,用getChildFragmentManager,不能使用getSupportFragmentManager或getFragmentManager,这两个可以在Activity中使用

我遇到最坑爹的是,它竟然与MagicIndicator冲突,调用刷新,会导致页面空白

最终没有办法,我只能adapter

adapter = new NewsPagerAdapter(getChildFragmentManager(), fragments);
mViewPager.setAdapter(adapter);
commonNavigator.notifyDataSetChanged();
adapter.notifyDataSetChanged();

最后问题解决


当然,一般只需上面两段代码在用

adapter.notifyDataSetChanged();


就可以起到刷新作用了

我这个情况比较特殊,具体原因,也没有调查出来,有谁知道可以和我说一下,谢谢

<think>好的,用户想在Android的Fragment中编写新闻分类的导航栏。首先,我需要考虑常见的实现方式,比如使用ViewPager2和TabLayout的组合,这是比较标准的做法。用户可能需要一个可滑动的标签页来切换不同的新闻分类。 接下来,我应该分步骤来指导。首先,添加必要的依赖库,比如ViewPager2和Material Components库,确保build.gradle文件中包含这些依赖。然后,在布局文件中添加TabLayout和ViewPager2,说明如何将它们放在Fragment的布局里。 然后,需要创建Fragment的适配器,这里应该使用FragmentStateAdapter,并为每个标签页返回对应的新闻列表Fragment。用户可能不太清楚如何关联TabLayout和ViewPager2,所以需要说明使用TabLayoutMediator来绑定它们,并设置标签的标题。 另外,用户可能需要动态更改新闻分类,所以应该提到如何更新数据,比如修改适配器的数据源并通知数据变化。还需要考虑一些优化点,比如预加载页面数量,或者自定义标签的样式,比如字体大小和颜色。 需要检查是否有遗漏的步骤,比如布局文件的编写是否正确,或者在Fragment中的初始化过程是否正确。还要确保代码示例正确,比如Kotlin的语法,以及如何正确使用ViewBinding或者findViewById来获取控件。 可能用户会遇到的问题包括TabLayout和ViewPager2不联动,或者标签标题不显示,这时候需要强调正确使用TabLayoutMediator,并确保标题列表与Fragment的位置对应。另外,关于如何动态更新分类,可能需要更详细的说明,比如在数据变化时如何通知适配器刷新。 最后,总结关键点,确保用户能够按照步骤实现,并可以根据需要进行扩展和样式调整。还要提醒可能的性能优化和常见问题,帮助用户避免常见的。</think>在Android Fragment中实现新闻分类导航栏,推荐采用`ViewPager2`+`TabLayout`组合方案。以下是具体实现步骤: --- ### 一、添加依赖(build.gradle) ```gradle implementation 'androidx.viewpager2:viewpager2:1.0.0' implementation 'com.google.android.material:material:1.9.0' ``` --- ### 二、布局文件实现 ```xml <!-- fragment_news.xml --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.google.android.material.tabs.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary"/> <androidx.viewpager2.widget.ViewPager2 android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> </LinearLayout> ``` --- ### 三、创建Fragment适配器 ```kotlin class NewsPagerAdapter( fragment: Fragment, private val categories: List<String> ) : FragmentStateAdapter(fragment) { override fun getItemCount(): Int = categories.size override fun createFragment(position: Int): Fragment { return NewsListFragment.newInstance(categories[position]) } } ``` --- ### 四、初始化导航栏(在Fragment中) ```kotlin class NewsFragment : Fragment() { private lateinit var binding: FragmentNewsBinding override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { binding = FragmentNewsBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 初始化分类数据 val categories = listOf("头条", "科技", "体育", "财经", "娱乐") // 设置ViewPager适配器 val adapter = NewsPagerAdapter(this, categories) binding.viewPager.adapter = adapter // 关联TabLayout与ViewPager TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position -> tab.text = categories[position] }.attach() } } ``` --- ### 五、新闻列表Fragment实现 ```kotlin class NewsListFragment : Fragment() { companion object { private const val ARG_CATEGORY = "category" fun newInstance(category: String): NewsListFragment { val args = Bundle().apply { putString(ARG_CATEGORY, category) } return NewsListFragment().apply { arguments = args } } } // 这里实现具体新闻列表逻辑 } ``` --- ### 六、动态更新分类(可选) ```kotlin fun updateCategories(newCategories: List<String>) { val currentAdapter = binding.viewPager.adapter as? NewsPagerAdapter currentAdapter?.categories = newCategories currentAdapter?.notifyDataSetChanged() // 需要重写适配器的getItemId和containsItem方法处理数据集变化 } ``` --- ### 关键优化点: 1. **预加载策略**:通过`setOffscreenPageLimit`控制预加载页面数量 ```kotlin binding.viewPager.offscreenPageLimit = 2 ``` 2. **标签样式定制**: ```kotlin // 设置自定义标签布局 val tabView = LayoutInflater.from(context).inflate(R.layout.custom_tab, null) tab.textView?.textSize = 14f tab.textView?.setTextColor(ContextCompat.getColorStateList(context, R.color.tab_text)) ``` 3. **滑动动画禁用**(如果需要): ```kotlin binding.viewPager.isUserInputEnabled = false ``` --- ### 扩展方案对比 | 实现方式 | 优点 | 缺点 | |----------------|--------------------------|--------------------------| | ViewPager2 | 原生支持、手势流畅 | 复杂布局需要自定义 | | RecyclerView | 高度自定义布局 | 需自行实现切换逻辑 | | ScrollView | 实现简单 | 性能差、不支持动态更新 | 根据实际需求选择方案,常规推荐优先使用ViewPager2+TabLayout组合。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值