当前位置: 首页 > ds >正文

在新闻资讯 APP 中添加不同新闻分类页面,通过 ViewPager2 实现滑动切换

在新闻资讯 APP 中添加不同新闻分类页面,通过 ViewPager2 实现滑动切换

核心组件的作用

  • ViewPager2:是 ViewPager 的升级版,基于RecyclerView实现,支持水平 / 垂直滑动、RTL(从右到左)布局,且修复了 ViewPager 的诸多缺陷(如 notifyDataSetChanged 不生效、滑动冲突等)。
  • Fragment:可复用的 UI 组件,作为 ViewPager2 的 “页面” 内容,每个滑动页面对应一个 Fragment 实例。
  • FragmentStateAdapter:ViewPager2 的适配器,专门用于管理 Fragment 与 ViewPager2 的绑定,负责创建、销毁 Fragment,类似 RecyclerView 的 Adapter。
  • TabLayout(可选):通常与 ViewPager2 配合使用,显示标签标题,实现 “标签点击切换 + 滑动切换” 的联动效果。

开发步骤

1.引入依赖

ViewPager2 属于 AndroidX 库,需在build.gradle(Module 级别)中添加依赖(确保版本兼容):

dependencies {// ViewPager2核心依赖implementation "androidx.viewpager2:viewpager2:1.0.0"// Fragment依赖(若已引入AndroidX Fragment可忽略)implementation "androidx.fragment:fragment-ktx:1.5.6"// (可选)TabLayout联动依赖(与ViewPager2配合)implementation "com.google.android.material:material:1.9.0"
}
2.创建Fragment页面

每个滑动页面对应一个 Fragment,需创建多个 Fragment(如首页、推荐、我的等)。
以 "首页"页面为例:

 @NonNull@Overridepublic ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = LayoutInflater.from(context).inflate(R.layout.item_recommend_user, parent, false);return new ViewHolder(view);}

每个 Fragment 对应一个布局文件(如fragment_home.xml),仅需简单的 UI 内容即可。

3.自定义一个ViewPage2布局

在 Activity 的布局文件中添加 ViewPager2,若需要标签页,可搭配 TabLayout:

我这里把之前写的recyclerView给改成了ViewPage2,用来实现页面的切换

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><!-- 顶部区域:搜索框 + 分类栏 --><LinearLayoutandroid:id="@+id/top_container"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:elevation="4dp"app:layout_behavior=".util.ScrollAwareFABBehavior"><!-- 搜索栏 --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:background="#D3D3D3"android:padding="8dp"android:elevation="2dp"><EditTextandroid:id="@+id/search_edit_frame"android:layout_width="0dp"android:layout_height="40dp"android:layout_weight="3"android:background="@drawable/search_bg"android:paddingHorizontal="12dp"android:singleLine="true" /><Buttonandroid:id="@+id/button"android:layout_width="0dp"android:layout_height="40dp"android:layout_weight="1"android:text="搜索"android:backgroundTint="#4CAF50"android:textColor="@android:color/white" /></LinearLayout><!-- 分类栏 --><LinearLayoutandroid:id="@+id/category_bar"android:layout_width="match_parent"android:layout_height="50dp"android:orientation="horizontal"android:background="@android:color/white"android:elevation="1dp"><TextViewandroid:id="@+id/tab_hot"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:text="热榜"android:textSize="16sp"android:textColor="#333333"android:gravity="center"android:clickable="true"android:background="?attr/selectableItemBackground" /><TextViewandroid:id="@+id/tab_follow"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:text="关注"android:textSize="16sp"android:textColor="#333333"android:gravity="center"android:clickable="true"android:background="?attr/selectableItemBackground" /><TextViewandroid:id="@+id/tab_recommend"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:text="推荐"android:textSize="16sp"android:textColor="#333333"android:gravity="center"android:clickable="true"android:background="?attr/selectableItemBackground" /><TextViewandroid:id="@+id/tab_city"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:text="同城"android:textSize="16sp"android:textColor="#333333"android:gravity="center"android:clickable="true"android:background="?attr/selectableItemBackground" /></LinearLayout></LinearLayout><!-- ViewPager2容器 --><androidx.viewpager2.widget.ViewPager2android:id="@+id/view_pager"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginTop="?attr/actionBarSize" /><!-- 底部导航栏(保持原设计) --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:padding="8dp"android:background="#FFFFFF"android:layout_gravity="bottom" ><!-- 首页 --><LinearLayoutandroid:id="@+id/home_tab"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="vertical"android:gravity="center"><ImageViewandroid:layout_width="25dp"android:layout_height="25dp"android:layout_gravity="center_horizontal"android:src="@drawable/main"android:contentDescription="首页图标"/><TextViewandroid:id="@+id/home_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16dp"android:text="首页"android:gravity="center_horizontal"/></LinearLayout><!-- 菜单 --><LinearLayoutandroid:id="@+id/menu_tab"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="vertical"android:gravity="center"><ImageViewandroid:layout_width="25dp"android:layout_height="25dp"android:layout_gravity="center_horizontal"android:src="@drawable/menu"android:contentDescription="菜单图标"/><TextViewandroid:id="@+id/menu_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16dp"android:text="菜单"android:gravity="center_horizontal"/></LinearLayout><!-- 我的 --><LinearLayoutandroid:id="@+id/mine_tab"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="vertical"android:gravity="center"><ImageViewandroid:layout_width="25dp"android:layout_height="25dp"android:layout_gravity="center_horizontal"android:src="@drawable/mine"android:contentDescription="我的图标"/><TextViewandroid:id="@+id/mine_text"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="16dp"android:text="我的"android:gravity="center_horizontal"/></LinearLayout></LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
4.实现FragmentStateAdapter

