效果图
class MainActivity : Activity(), Runnable {private lateinit var viewPager: ViewPagerprivate lateinit var bannerAdapter: BannerAdapterprivate val images = ArrayList<Int>() // 存储图片资源的列表private val handler = Handler() // 用于定时发送消息的Handlerprivate val DELAY_TIME = 3000L // 轮播的延迟时间,单位为毫秒override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)var list= arrayListOf<Bean>()viewPager = findViewById(R.id.view_pager) // 获取ViewPager控件images.apply { // 初始化图片资源的列表add(R.mipmap.ic_launcher) // 添加图片资源add(R.mipmap.ic_launcher) // 添加图片资源add(R.mipmap.ic_launcher) // 添加图片资源add(R.mipmap.ic_launcher) // 添加图片资源add(R.mipmap.ic_launcher) // 添加图片资源add(R.mipmap.ic_launcher) // 添加图片资源add(R.mipmap.ic_launcher) // 添加图片资源add(R.mipmap.ic_launcher) // 添加图片资源}//处理数据//数据处理为3的倍数(加的方式)val value=images.size%3if (value==1){images.add(images[1])images.add(images[2])}else if (value==2){images.add(images[1])}for (i in 0 until images.size step 3){list.add(Bean(BeanItem(images[i],"title$i"),BeanItem(images[i+1],"title${i+1}"),BeanItem(images[i+2],"title${i+2}")))}bannerAdapter = BannerAdapter(this, list) // 创建适配器对象viewPager.adapter = bannerAdapter // 设置适配器viewPager.currentItem = images.size * 100 // 设置当前的位置,以保证可以向前滑动
// viewPager.setPageTransformer(true, ZoomOutPageTransformer()) // 设置页面的转换效果,您可以自定义或使用第三方的库viewPager.pageMargin = 20 // 设置页面的间隔viewPager.offscreenPageLimit = 3 // 设置预加载的页面数handler.postDelayed({ // 发送一个延迟的Runnable对象val currentItem = viewPager.currentItem // 获取当前的位置viewPager.currentItem = currentItem + 1 // 设置下一个位置handler.postDelayed(this, DELAY_TIME) // 再次发送延迟的Runnable对象,实现循环}, DELAY_TIME)}override fun onDestroy() {super.onDestroy()handler.removeCallbacksAndMessages(null) // 移除所有的消息和回调,避免内存泄漏}private val TAG = "MainActivity"override fun run() {handler.postDelayed({ // 发送一个延迟的Runnable对象val currentItem = viewPager.currentItem // 获取当前的位置viewPager.currentItem = currentItem + 1 // 设置下一个位置handler.postDelayed(this, DELAY_TIME) // 再次发送延迟的Runnable对象,实现循环}, DELAY_TIME)}
}class BannerAdapter(private val context: Context, private val list: ArrayList<Bean>) : PagerAdapter() {override fun getCount(): Int {return Int.MAX_VALUE // 设置为一个很大的数,以实现无限循环}@SuppressLint("MissingInflatedId")override fun instantiateItem(container: ViewGroup, position: Int): Any {val view = LayoutInflater.from(context).inflate(R.layout.item_banner, container, false) // 加载自定义的布局文件val imageView1 = view.findViewById<ImageView>(R.id.image_view1) // 获取布局文件中的ImageViewval imageView2 = view.findViewById<ImageView>(R.id.image_view2) // 获取布局文件中的ImageViewval imageView3 = view.findViewById<ImageView>(R.id.image_view3) // 获取布局文件中的ImageViewval tv1 = view.findViewById<TextView>(R.id.tv1) // 获取布局文件中的ImageViewval tv2 = view.findViewById<TextView>(R.id.tv2) // 获取布局文件中的ImageViewval tv3 = view.findViewById<TextView>(R.id.tv3) // 获取布局文件中的ImageViewimageView1.setImageResource(list[position % list.size].item1.img) // 设置图片资源imageView2.setImageResource(list[position % list.size].item2.img) // 设置图片资源imageView3.setImageResource(list[position % list.size].item3.img) // 设置图片资源tv1.text=list[position % list.size].item1.titletv2.text=list[position % list.size].item2.titletv3.text=list[position % list.size].item3.titlecontainer.addView(view) // 将视图添加到容器中return view // 返回视图对象}override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {container.removeView(`object` as View) // 移除视图}override fun isViewFromObject(view: View, `object`: Any): Boolean {return view == `object` // 判断视图是否和对象相同}
}
bean
class Bean(val item1:BeanItem,val item2:BeanItem,val item3:BeanItem)
class BeanItem(val img:Int,val title:String)
自定义垂直viewPager
class VerticalViewPager(context: Context, attrs: AttributeSet?) : ViewPager(context, attrs) {private val gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {override fun onScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {return if (abs(distanceX) > abs(distanceY)) {false} else {super.onScroll(e1, e2, distanceX, distanceY)}}})init {setPageTransformer(true, VerticalPageTransformer())}override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {val intercepted = super.onInterceptTouchEvent(swapXY(ev))swapXY(ev)return intercepted}override fun onTouchEvent(ev: MotionEvent): Boolean {return if (gestureDetector.onTouchEvent(ev)) {super.onTouchEvent(swapXY(ev))} else {false}}private fun swapXY(event: MotionEvent?): MotionEvent? {event?.let {val width = width.toFloat()val height = height.toFloat()val newX = it.y / height * widthval newY = it.x / width * heightit.setLocation(newX, newY)}return event}
}
class VerticalPageTransformer : PageTransformer {override fun transformPage(view: View, position: Float) {if (position < -1) { // [-Infinity,-1)// This page is way off-screen to the left.view.alpha = 0f} else if (position <= 1) { // [-1,1]view.alpha = 1f// Counteract the default slide transitionview.translationX = view.width * -position//set Y position to swipe in from topval yPosition = position * view.heightview.translationY = yPosition} else { // (1,+Infinity]// This page is way off-screen to the right.view.alpha = 0f}}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="200dp"><com.example.banner.view.VerticalViewPagerandroid:id="@+id/view_pager"android:layout_width="match_parent"android:layout_height="wrap_content"android:clipToPadding="false"/></LinearLayout>
item_banner
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:paddingHorizontal="40dp"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:layout_weight="1"android:gravity="center"><ImageViewandroid:layout_marginHorizontal="10dp"android:layout_width="match_parent"android:layout_height="200dp"android:id="@+id/image_view1"android:scaleType="fitXY"android:src="@mipmap/ic_launcher"android:layout_weight="1"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/tv1"android:text="hello"/></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:layout_weight="1"android:gravity="center"><ImageViewandroid:layout_marginHorizontal="10dp"android:layout_width="match_parent"android:layout_height="200dp"android:id="@+id/image_view2"android:scaleType="fitXY"android:src="@mipmap/ic_launcher"android:layout_weight="1"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/tv2"android:text="hello"/></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:layout_weight="1"android:gravity="center"><ImageViewandroid:layout_marginHorizontal="10dp"android:layout_width="match_parent"android:layout_height="200dp"android:id="@+id/image_view3"android:scaleType="fitXY"android:src="@mipmap/ic_launcher"android:layout_weight="1"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/tv3"android:text="hello"/></LinearLayout></LinearLayout>