【Android】ViewPager

打印 上一主题 下一主题

主题 894|帖子 894|积分 2682

1.ViewPager的简介和作用


ViewPager是android扩展包v4包中的类,这个类可以让用户左右切换当前的view,用于答应用户在几个页面(或称为碎片)之间左右滑动切换。它通常用于创建像画廊或轮播图那样的用户体验。


  • ViewPager类直接继承了ViewGroup类,所有它是一个容器类,可以在其中添加其他的view类。
  • ViewPager类必要一个PagerAdapter适配器类给它提供数据。
  • ViewPager常常和Fragment一起使用,而且提供了专门的FragmentPagerAdapter和FragmentStatePagerAdapter类供Fragment中的ViewPager使用。
   作用:

  ViewPager 的紧张作用包罗:
  

  • 页面滑动:答应用户通过水平滑动来切换差别的页面。
  • 动画效果:提供平滑的页面切换动画,加强用户体验。
  • 页面预加载:可以配置 ViewPager 预加载相邻的页面,如许用户在滑动时页面切换更加流通。
  • 页面指示器:通常与 TabLayout 或其他指示器组件连合使用,显示当前页面的位置和总数。
  • 页面适配器:通过适配器模式,可以灵活地管理页面的内容,适配器负责提供页面视图。
  • 自界说页面转换:开发者可以通过实现 PageTransformer 接口来自界说页面滑动时的动画和转换效果。
  • 变乱监听:提供页面切换的监听器,如 OnPageChangeListener,以便在页面切换时执行特定的利用。
  2.ViewPager的适配器


简介中提到了PagerAdapter,和ListView等控件使用一样,必要ViewPager设置PagerAdapter来完成页面和数据的绑定,
这个PagerAdapter是一个基类适配器,我们常常用它来实现app引导图,它的子类有FragmentPagerAdapter和FragmentStatePagerAdapter,这两个子类适配器用于和Fragment一起使用,在安卓应用中它们就像listview一样出现的频繁。
适配器:ViewPager紧张有两种Adapter用于适配填充Fragment。
PagerAdapter 是 Android 中的一个抽象类,用于为 ViewPager 提供数据和视图。当你想要在 ViewPager 中展示一系列的页面时,你必要创建一个 PagerAdapter 的子类来管理这些页面。
  1. public class MyPagerAdapter extends PagerAdapter {
  2.     private Context context;
  3.     private List<Fragment> fragments;
  4.     public MyPagerAdapter(Context context, List<Fragment> fragments) {
  5.         this.context = context;
  6.         this.fragments = fragments;
  7.     }
  8.     @Override
  9.     public Object instantiateItem(ViewGroup container, int position) {//必须实现,用于实例化
  10.         Fragment fragment = fragments.get(position);
  11.         FragmentManager fragmentManager = ((FragmentActivity) context).getSupportFragmentManager();
  12.         fragmentManager.beginTransaction().add(container.getId(), fragment, "fragment" + position).commit();
  13.         return fragment;
  14.     }
  15.     @Override
  16.     public void destroyItem(ViewGroup container, int position, Object object) {//必须实现,销毁
  17.         FragmentManager fragmentManager = ((FragmentActivity) context).getSupportFragmentManager();
  18.         fragmentManager.beginTransaction().remove((Fragment) object).commit();
  19.     }
  20.     @Override
  21.     public int getCount() {//必须实现
  22.         return fragments.size();
  23.     }
  24.     @Override
  25.     public boolean isViewFromObject(View view, Object object) {//必须实现
  26.         return view.equals(object);
  27.     }
  28. }
