参考《ViewPager smoothScroll 速度控制》,很不错的文章,用Kotlin改写记录如下:
自定义滑动控制类,以实现自定义滑动
/**
* <pre>
* author : jake
* time : 2018/11/20
* function : 控制ViewPager滑动速度
* version: 1.0
* </pre>
*
* 重写 startScroll方法,忽略传过来的 duration 值
*/
class FixedSpeedScroller : Scroller {
// var mDuration = 1500
var mDuration = 1200
constructor (context: Context) : super(context)
constructor (context: Context, interpolator: Interpolator) : super(context, interpolator)
constructor (context: Context, interpolator: Interpolator, flywheel: Boolean) : super(context, interpolator, flywheel)
override fun startScroll(startX: Int, startY: Int, dx: Int, dy: Int) {
super.startScroll(startX, startY, dx, dy, mDuration)
}
override fun startScroll(startX: Int, startY: Int, dx: Int, dy: Int, duration: Int) {
super.startScroll(startX, startY, dx, dy, mDuration)
}
fun getmDuration(): Int {
return mDuration
}
fun setmDuration(duration: Int) {
mDuration = duration
}
}
在自定义ViewPager中,通过反射,更改原生滑动控制类为自定义类
init {
/**
* 通过反射来修改 ViewPager的mScroller属性,以改变滑动速度
*/
try {
val clazz = Class.forName("android.support.v4.view.ViewPager")
val field = clazz.getDeclaredField("mScroller")
val fixedSpeedScroller = FixedSpeedScroller(context, LinearOutSlowInInterpolator())
fixedSpeedScroller.setmDuration(1200)
field.isAccessible = true
field.set(this, fixedSpeedScroller)
} catch (e: Exception) {
e.printStackTrace()
}
}
附ViewPager源码:
见自适应高度(最低高度为屏幕高度)& 横屏闪退不拉长页面 & 自定义滑动速度
/**
* <pre>
* author : jake
* time : 2018/07/09
* function : 控制是否可以左右滑动的viewpager & 自适应高度
* version: 1.0
* </pre>
*/
class ViewPagerAutoHeight : ViewPagerSlide {
private lateinit var maxList: ArrayList<Int>
constructor(context: Context) : super(context) {
maxList = ArrayList()
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
maxList = ArrayList()
}
init {
/**
* 通过反射来修改 ViewPager的mScroller属性,以改变滑动速度
*/
try {
val clazz = Class.forName("android.support.v4.view.ViewPager")
val field = clazz.getDeclaredField("mScroller")
val fixedSpeedScroller = FixedSpeedScroller(context, LinearOutSlowInInterpolator())
fixedSpeedScroller.setmDuration(1200)
field.isAccessible = true
field.set(this, fixedSpeedScroller)
} catch (e: Exception) {
e.printStackTrace()
}
}
// 自适应高度(根据内容区大小)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
var index = currentItem
var height = 0
var v = (adapter!!.instantiateItem(this, index) as Fragment).view
if (v != null) {
v.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED))
height = v.measuredHeight
/**
* 由于特殊情况,需要实现 viewpager 从开始位置 至 底部占满,超出屏幕才自适应高度
*
* 因为子任务提交按钮的位置,必须撑满屏幕才行,否则就要放到外层类中,进行消息传递,更麻烦
*
* 通用情况,可以去掉
*/
val systemHeight = if (appWidth > appHeight) appHeight else appWidth
if (height < systemHeight - top) {
height = systemHeight - top
maxList.add(height)
} else {
maxList.add(height)
}
height = maxList.max()!!
// ------------------------- 结束 --------------------------------------
}
var heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
override fun onPageScrolled(position: Int, offset: Float, offsetPixels: Int) {
super.onPageScrolled(position, offset, offsetPixels)
// 重新测量布局
maxList.clear()
requestLayout()
}
// 在退出页面的时候,清空最大值集合,以防止崩溃后,页面变长
fun clearMaxList() {
maxList?.clear()
}
}