1.ViewPager的简介和作用
 ViewPager是android扩展包v4包中的类,这个类可以让用户左右切换当前的view,用于允许用户在几个页面(或称为碎片)之间左右滑动切换。它通常用于创建像画廊或轮播图那样的用户体验。
- ViewPager类直接继承了ViewGroup类,所有它是一个容器类,可以在其中添加其他的view类。
- ViewPager类需要一个PagerAdapter适配器类给它提供数据。
- ViewPager经常和Fragment一起使用,并且提供了专门的FragmentPagerAdapter和FragmentStatePagerAdapter类供Fragment中的ViewPager使用。
2.ViewPager的适配器
 简介中提到了PagerAdapter,和ListView等控件使用一样,需要ViewPager设置PagerAdapter来完成页面和数据的绑定,
这个PagerAdapter是一个基类适配器,我们经常用它来实现app引导图,它的子类有FragmentPagerAdapter和FragmentStatePagerAdapter,这两个子类适配器用于和Fragment一起使用,在安卓应用中它们就像listview一样出现的频繁。
适配器:ViewPager主要有两种Adapter用于适配填充Fragment。
PagerAdapter 是 Android 中的一个抽象类,用于为 ViewPager 提供数据和视图。当你想要在 ViewPager 中展示一系列的页面时,你需要创建一个 PagerAdapter 的子类来管理这些页面。
public class MyPagerAdapter extends PagerAdapter {
    private Context context;
    private List<Fragment> fragments;
    public MyPagerAdapter(Context context, List<Fragment> fragments) {
        this.context = context;
        this.fragments = fragments;
    }
    @Override
    public Object instantiateItem(ViewGroup container, int position) {//必须实现,用于实例化
        Fragment fragment = fragments.get(position);
        FragmentManager fragmentManager = ((FragmentActivity) context).getSupportFragmentManager();
        fragmentManager.beginTransaction().add(container.getId(), fragment, "fragment" + position).commit();
        return fragment;
    }
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {//必须实现,销毁
        FragmentManager fragmentManager = ((FragmentActivity) context).getSupportFragmentManager();
        fragmentManager.beginTransaction().remove((Fragment) object).commit();
    }
    @Override
    public int getCount() {//必须实现
        return fragments.size();
    }
    @Override
    public boolean isViewFromObject(View view, Object object) {//必须实现
        return view.equals(object);
    }
}一个PagerAdapter 需要至少实现这四个方法
这个东西是一个基类,我们常用的viewpager+fragment主要使用他的子类:FragmentPagerAdapter和FragmentStatePagerAdapter
首先是FragmentPagerAdapter:
    private static class FragmentAdapter extends FragmentPagerAdapter{
        private ArrayList<Fragment> fragments;
        public FragmentAdapter(FragmentManager fm,ArrayList<Fragment> fragments) {
            super(fm);
            this.fragments = fragments;
        }
        @Override
        public Fragment getItem(int position) {
            return fragments.get(position);
        }
        @Override
        public int getCount() {
            return fragments.size();
        }
    }
FragmentStatePagerAdapter:
    private static class FragmentStateAdapter extends FragmentStatePagerAdapter{
        private ArrayList<Fragment> fragments;
        public FragmentStateAdapter(FragmentManager fm,ArrayList<Fragment> fragments) {
            super(fm);
            this.fragments = fragments;
        }
        @Override
        public Fragment getItem(int position) {
            return fragments.get(position);
        }
        @Override
        public int getCount() {
            return fragments.size();
        }
    }
与 FragmentPagerAdapter 相比,FragmentStatePagerAdapter 更适合用于页面数量较多的情况。FragmentPagerAdapter 会保留所有页面的 Fragment 在内存中,而 FragmentStatePagerAdapter 则仅在需要时加载 Fragment,这样可以减少内存的使用。
在fragment中的区别:
3.viewpager2
首先介绍一下viewpager2:
ViewPager2 的运作机制
ViewPager2 的运作离不开两个关键组件:PagerAdapter 和 PageTransformer。PagerAdapter,例如 FragmentStatePagerAdapter 或 FragmentPagerAdapter,负责管理 Fragment 的集合,根据当前位置创建或销毁 Fragment。
PageTransformer 则用于控制页面之间的过渡效果。开发者可以自定义 PageTransformer,实现缩放、平移或淡入淡出的效果,为用户提供更加流畅、生动的视觉体验。
我们以常用的ViewPager2的多Fragment页面切换为例展示一下使用
1.制作一个fragment的xml文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns: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"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".View.myFragment">
    <com.example.weatherwindknow.View.MyView
        android:id="@+id/mv"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_gravity="center_horizontal"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>我们在这里绑定了我们的类