复制代码
一个PagerAdapter 必要至少实现四个方法
这个东西是一个基类,我们常用的viewpager+fragment紧张使用他的子类:FragmentPagerAdapter和FragmentStatePagerAdapter
首先是FragmentPagerAdapter:
   特点

  

  • 每个页面一个 Fragment:FragmentPagerAdapter 为 ViewPager 的每个页面创建一个 Fragment 实例。
  • 内存效率:FragmentPagerAdapter 会保留所有页面的 Fragment 对象,这意味着用户在页面间切换时,页面状态不会丢失,但这也可能导致更多的内存使用。
  • 易于实现:相比于 PagerAdapter,FragmentPagerAdapter 提供了更简单的 API 来管理 Fragment。
  1.     private static class FragmentAdapter extends FragmentPagerAdapter{
  2.         private ArrayList<Fragment> fragments;
  3.         public FragmentAdapter(FragmentManager fm,ArrayList<Fragment> fragments) {
  4.             super(fm);
  5.             this.fragments = fragments;
  6.         }
  7.         @Override
  8.         public Fragment getItem(int position) {
  9.             return fragments.get(position);
  10.         }
  11.         @Override
  12.         public int getCount() {
  13.             return fragments.size();
  14.         }
  15.     }
复制代码
FragmentStatePagerAdapter:
   紧张特点

  

  • 按需加载:当用户欣赏到某个页面时,FragmentStatePagerAdapter 会创建该页面的 Fragment,而当用户离开该页面时,对应的 Fragment 可能会被烧毁,以节省内存。
  • 状态生存:FragmentStatePagerAdapter 会在 Fragment 被烧毁前生存其状态,以便在用户返回该页面时恢复 Fragment 的状态。
  • 实用于大量页面:由于它会烧毁不在屏幕上的 Fragment,因此更适实用于拥有大量页面的 ViewPager。
  1.     private static class FragmentStateAdapter extends FragmentStatePagerAdapter{
  2.         private ArrayList<Fragment> fragments;
  3.         public FragmentStateAdapter(FragmentManager fm,ArrayList<Fragment> fragments) {
  4.             super(fm);
  5.             this.fragments = fragments;
  6.         }
  7.         @Override
  8.         public Fragment getItem(int position) {
  9.             return fragments.get(position);
  10.         }
  11.         @Override
  12.         public int getCount() {
  13.             return fragments.size();
  14.         }
  15.     }
复制代码
与 FragmentPagerAdapter 相比,FragmentStatePagerAdapter 更适实用于页面数量较多的情况。FragmentPagerAdapter 会保留所有页面的 Fragment 在内存中,而 FragmentStatePagerAdapter 则仅在必要时加载 Fragment,如许可以淘汰内存的使用。
在fragment中的区别:
   

  • ViewPager默认会保留当前页和前后两页的内容,即一共三页。首页之前没有了以是只保留当前页和后一页;
  • 对于不保留的内容,FragmentPagerAdapter 只进行到对Fragment的destroyView,不会destroy和detach;
  • 而FragmentStatePagerAdapter会执行destroy和detach,当划回去的时候会再次执行attach和create;
  • 因此,FragmentPagerAdapter实用于数量较少的场景,用空间换时间;FragmentStatePagerAdapter实用于数量较多的场景,每次会执行destroy,节省内存。
  3.viewpager2

首先先容一下viewpager2:
   

  • 基于 RecyclerView:ViewPager2 是创建在 RecyclerView 基础上的,因此它继承了 RecyclerView 的所有优点,如高效的视图接纳机制和灵活的布局管理。
  • 灵活的缓存计谋:ViewPager2 答应开发者通过 offscreenPageLimit 属性来控制预加载的页面数量,提供了更灵活的缓存计谋。
  • 支持垂直和水平滑动:ViewPager2 支持垂直滑动,这使得它可以在差别的布局方向上使用。
  • 适配器:使用 RecyclerView.Adapter 或 FragmentStateAdapter 作为其适配器。FragmentStateAdapter 是专为 ViewPager2 设计的,用于管理 Fragment 的生命周期。
  • 新特性:ViewPager2 支持更多的自界说动画和转换效果,可以通过 PageTransformer 来实现。
  • 更好的性能:由于基于 RecyclerView,ViewPager2 在性能上通常优于 ViewPager,特殊是在处理大量数据或复杂布局时。
  ViewPager2 的运作机制
