您的位置:

Android ViewPage: 初识多页面滑动

一、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进行更丰富的页面构建和多样化的应用实现。