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