ViewPager是 Android 中用于实现水平或垂直滚动的视图容器,通常用于实现分页效果。在 ViewPager中,用户可以滑动屏幕来切换不同的页面,它常用于实现类似于图片轮播、页面切换等功能。
如何通过ViewPager组件实现轮播图效果呢?以下是我个人的方法。
这是最终的效果(前面是自动轮播,有鼠标的是人为拖动)。
首先写banner的布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.viewpager.widget.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="300dp" />
</LinearLayout>
引入androidx.viewpager.widget.ViewPager控件。
然后创建BannerActivity活动
在onCreate函数中
setContentView(R.layout.banner);
viewPager=findViewById(R.id.pager);
int[] imgList={
R.drawable.banner1,
R.drawable.banner2,
R.drawable.banner3
};
设置当前的banner视图,找到id为pager的控件,并且我定义了三个图片作为imgList的数据。
然后在官网上查看发现使用viewpager组件需要使用他自己的适配器。
因此
viewPager.setAdapter(new PagerAdapter() {
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view==object;
}
@Override
@NonNull
public Object instantiateItem(@NonNull ViewGroup container,int position){
ImageView img=new ImageView(BannerActivity.this);
img.setMaxWidth(ViewGroup.LayoutParams.MATCH_PARENT);
img.setMaxHeight(ViewGroup.LayoutParams.MATCH_PARENT);
img.setImageResource(imgList[position%imgList.length]);
container.addView(img);
return img;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView((View) object); // 添加 destroyItem
}
});
getCount函数返回轮播的个数,这里我用了Integer.MAX_VALUE,使得让他尽量大以达到无线轮播的效果。
isViewFromObject方法通常用于判断viewpager中的视图(view)是否与当前页面的对象(object)关联。
instantiateItem用于在viewpager的指定页面插入新的视图,我的代码中,我创建了ImageVIew控件,通过每次滑动时取position%imgList.length来实现图片无限轮播的效果,这样就不会使得向后或者向前滑动的时候没有内容了,然后通过container.addView将我创建的ImageView控件放到viewpager组件里面。
destroyItem主要用于销毁和移除不再显示的页面视图。当ViewPager滑动到其他页面时,会调用该方法来释放已经不再可见的页面,以提高内存的使用效率并避免内存泄漏。
做完以上方式后
viewPager.setCurrentItem(Integer.MAX_VALUE / 2);
currentItem=Integer.MAX_VALUE / 2;
我设置viewpager的当前位置为最大值/2,避免刚开始无法向右滑动的bug,这样处理就可以刚开始既可以向左也可以向右滑动。
设置以上方法后便可以实现轮播图的滑动,但是在实际的应用中,往往还设置了banner的自动轮播,所以我又添加了自动轮播的方法。
// 设置ViewPager的页面监听
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
currentItem = position; // 更新当前页面的索引
}
@Override
public void onPageScrollStateChanged(int state) {
System.out.println(state);
if (state == 1) {
// startAutoSlide(); // 用户停止滑动时重启轮播
TimerHandler.removeCallbacks(myTimerRun);
}
if(state==2){
TimerHandler.postDelayed(myTimerRun, 2000);
}
}
});
myTimerRun=new Runnable() {
@Override
public void run(){
currentItem++;
viewPager.setCurrentItem(currentItem, true);
}
};
TimerHandler.postDelayed(myTimerRun, 2000);
通过viewPager.addOnPageChangeListener设置viewpager的页面监听,我设置了一个全局的currentItem来记录当前的position,定时器要做的就时每次执行时currentItem++,让后调用viewpager.setCurrentItem函数使得去到指定的页面。
然后就是要处理一个事情就是当你用户如果在拖动轮播图的时候我们需要销毁定时器
他这里是有三个状态的,onPageScrollStateChanged(int state)这个函数中当state为1的时候我就处理TimerHandler.removeCallbacks(myTimerRun)销毁定时器,当达到稳定时又启动定时器,这样就可以避免用户在滑动时,因为定时器的效果,让其自动轮播。
但是有一个需要注意的是,刚开始需要启动定时器,所以最下面那个步骤我就启用了定时器,每2s执行一次轮播。
以上就是我简单使用viewpager实现了banner,并且是自动化,可无限循环。
如有问题,欢迎指正!!!