最近想要实现一个自定义一个viewPager实现广播轮播的效果,但是网上找了许多很多杰作,有的并不是太好比如改写view count的值为Int的最大值什么的,有的就是嵌套其他东西太多,我只想要个轮播的viewPager而他的包里包含了太多其他东西/(ㄒoㄒ)/~~;
所以还是还是手撸一个吧;实现的思路就是改写viewPager用postDelayed来实现轮播,并且还要解决手指拖拽viewPager时自动轮播要停止的问题;so,上代码吧(Kotlin版):
1.定义Runnable
private val autoScrollRunnable = object : Runnable {
override fun run() {
if (currentItem == adapter.count - 1) {
// currentItem = 0
setCurrentItem(0, false)
} else {
currentItem += 1
}
postDelayed(this, duration.toLong())
}
}
2.定义styleable方便自定义使用
<declare-styleable name="AutoScrollViewPager">
<attr format="boolean" name="indeterminate"/>
<attr format="boolean" name="autoScroll"/>
<attr format="integer" name="duration"/>
</declare-styleable>
private val default_duration = 2000
var duration = default_duration
//是否自动滚动
private var autoScroll = true
//是否循环滚动
private var indeterminate = true
private var startX = 0f
constructor(context: Context) : this(context, null)
init {
var typeArray = context.obtainStyledAttributes(attrs, R.styleable.AutoScrollViewPager)
duration = typeArray.getInt(R.styleable.AutoScrollViewPager_duration, default_duration)
setAutoScrollEnabled(typeArray.getBoolean(R.styleable.AutoScrollViewPager_autoScroll, true))
indeterminate = typeArray.getBoolean(R.styleable.AutoScrollViewPager_indeterminate, true)
typeArray.recycle()
}
3.定义一些方法
internal fun setAutoScrollEnabled(value: Boolean) {
autoScroll = value
if (autoScroll) {
startAutoScroll()
}
}
private fun startAutoScroll() {
stopAutoScroll()
postDelayed(autoScrollRunnable, duration.toLong())
}
private fun stopAutoScroll() {
removeCallbacks(autoScrollRunnable)
}
4. 自动调用轮播
override fun onAttachedToWindow() {
super.onAttachedToWindow()
setAutoScrollEnabled(autoScroll)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
stopAutoScroll()
}
override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
super.onWindowFocusChanged(hasWindowFocus)
if (hasWindowFocus) {
setAutoScrollEnabled(autoScroll)
} else {
stopAutoScroll()
}
}
这里会涉及到一个问题,就是View的post(Runnable)方法非100%执行,原因和处理方法在这里
5.手指拖拽viewPager时停止自动轮播
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
try {
when(event.actionMasked){
MotionEvent.ACTION_DOWN ->{
//按下手指停止自动滚动
stopAutoScroll()
startX = event.x
}
}
return super.onInterceptTouchEvent(event)
} catch (e: Exception) {
JLog.e(e)
}
return true
}
override fun onTouchEvent(ev: MotionEvent): Boolean {
try {
when (ev.action and MotionEvent.ACTION_MASK) {
MotionEvent.ACTION_UP -> {
//如果indeterminate为true则手指滑动到最后一个时再滑动则跳到一个view
if (indeterminate
&& (currentItem == 0 || currentItem == adapter.count - 1)) {
if (currentItem == adapter.count - 1
&& (ev.x < startX && startX - ev.x > 50)) {
postDelayed({ setCurrentItem(0, false) },
100)
}
}
//移开手指开始自动滚动
startAutoScroll()
}
}
return super.onTouchEvent(ev)
} catch (e: Exception) {
JLog.e(e)
}
return false
}
这就ok了,最后奉上完整代码,Java版本的会后续补上✧(≖ ◡ ≖):
/**
* Created by JokAr on 2017/6/22.
*/
open class AutoScrollViewPager @JvmOverloads constructor(context: Context, attrs: AttributeSet?)
: ViewPager(context, attrs) {
private val default_duration = 2000
var duration = default_duration
//是否自动滚动
private var autoScroll = true
//是否循环滚动
private var indeterminate = true
private var startX = 0f
constructor(context: Context) : this(context, null)
init {
var typeArray = context.obtainStyledAttributes(attrs, R.styleable.AutoScrollViewPager)
duration = typeArray.getInt(R.styleable.AutoScrollViewPager_duration, default_duration)
setAutoScrollEnabled(typeArray.getBoolean(R.styleable.AutoScrollViewPager_autoScroll, true))
indeterminate = typeArray.getBoolean(R.styleable.AutoScrollViewPager_indeterminate, true)
typeArray.recycle()
}
private val autoScrollRunnable = object : Runnable {
override fun run() {
if (currentItem == adapter.count - 1) {
// currentItem = 0
setCurrentItem(0, false)
} else {
currentItem += 1
}
postDelayed(this, duration.toLong())
}
}
internal fun setAutoScrollEnabled(value: Boolean) {
autoScroll = value
if (autoScroll) {
startAutoScroll()
}
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
setAutoScrollEnabled(autoScroll)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
stopAutoScroll()
}
override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
super.onWindowFocusChanged(hasWindowFocus)
if (hasWindowFocus) {
setAutoScrollEnabled(autoScroll)
} else {
stopAutoScroll()
}
}
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
try {
when(event.actionMasked){
MotionEvent.ACTION_DOWN ->{
//按下手指停止自动滚动
stopAutoScroll()
startX = event.x
}
}
return super.onInterceptTouchEvent(event)
} catch (e: Exception) {
JLog.e(e)
}
return true
}
override fun onTouchEvent(ev: MotionEvent): Boolean {
try {
when (ev.action and MotionEvent.ACTION_MASK) {
MotionEvent.ACTION_UP -> {
//如果indeterminate为true则手指滑动到最后一个时再滑动则跳到一个view
if (indeterminate
&& (currentItem == 0 || currentItem == adapter.count - 1)) {
if (currentItem == adapter.count - 1
&& (ev.x < startX && startX - ev.x > 50)) {
postDelayed({ setCurrentItem(0, false) },
100)
}
}
//移开手指开始自动滚动
startAutoScroll()
}
}
return super.onTouchEvent(ev)
} catch (e: Exception) {
JLog.e(e)
}
return false
}
private fun startAutoScroll() {
stopAutoScroll()
postDelayed(autoScrollRunnable, duration.toLong())
}
private fun stopAutoScroll() {
removeCallbacks(autoScrollRunnable)
}
}