一、ViewPage简介
ViewPage是一个内置滑动效果的控件,可以容纳多个子页面(Fragment或View),通过左右滑动手势,在多个子页面间进行切换。其具有以下特点:
- 使用简单方便,易于实现多个页面的滑动切换
- 使用ViewPage可以方便的实现引导页面、轮播图等功能
- ViewPage支持自定义页面切换的动画效果,可以在应用中提供更好的用户体验
二、ViewPage的基本使用
使用ViewPage需要借助PagerAdapter类,PagerAdapter负责为ViewPage提供子页面,同时也负责为子页面设置标识,以便于ViewPage在滑动切换时进行页面的索引和页面缓存。下面代码展示了如何使用ViewPage,其中提供了三个页面,每个页面内包含一个简单的TextView:
// 布局文件中引用ViewPage <androidx.viewpager.widget.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent" /> // ViewPager使用的PagerAdapter,其中getPageTitle()返回页面的标识 class MyPagerAdapter extends PagerAdapter { private List<View> mViews; public MyPagerAdapter(List<View> views) { mViews = views; } @Override public int getCount() { return mViews.size(); } @Override public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { return view == object; } @NonNull @Override public Object instantiateItem(@NonNull ViewGroup container, int position) { View view = mViews.get(position); container.addView(view); return view; } @Override public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { container.removeView(mViews.get(position)); } @Nullable @Override public CharSequence getPageTitle(int position) { return "Page " + (position + 1); } } // 实例化ViewPage和PagerAdapter,设置Adapter ViewPager viewPager = findViewById(R.id.view_pager); List<View> views = new ArrayList<>(); LayoutInflater inflater = LayoutInflater.from(this); View view1 = inflater.inflate(R.layout.page_1, null); View view2 = inflater.inflate(R.layout.page_2, null); View view3 = inflater.inflate(R.layout.page_3, null); views.add(view1); views.add(view2); views.add(view3); MyPagerAdapter adapter = new MyPagerAdapter(views); viewPager.setAdapter(adapter);
三、ViewPage的进阶使用
1、实现ViewPagerIndicator
ViewPagerIndicator 可以在TabLayout的下方建立一个ViewPager的Indicator,也可以叫HeaderViewPager。其中,TabLayout 和 ViewPager 都是 Android SDK 中的原生组件。而 ViewPagerIndicator 则是一个能实现类似于 iOS 中的组件的 Android 三方库。下面代码展示了如何使用ViewPagerIndicator,在TabLayout下面展示当前ViewPage的位置:
// 布局文件中引用ViewPager、TabLayout和ViewPagerIndicator <androidx.viewpager.widget.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.viewpagerindicator.CirclePageIndicator android:id="@+id/indicator" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="10dp" android:paddingTop="10dp" /> <com.google.android.material.tabs.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" app:tabIndicatorColor="@android:color/white" app:tabMode="fixed" app:tabSelectedTextColor="@android:color/white" app:tabTextColor="#ffffff" /> // ViewPager使用的PagerAdapter class MyPagerAdapter extends FragmentPagerAdapter { private List<Fragment> mFragments; public MyPagerAdapter(FragmentManager fm, List<Fragment> fragments) { super(fm, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); mFragments = fragments; } @Override public int getCount() { return mFragments.size(); } @NonNull @Override public Fragment getItem(int position) { return mFragments.get(position); } } // 实例化ViewPager、ViewPagerIndicator和TabLayout,并设置PagerAdapter ViewPager viewPager = findViewById(R.id.view_pager); List<Fragment> fragments = new ArrayList<>(); fragments.add(new Fragment1()); fragments.add(new Fragment2()); fragments.add(new Fragment3()); MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager(), fragments); viewPager.setAdapter(adapter); CirclePageIndicator indicator = findViewById(R.id.indicator); indicator.setViewPager(viewPager); TabLayout tabLayout = findViewById(R.id.tab_layout); tabLayout.setupWithViewPager(viewPager);
2、自定义页面切换效果
由于ViewPage内置的页面切换效果有限,我们有时需要自定义一些页面切换效果以提供更好的用户体验。下面代码展示了如何自定义一种渐变的页面切换效果,即在页面滑动过程中,前一页逐渐淡出,后一页逐渐淡入:
// 布局文件中引用ViewPager <androidx.viewpager.widget.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent" /> // 自定义的页面切换效果 class FadePageTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.7f; private static final float MIN_ALPHA = 0.5f; @Override public void transformPage(@NonNull View view, float position) { if (position < -1) { view.setAlpha(0); } else if (position <= 1) { float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position)); view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); } else { view.setAlpha(0); } } } // 实例化ViewPager和PagerAdapter,并设置页面切换效果 ViewPager viewPager = findViewById(R.id.view_pager); List<View> views = new ArrayList<>(); LayoutInflater inflater = LayoutInflater.from(this); View view1 = inflater.inflate(R.layout.page_1, null); View view2 = inflater.inflate(R.layout.page_2, null); View view3 = inflater.inflate(R.layout.page_3, null); views.add(view1); views.add(view2); views.add(view3); MyPagerAdapter adapter = new MyPagerAdapter(views); viewPager.setAdapter(adapter); FadePageTransformer transformer = new FadePageTransformer(); viewPager.setPageTransformer(true, transformer);
3、利用ViewPager实现轮播图
使用ViewPager可以非常轻松地实现一个轮播图,只需要将ViewPager的页面设置为图片即可。下面代码展示了如何利用ViewPager实现一个简单的轮播图,并在页面切换时展示页面的位置:
// 布局文件中引用ViewPager、TextView和ViewPagerIndicator <androidx.viewpager.widget.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" /> <TextView android:id="@+id/tv_index" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Index: 1" android:textColor="#333333" android:textSize="16sp" /> <com.viewpagerindicator.CirclePageIndicator android:id="@+id/indicator" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="10dp" android:paddingTop="10dp" /> // 自定义的PagerAdapter,其中展示的页面数据为图片 class MyPagerAdapter extends PagerAdapter { private List<Integer> mImages; public MyPagerAdapter(List<Integer> images) { mImages = images; } @Override public int getCount() { return mImages.size(); } @Override public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { return view == object; } @NonNull @Override public Object instantiateItem(@NonNull ViewGroup container, int position) { ImageView imageView = new ImageView(container.getContext()); imageView.setImageResource(mImages.get(position)); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); container.addView(imageView); return imageView; } @Override public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { container.removeView((ImageView) object); } @Nullable @Override public CharSequence getPageTitle(int position) { return "Page " + (position + 1); } } // 实例化ViewPager、PagerIndicator和PagerAdapter,设置Adapter和indicator ViewPager viewPager = findViewById(R.id.view_pager); List<Integer> images = new ArrayList<>(); images.add(R.drawable.pic_1); images.add(R.drawable.pic_2); images.add(R.drawable.pic_3); MyPagerAdapter adapter = new MyPagerAdapter(images); viewPager.setAdapter(adapter); CirclePageIndicator indicator = findViewById(R.id.indicator); indicator.setViewPager(viewPager); TextView tvIndex = findViewById(R.id.tv_index); tvIndex.setText("Index: 1"); viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { tvIndex.setText("Index: " + (position + 1)); } @Override public void onPageScrollStateChanged(int state) { } });
四、总结
ViewPage是Android SDK中一个非常实用的控件,可以方便地实现多个子页面的滑动切换。通过学习本文的介绍,我们可以初步掌握ViewPage的基本使用、ViewPagerIndicator的实现、页面切换效果的自定义以及利用ViewPage实现轮播图等知识。在实际开发中,我们可以根据业务需要结合ViewPage进行更丰富的页面构建和多样化的应用实现。