ViewPager2 需要实现FragmentStateAdapter管理 Fragment(类似 RecyclerView 的 Adapter)。FragmentStateAdapter会根据页面切换动态创建 / 销毁 Fragment,优化内存占用。

package com.example.news.adapter;import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import com.example.news.fragment.*;public class CategoryPagerAdapter extends FragmentStateAdapter {public CategoryPagerAdapter(@NonNull FragmentActivity fragmentActivity) {super(fragmentActivity);}@NonNull@Overridepublic Fragment createFragment(int position) {switch (position) {case 0:return new HotFragment();case 1:return new FollowFragment();case 2:return new RecommendFragment();case 3:return new CityFragment();default:throw new IllegalArgumentException("Invalid position: " + position);}}@Overridepublic int getItemCount() {return 4; // 四个分类页面}
}
5.初始化 ViewPager2 并绑定适配器
public class MainActivity extends AppCompatActivity {private ViewPager2 viewPager2;private TabLayout tabLayout;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);viewPager2 = findViewById(R.id.view_pager2);tabLayout = findViewById(R.id.tab_layout);// 1. 创建Fragment集合List<Fragment> fragments = new ArrayList<>();fragments.add(new HomeFragment());fragments.add(new RecommendFragment());fragments.add(new MineFragment());// 2. 创建适配器并绑定ViewPager2MyViewPager2Adapter adapter = new MyViewPager2Adapter(this, fragments);viewPager2.setAdapter(adapter);// 3. (可选)关联TabLayout与ViewPager2(实现标签与页面同步)new TabLayoutMediator(tabLayout, viewPager2, (tab, position) -> {// 设置标签文本(根据position动态设置)switch (position) {case 0:tab.setText("首页");break;case 1:tab.setText("推荐");break;case 2:tab.setText("我的");break;}}).attach(); // 必须调用attach()才会生效}
}
(可选)配置 ViewPager2 高级属性

根据需求设置 ViewPager2 的滑动方向、预加载、滑动禁用等属性:

// 1. 设置滑动方向(默认水平,可改为垂直)
viewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);// 2. 设置预加载页面数量(默认预加载相邻1页,不能设置为0)
viewPager2.setOffscreenPageLimit(1); // 预加载1页(左右各1页)// 3. 禁用滑动(保留编程式切换,如仅通过Tab点击切换)
viewPager2.setUserInputEnabled(false);// 4. 页面切换监听(监听滑动状态、位置变化)
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {// 页面滚动时回调}@Overridepublic void onPageSelected(int position) {// 页面选中时回调(常用:更新标题栏、加载数据等)Log.d("ViewPager2", "选中第" + position + "页");}@Overridepublic void onPageScrollStateChanged(int state) {// 滑动状态变化:SCROLL_STATE_IDLE(静止)、SCROLL_STATE_DRAGGING(拖动)、SCROLL_STATE_SETTLING(惯性滑动)}
});
FragmentStateAdapter 的工作原理
  • FragmentStateAdapter通过createFragment(int position)为每个位置创建 Fragment,且会缓存当前页及相邻页的 Fragment(数量由offscreenPageLimit控制)。
  • 当 Fragment 不可见且超出缓存范围时,会被销毁(调用onDestroy()),但状态会被保存(通过onSaveInstanceState()),下次显示时重建并恢复状态。
  • 构造方法必须传入FragmentActivityFragment,因为适配器需要通过它们的getSupportFragmentManager()Lifecycle管理 Fragment 生命周期。

在这里插入图片描述

http://www.xdnf.cn/news/15620.html

相关文章:

  • 网络基础协议综合实验
  • GeoTools 工厂设计模式
  • 【Linux庖丁解牛】— 保存信号!
  • SAP学习笔记 - 开发45 - RAP开发 Managed App New Service Definition,Metadata Extension
  • C++中list各种基本接口的模拟实现
  • 25、企业能源管理(Energy):锚定双碳目标,从分类管控到智能优化的数字化转型之路
  • npu-smi info命令参数解释
  • C++-linux系统编程 8.进程(三)孤儿进程、僵尸进程与进程回收
  • 数据结构之单链表
  • Java :List,LinkedList,ArrayList
  • sqli-labs靶场通关笔记:第17关 POST请求的密码重置
  • 连接new服务器注意事项
  • kiro, 新款 AI 编辑器, 简单了解一下
  • Java基础(八):封装、继承、多态与关键字this、super详解
  • 笔试——Day8
  • Scrapy扩展深度解析:构建可定制化爬虫生态系统的核心技术
  • 直播数据统计:如何让数据为我们所用?
  • CommunityToolkit.Mvvm IOC 示例
  • C++回顾 Day8
  • 一文深入:AI 智能体系统架构设计
  • 简单工厂设计模式
  • QT 中各种坑
  • 算法学习day16----Python数据结构--模拟队列
  • haproxy负载均衡
  • 【雅思播客016】New Year Resolution 新年决心
  • vue实现el-table-column中自定义label
  • 深入理解C++11 std::iota:从原理到实践
  • Oracle日期时间函数说明及与MySql区别说明
  • 028_分布式部署架构
  • lanch4j将jar转成exe