ViewPager2 的运作离不开两个关键组件:PagerAdapter 和 PageTransformer。PagerAdapter,比方 FragmentStatePagerAdapter 或 FragmentPagerAdapter,负责管理 Fragment 的集合,根据当前位置创建或烧毁 Fragment。
PageTransformer 则用于控制页面之间的过渡效果。开发者可以自界说 PageTransformer,实现缩放、平移或淡入淡出的效果,为用户提供更加流通、生动的视觉体验。
我们以常用的ViewPager2的多Fragment页面切换为例展示一下使用
1.制作一个fragment的xml文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     xmlns:app="http://schemas.android.com/apk/res-auto"
  4.     android:layout_width="match_parent"
  5.     android:layout_height="match_parent"
  6.     xmlns:tools="http://schemas.android.com/tools"
  7.     tools:context=".View.myFragment">
  8.     <com.example.weatherwindknow.View.MyView
  9.         android:id="@+id/mv"
  10.         android:layout_width="200dp"
  11.         android:layout_height="200dp"
  12.         android:layout_gravity="center_horizontal"
  13.         app:layout_constraintBottom_toBottomOf="parent"
  14.         app:layout_constraintEnd_toEndOf="parent"
  15.         app:layout_constraintStart_toStartOf="parent"
  16.         app:layout_constraintTop_toTopOf="parent" />
  17. </androidx.constraintlayout.widget.ConstraintLayout>
复制代码
我们在这里绑定了我们的类
在fragment类中:
  1. public class myFragment extends Fragment {
  2.     FragmentMyBinding binding;
  3.     @Nullable
  4.     @Override
  5.     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  6.         binding = FragmentMyBinding.inflate(inflater,container,false);
  7.         return binding.getRoot();
  8.     }
  9.     @Override
  10.     public void onDestroyView() {
  11.         super.onDestroyView();
  12.         binding = null;
  13.     }
  14. }
复制代码
2、制作Adapter

我们可以直接使用上面的示例
这里我们使用FragmentStateAdapter。
  1. public class MyviewPagerAdapter extends FragmentStateAdapter {
  2.     List<Fragment> List;
  3.     public MyviewPagerAdapter(@NonNull FragmentActivity fragmentActivity, List<Fragment> fragmentList) {
  4.         super(fragmentActivity);
  5.         this.List = fragmentList;
  6.     }
  7.     @NonNull
  8.     @Override
  9.     public Fragment createFragment(int position) {
  10.         return List.get(position);
  11.     }
  12.     @Override
  13.     public int getItemCount() {
  14.         return List != null ? List.size() : 0;
  15.     }
  16. }
复制代码
  createFragment:用于返回指定的frgment界面
  getItemCount:用于加载容器大小
  3.在活动中使用

  1.         List<Fragment> fragmentList = new ArrayList<>();
  2.         fragmentList.add(new myFragment());
  3.         fragmentList.add(new myFragment());
  4.         fragmentList.add(new myFragment());
  5.         fragmentList.add(new myFragment());
  6.         fragmentList.add(new myFragment());
  7.         MyviewPagerAdapter adapter = new MyviewPagerAdapter(this,fragmentList);
  8.         binding.viewPager.setAdapter(adapter);
复制代码
我们这里可以看出来逻辑:首先加载数据,再把数据加载进适配器,再设置适配器。
4.TabLayout / 指示器CircleIndicator

这两个东西的作用是一个知识器的效果
我们先来先容指示器CircleIndicator:这是一个简单的圆点指示器,我们使用时
首先引入库:
  1. implementation 'me.relex:circleindicator:2.1.6'
复制代码
其次将这个加入我们的布局中(一般使用是RelativeLayout)
  1. <RelativeLayout
  2.     android:layout_width="wrap_content"
  3.     android:layout_height="wrap_content">
  4.     <me.relex.circleindicator.CircleIndicator3
  5.         android:id="@+id/indicator"
  6.         android:layout_width="match_parent"
  7.         android:layout_height="48dp"
  8.         app:ci_width="5dp"
  9.         app:ci_height="5dp"
  10.         app:ci_margin="5dp"
  11.         app:ci_orientation="horizontal"
  12.         app:ci_gravity="center"/>
  13.     <androidx.viewpager2.widget.ViewPager2
  14.         android:id="@+id/viewPager"
  15.         android:layout_width="match_parent"
  16.         android:layout_height="match_parent"
  17.         android:orientation="horizontal"/>
  18. </RelativeLayout>
