【Android】ViewPager2结合Fragment实现多页面滑动切换

一、什么是ViewPager2

ViewPager2 是 Android Jetpack 中的一个组件,用于在屏幕上实现可水平或垂直滑动的页面切换效果。它是早期 ViewPager 库的现代化替代品,解决了 ViewPager 的许多遗留问题并引入了强大的新功能。

你可以把它想象成一个可以左右(或上下)滑动的"相册"或者"引导页",每一页都是一个独立的视图(FragmentView),用户通过滑动手势在不同页面间切换。最常见的应用场景包括:

  • 应用引导页:新用户安装应用后的功能介绍幻灯片。

  • 图片浏览器/相册:全屏查看图片,滑动切换上一张/下一张。

  • 标签页 :与 TabLayout 结合使用,实现类似 Chrome 浏览器顶部的标签页效果。

  • 新闻/文章详情流:滑动切换到下一篇新闻或文章。

相较于ViewPager的优点:

  • 垂直方向支持
    除了支持传统的水平分页之外,ViewPager2 还支持垂直分页。您可以通过设置 ViewPager2 元素的 android:orientation 属性为其启用垂直分页:
java 复制代码
<androidx.viewpager2.widget.ViewPager2
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/pager"
        android:orientation="vertical" />
    
  • 从右到左支持

ViewPager2 支持从右到左 (RTL) 分页。系统会根据语言区域在适当的情况下自动启用 RTL 分页,不过您也可以通过设置 ViewPager2 元素的 android:layoutDirection 属性为其手动启用 RTL 分页:

java 复制代码
<androidx.viewpager2.widget.ViewPager2
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/pager"
        android:layoutDirection="rtl" />
    
  • 可修改的 Fragment 集合

ViewPager2 支持对可修改的 Fragment 集合进行分页浏览,在底层集合发生更改时调用 notifyDatasetChanged() 来更新界面。

这意味着,您的应用可以在运行时动态修改 Fragment 集合,而 ViewPager2 会正确显示修改后的集合。

二、ViewPager2结合Fragment使用

1.添加依赖

java 复制代码
dependencies {
    implementation "androidx.viewpager2:viewpager2:1.0.0"
}

2.在布局文件中添加ViewPager2

XML 复制代码
<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/viewPager2"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

3.创建要添加的Fragment及其布局文件

java 复制代码
import androidx.fragment.app.Fragment;

public class MainFragment extends Fragment {

    private static final String ARG_ID = "id";

    public static MainFragment newInstance(String id) {
        MainFragment fragment = new MainFragment();
        Bundle args = new Bundle();
        args.putString(ARG_ID, id);
        fragment.setArguments(args);
        return fragment;
    }

    // 完整的 Fragment 实现...
}

在其中编写newInstance方法,方便在Adapter中创建实例。

4.创建适配器

自定义Adapter继承 FragmentStateAdapter,重写getItemCount()和createFragment(position: Int)。

其中,getItemCount()返回 ViewPager2 中总共有多少页(即有多少个 Fragment);

createFragment(position: Int)根据给定的位置(position)创建并返回对应的 Fragment 实例。

java 复制代码
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;

import java.util.List;

public class DynamicFragmentStateAdapter extends FragmentStateAdapter {

    private final List<Data> dataList;

    public DynamicFragmentStateAdapter(@NonNull FragmentActivity fragmentActivity, List<Data> dataList) {
        super(fragmentActivity);
        this.dataList = dataList;
    }

    public DynamicFragmentStateAdapter(@NonNull Fragment fragment, List<Data> dataList) {
        super(fragment);
        this.dataList = dataList;
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        // 获取当前位置的数据
        Data data = dataList.get(position);
        
       return MainFragment.newInstance(data);
       
    }

    @Override
    public int getItemCount() {
        return dataList != null ? dataList.size() : 0;
    }

    // 可选:更新数据的方法
    public void updateData(List<Data> newDataList) {
        this.dataList.clear();
        this.dataList.addAll(newDataList);
        notifyDataSetChanged(); // 通知适配器数据已更改
    }
}

5.在Activity或Fragment中设置适配器

在Activity的onCreate()中设置,在Fragment的onCreateView()中设置。

java 复制代码
 private ViewPager2 viewPager2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        viewPager2 = findViewById(R.id.view_pager);
        MainFragmentAdapter adapter = new MainFragmentAdapter(this);
        viewPager2.setAdapter(adapter);
    }
java 复制代码
public class ParentFragment extends Fragment {

    private ViewPager2 viewPager2;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_parent, container, false);
        
        viewPager2 = view.findViewById(R.id.view_pager);
        MainFragmentAdapter adapter = new MainFragmentAdapter(this);
        viewPager2.setAdapter(adapter);
        
        return view;
    }
}
相关推荐
xiangpanf3 小时前
Laravel 10.x重磅升级:五大核心特性解析
android
robotx6 小时前
安卓线程相关
android
消失的旧时光-19437 小时前
Android 面试高频:JSON 文件、大数据存储与断电安全(从原理到工程实践)
android·面试·json
dalancon8 小时前
VSYNC 信号流程分析 (Android 14)
android
dalancon8 小时前
VSYNC 信号完整流程2
android
dalancon8 小时前
SurfaceFlinger 上帧后 releaseBuffer 完整流程分析
android
用户69371750013849 小时前
不卷AI速度,我卷自己的从容——北京程序员手记
android·前端·人工智能
程序员Android9 小时前
Android 刷新一帧流程trace拆解
android
墨狂之逸才10 小时前
解决 Android/Gradle 编译报错:Comparison method violates its general contract!
android
阿明的小蝴蝶11 小时前
记一次Gradle环境的编译问题与解决
android·前端·gradle