前言
这次要在上一篇轮播图的基础上做改造,增加两个功能:
- 用户触摸到轮播图时,停止轮播
- 在轮播图上展示一个小指示器,指示当前轮播组件的位置
触摸停播
触摸停播的设计思路是:监听实现轮播图的触摸事件,如果用户正在触摸就停止自动轮播。
package com.example.loopapplication.looper;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.viewpager.widget.ViewPager;
public class TouchableViewPager extends ViewPager {
OnViewPagerTouchListener mOnViewPagerTouchListener;
public TouchableViewPager(@NonNull Context context) {
super(context);
}
public TouchableViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// 触摸开始
if (mOnViewPagerTouchListener != null) {
mOnViewPagerTouchListener.onPageTouched(true);
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
// 触摸结束
if (mOnViewPagerTouchListener != null) {
mOnViewPagerTouchListener.onPageTouched(false);
}
break;
}
return super.onTouchEvent(ev);
}
public void setOnTouchListener(TouchableViewPager.OnViewPagerTouchListener listener) {
mOnViewPagerTouchListener = listener;
}
public interface OnViewPagerTouchListener{
void onPageTouched(boolean isTouched);
}
}
mViewPager.setOnTouchListener(new TouchableViewPager.OnViewPagerTouchListener() {
@Override
public void onPageTouched(boolean isTouched) {
mIsTouch = isTouched;
}
});
private Runnable mLoopTask = new Runnable() {
@Override
public void run() {
if (!mIsTouch) {
int currentItems = mViewPager.getCurrentItem();
// 将当前组件序号自增,达到自动轮播的效果
mViewPager.setCurrentItem(++currentItems);
}
// 自动轮播间隔1秒
mHandler.postDelayed(this, 2000);
}
};
指示器
指示器的设计思路是:
轮播图初始化时,创建数据个数相等的小圆点,默认为未选中状态。
监听轮播图切换轮播视图事件,每次组件切换都遍历一次圆点,将对应当前数据位置的圆点改成选中态。
/**
* 初始化圆点阵列
*/
private void initPointIndication() {
mPointIndication = this.findViewById(R.id.point_indication);
for (int i = 0; i < mPictures.size(); i++) {
View viewPoint = new View(this);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewUtils.dp2dx(this, 15), ViewUtils.dp2dx(this, 15));
layoutParams.leftMargin = ViewUtils.dp2dx(this, 10);
viewPoint.setLayoutParams(layoutParams);
viewPoint.setBackground(getResources().getDrawable(R.drawable.shape_point_normal));
mPointIndication.addView(viewPoint);
}
}
/**
* 设置圆点选中态
* @param curPosition
*/
private void setPointIndication(int curPosition) {
if (mPointIndication != null) {
for (int i = 0; i < mPointIndication.getChildCount(); i++) {
View point = mPointIndication.getChildAt(i);
if (point != null) {
if (i == curPosition) {
Log.d(TAG, "setPointIndication: 选中 " + i);
point.setBackground(getResources().getDrawable(R.drawable.shape_point_selected));
} else {
point.setBackground(getResources().getDrawable(R.drawable.shape_point_normal));
}
}
}
}
}
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
// 轮播当前展示的位置 需要换算成数据里面的真实位置
int realPosition = 0;
if (mLooperPagerAdapter.getDataSize() != 0) {
realPosition = position % mLooperPagerAdapter.getDataSize();
}
Log.d(TAG, "onPageSelected: position = " + position + ", real position = " + realPosition + ", data size = " + mLooperPagerAdapter.getDataSize());
setPointIndication(realPosition);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});