复制代码
之后开始使用,依据如下步调即可使用
  1. ViewPager2 viewpager = view.findViewById(R.id.viewpager);
  2. viewpager.setAdapter(mAdapter);
  3. CircleIndicator3 indicator = view.findViewById(R.id.indicator);
  4. indicator.setViewPager(viewpager);
  5. adapter.registerAdapterDataObserver(indicator.getAdapterDataObserver());
复制代码
接下来先容tablayout:
首先加入布局中:
  1.     <LinearLayout
  2.         android:layout_width="match_parent"
  3.         android:layout_height="match_parent"
  4.         android:orientation="vertical">
  5.         <com.google.android.material.tabs.TabLayout
  6.             android:id="@+id/tabs"
  7.             android:layout_width="match_parent"
  8.             android:layout_height="wrap_content"
  9.             app:tabMode="fixed" />
  10.         <androidx.viewpager2.widget.ViewPager2
  11.             android:id="@+id/viewPager"
  12.             android:layout_width="match_parent"
  13.             android:layout_height="match_parent"
  14.             android:orientation="horizontal"/>
  15.       
  16.         
  17.     </LinearLayout>
复制代码
之后在代码中将两个关联一下即可:
  1. // 将 TabLayout 与 ViewPager 关联
  2. tabLayout.setupWithViewPager(viewPager);
复制代码
自界说标签:我们可以自界说标签的文本、图标。
  1. TabLayout tabLayout = findViewById(R.id.tabs);
  2. // 添加标签
  3. tabLayout.addTab(tabLayout.newTab().setText("标签1"));
  4. tabLayout.addTab(tabLayout.newTab().setText("标签2"));
  5. tabLayout.addTab(tabLayout.newTab().setText("标签3"));
  6. // 设置标签的图标
  7. tabLayout.getTabAt(0).setIcon(R.drawable.ic_tab1);
  8. tabLayout.getTabAt(1).setIcon(R.drawable.ic_tab2);
  9. tabLayout.getTabAt(2).setIcon(R.drawable.ic_tab3);
复制代码
除了代码设置,我们还可以静态改变,设置两个样式分别代表选中未选中,app:tabTextAppearance="@style/TabLayoutTextUnSelected"
监听标签的点击变乱:我们可以为标签设置点击变乱监听器。
  1. tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
  2.     @Override
  3.     public void onTabSelected(TabLayout.Tab tab) {
  4.         // 当标签被选中时
  5.     }
  6.     @Override
  7.     public void onTabUnselected(TabLayout.Tab tab) {
  8.         // 当标签未被选中时
  9.     }
  10.     @Override
  11.     public void onTabReselected(TabLayout.Tab tab) {
  12.         // 当标签被重新选中时
  13.     }
  14. });
复制代码
动态添加和删除标签:我们可以在运行时动态地添加和删除标签。
  1. // 添加标签
  2. TabLayout.Tab newTab = tabLayout.newTab();
  3. newTab.setText("新标签");
  4. tabLayout.addTab(newTab);
  5. // 删除标签
  6. tabLayout.removeTabAt(index);
复制代码
tablayout监听:
  1.         binding.tabMode.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
  2.             TextView textView = new TextView(MainActivity.this);
  3.             @Override
  4.             public void onTabSelected(TabLayout.Tab tab) {
  5.                 //选中时的变化
  6.             }
  7.             public void onTabUnselected(TabLayout.Tab tab) {
  8.                 //未选中的变化
  9.             }
  10.             @Override
  11.             public void onTabReselected(TabLayout.Tab tab) {
  12.                 //重复选中的变化,当用户再次点击已经选中的Tab时,这个方法就会被调用。
  13.             }
  14.         });
复制代码
我们可以在 onTabSelected中处理选中的时候情况,更改样式等等,但是要在 onTabSelected中设置内容,而且在 onTabUnSelected中清撤除我们的样式,否则会出现叠加爆掉的情况

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

络腮胡菲菲

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表