今天给大家实现一个自定义的卡片切换效果。
gallery
工程结构非常简单,就以下三个类:
一. 页面相关
TestGalleryActivity
package com.openld.seniorui.testgallery
import android.os.Bundle
import android.os.Message
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.viewpager.widget.ViewPager
import com.openld.seniorui.R
import java.util.*
/**
* 测试一下画廊效果
*/
class TestGalleryActivity : AppCompatActivity() {
private val TAG = "Gallery"
private var mCurrentIndex = 0
private lateinit var mGallery: ViewPager
private val mFruitList = mutableListOf<Int>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test_gallery)
initData()
initWidgets()
addListeners()
}
private fun initData() {
mFruitList.add(R.drawable.fruit_image1)
mFruitList.add(R.drawable.fruit_image2)
mFruitList.add(R.drawable.fruit_image3)
mFruitList.add(R.drawable.fruit_image4)
mFruitList.add(R.drawable.fruit_image5)
mFruitList.add(R.drawable.fruit_image6)
mFruitList.add(R.drawable.fruit_image7)
mFruitList.add(R.drawable.fruit_image8)
mFruitList.add(R.drawable.fruit_image9)
mFruitList.add(R.drawable.fruit_image10)
mFruitList.add(R.drawable.fruit_image11)
mFruitList.add(R.drawable.fruit_image12)
mFruitList.add(R.drawable.fruit_image13)
mFruitList.add(R.drawable.fruit_image14)
mFruitList.add(R.drawable.fruit_image15)
mFruitList.add(R.drawable.fruit_image16)
mFruitList.add(R.drawable.fruit_image17)
}
private fun addListeners() {
mGallery.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
Log.d(TAG, ">>> $position")
mCurrentIndex = position
}
override fun onPageSelected(position: Int) {
}
override fun onPageScrollStateChanged(state: Int) {
}
})
}
private fun initWidgets() {
Message.obtain()
mGallery = findViewById(R.id.gallery)
val adapter = GalleryAdapter(this, mFruitList)
mGallery.offscreenPageLimit = mFruitList.size
mGallery.adapter = adapter
mGallery.currentItem = mFruitList.size - 1
mGallery.setPageTransformer(false, GalleryTransformer())
// 滑到第一个
scrollToFirst()
// 训话滑动轮播
loopScroll()
}
/**
* 循环滑动轮播
*/
private fun loopScroll() {
// 轮播
mGallery.postDelayed({
val timer = Timer()
timer.schedule(object : TimerTask() {
override fun run() {
if (mCurrentIndex == mFruitList.size) {
mCurrentIndex = 0
}
mGallery.currentItem = mCurrentIndex++
}
}, 0, 2000)
}, 2200)
}
/**
* 滑动到第一个
*/
private fun scrollToFirst() {
// 这鬼滑动速度不知道怎么控制
mGallery.postDelayed({
mGallery.setCurrentItem(0, true)
}, 200)
}
}
页面布局activity_test_gallery.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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
tools:context=".testgallery.TestGalleryActivity">
<androidx.viewpager.widget.ViewPager
android:id="@+id/gallery"
android:layout_width="200dp"
android:layout_height="300dp"
android:orientation="horizontal"
android:overScrollMode="always"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
页面中的图片资源自己替换下好了
二.适配器
GalleryAdapter
package com.openld.seniorui.testgallery
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.annotation.NonNull
import androidx.appcompat.widget.AppCompatImageView
import androidx.viewpager.widget.PagerAdapter
import com.openld.seniorui.R
class GalleryAdapter(@NonNull context: Context, @NonNull fruitList: List<Int>) :
PagerAdapter() {
private val mContext = context
private var mFruitList: List<Int> = fruitList
override fun getCount(): Int {
return mFruitList.size
}
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view == `object`
}
override fun instantiateItem(container: ViewGroup, position: Int): Any {
return LayoutInflater.from(mContext).inflate(R.layout.item_gallery, container, false)
.apply {
val imgFruit: AppCompatImageView = findViewById(R.id.img_fruit)
imgFruit.setImageResource(mFruitList[position])
imgFruit.setOnClickListener {
Toast.makeText(mContext, "点击了第${position}个图片", Toast.LENGTH_SHORT).show()
}
tag = "gallery_item_$position"
container.addView(this)
}
}
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
container.removeView(`object` as View)
}
}
适配器条目布局item_gallery.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FCFCFC"
android:elevation="10dp"
app:cardCornerRadius="10dp"
app:contentPadding="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/img_fruit"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
tools:src="@drawable/fruit_image1" />
</androidx.cardview.widget.CardView>
用到的图片资源自己换一下好了
三.转换器
GalleryTransformer
控制滑动时候的各种属性变化,达到自定义滑动切换时候的炫酷效果。
package com.openld.seniorui.testgallery
import android.view.View
import androidx.viewpager.widget.ViewPager
/**
* author: lllddd
* created on: 2022/6/10 11:14
* description:
*/
class GalleryTransformer : ViewPager.PageTransformer {
private val MIN_SCALE = 0.5F
override fun transformPage(page: View, position: Float) {
if (position < 0F) {
page.scaleX = MIN_SCALE * position + 1.5F
page.scaleY = MIN_SCALE * position + 1.5F
page.alpha = MIN_SCALE * position + 1
// page.rotationY = 30F * position
page.rotation = 30 * position
} else {
page.scaleX = -MIN_SCALE * position + 1.5F
page.scaleY = -MIN_SCALE * position + 1.5F
page.alpha = -MIN_SCALE * position + 1
// page.rotationY = 30F * position
page.rotation = 30 * position
}
page.elevation = page.scaleX
}
}
这里效果的关键就是这个GalleryTransformer类,不明白原理的可以看下ViewPager.PageTransformer的相关源码或者解释。
就是page滑到中间的时候position为0,page在左侧时position取值区间为(-1, 0),page在右侧时position取值区间为(0, 1),根据这个再结合一些诸如alpha、scaleX、scaleY、rotation等属性的设置就能实现你要的切换效果啦。