在fragment类中:
public class myFragment extends Fragment {
    FragmentMyBinding binding;
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        binding = FragmentMyBinding.inflate(inflater,container,false);
        return binding.getRoot();
    }
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
}
2、制作Adapter
我们可以直接使用上面的示例
这里我们使用FragmentStateAdapter。
public class MyviewPagerAdapter extends FragmentStateAdapter {
    List<Fragment> List;
    public MyviewPagerAdapter(@NonNull FragmentActivity fragmentActivity, List<Fragment> fragmentList) {
        super(fragmentActivity);
        this.List = fragmentList;
    }
    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return List.get(position);
    }
    @Override
    public int getItemCount() {
        return List != null ? List.size() : 0;
    }
}3.在活动中使用
        List<Fragment> fragmentList = new ArrayList<>();
        fragmentList.add(new myFragment());
        fragmentList.add(new myFragment());
        fragmentList.add(new myFragment());
        fragmentList.add(new myFragment());
        fragmentList.add(new myFragment());
        MyviewPagerAdapter adapter = new MyviewPagerAdapter(this,fragmentList);
        binding.viewPager.setAdapter(adapter);我们这里可以看出来逻辑:首先加载数据,再把数据加载进适配器,再设置适配器。
4.TabLayout / 指示器CircleIndicator
这两个东西的作用是一个知识器的效果
我们先来介绍指示器CircleIndicator:这是一个简单的圆点指示器,我们使用时
首先引入库:
implementation 'me.relex:circleindicator:2.1.6'
其次将这个加入我们的布局中(一般使用是RelativeLayout)
<RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <me.relex.circleindicator.CircleIndicator3
        android:id="@+id/indicator"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        app:ci_width="5dp"
        app:ci_height="5dp"
        app:ci_margin="5dp"
        app:ci_orientation="horizontal"
        app:ci_gravity="center"/>
    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"/>
</RelativeLayout>之后开始使用,依据如下步骤即可使用
ViewPager2 viewpager = view.findViewById(R.id.viewpager);
viewpager.setAdapter(mAdapter);
CircleIndicator3 indicator = view.findViewById(R.id.indicator);
indicator.setViewPager(viewpager);
adapter.registerAdapterDataObserver(indicator.getAdapterDataObserver());接下来介绍tablayout:
首先加入布局中:
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabMode="fixed" />
        <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/viewPager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal"/> 
       
        
    </LinearLayout>
之后在代码中将两个关联一下即可:
// 将 TabLayout 与 ViewPager 关联
tabLayout.setupWithViewPager(viewPager);自定义标签:我们可以自定义标签的文本、图标。
TabLayout tabLayout = findViewById(R.id.tabs);
// 添加标签
tabLayout.addTab(tabLayout.newTab().setText("标签1"));
tabLayout.addTab(tabLayout.newTab().setText("标签2"));
tabLayout.addTab(tabLayout.newTab().setText("标签3"));
// 设置标签的图标
tabLayout.getTabAt(0).setIcon(R.drawable.ic_tab1);
tabLayout.getTabAt(1).setIcon(R.drawable.ic_tab2);
tabLayout.getTabAt(2).setIcon(R.drawable.ic_tab3);除了代码设置,我们还可以静态改变,设置两个样式分别代表选中未选中,app:tabTextAppearance="@style/TabLayoutTextUnSelected"
监听标签的点击事件:我们可以为标签设置点击事件监听器。
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
    @Override
    public void onTabSelected(TabLayout.Tab tab) {
        // 当标签被选中时
    }
    @Override
    public void onTabUnselected(TabLayout.Tab tab) {
        // 当标签未被选中时
    }
    @Override
    public void onTabReselected(TabLayout.Tab tab) {
        // 当标签被重新选中时
    }
});动态添加和删除标签:我们可以在运行时动态地添加和删除标签。
// 添加标签
TabLayout.Tab newTab = tabLayout.newTab();
newTab.setText("新标签");
tabLayout.addTab(newTab);
// 删除标签
tabLayout.removeTabAt(index);tablayout监听:
        binding.tabMode.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            TextView textView = new TextView(MainActivity.this);
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                //选中时的变化
            }
            public void onTabUnselected(TabLayout.Tab tab) {
                //未选中的变化
            }
            @Override
            public void onTabReselected(TabLayout.Tab tab) {
                //重复选中的变化,当用户再次点击已经选中的Tab时,这个方法就会被调用。
            }
        });
我们可以在 onTabSelected中处理选中的时候情况,更改样式等等,但是要在 onTabSelected中设置内容,并且在 onTabUnSelected中清除掉我们的样式,否则会出现叠加爆掉的情况










