/**
* 订阅页面轮播图适配器
*
* @author ryze
* @since 1.0 2019/07/17
*/
public abstract class AutoLoopSwitchBaseAdapter extends PagerAdapter {
public AutoLoopSwitchBaseAdapter() {
}
public static final int VIEWPAGER_RADIX = 100;
/**
* 实际轮播图个数
*/
public abstract int getDataCount();
public abstract View getView(int position);
public abstract Object getItem(int position);
/**
* 如果数据为空的时候,这里最好不为空
*/
public abstract View getEmptyView();
/**
* 当数据改变时,ViewPager预加载的View需要重新设置数据
*/
public abstract void updateView(View view, int position);
@Override
public final int getCount() {
if (getDataCount() > 1) {
//如果轮播个数大于1个,那么需要轮播,增加基数,同时在首尾加上一个,
return getDataCount() * VIEWPAGER_RADIX + 2;
} else {
return getDataCount();
}
}
/**
* 得到实际页面index
*/
public final int getActualIndex(int index) {
int position = index;
if (getDataCount() > 1) {
if (index == 0) {
position = getDataCount() - 1;
} else if (index == getCount() - 1) {
position = 0;
} else {
position = index - 1;
}
}
return position;
}
/**
* @param container
* @param position
* @return
*/
@Override
public final Object instantiateItem(ViewGroup container, int position) {
position = getActualIndex(position);
position %= getDataCount();
View v = getView(position);
if (v == null) {
v = getEmptyView();
}
v.setTag(position);
container.addView(v);
return v;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// super.destroyItem(container, position, object);
container.removeView((View) object);
}
@Override
public final boolean isViewFromObject(View view, Object o) {
return view == o;
}
}
AutoLoopSwitchBaseView.java
/**
* 手动自动可以滚动
*
* @author ryze
* @since 1.0 2019/07/17
*/
public abstract class AutoLoopSwitchBaseView extends RelativeLayout implements ViewPager.OnPageChangeListener {
private final int VIEWPAGER_SCROLL_DURTION = 400;
protected ViewPager mViewPager;
protected PageShowView mPageShowView;
protected View mFailtView;
//
private int mCurrentItem = 1;
protected LoopHandler mHandler;
protected boolean mIsDragging = false;
protected AutoLoopSwitchBaseAdapter mPagerAdapter;
//监听数据变化,用于去除 重试View
private DataSetObserver mObserver;
//正在切页
private boolean isLoopSwitch = false;
private boolean mCurrentVisible = true;
public AutoLoopSwitchBaseView(Context context) {
super(context);
initView();
}
public AutoLoopSwitchBaseView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public AutoLoopSwitchBaseView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public AutoLoopSwitchBaseView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initView();
}
/**
* 页面切换回调
*
* @param model adapter getItem
*/
protected abstract void onSwitch(int index, Object model);
/**
* 滚动延时时间
*/
protected abstract long getDurtion();
/**
* 如果需要网络异常处理
*/
protected abstract View getFailtView();
@Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
if (visibility == VISIBLE) {
mCurrentVisible = true;
} else {
mCurrentVisible = false;
}
}
public boolean isCurrentVisible() {
return mCurrentVisible;
}
public void setCurrentVisible(boolean mCurrentVisible) {
this.mCurrentVisible = mCurrentVisible;
}
private void initView() {
mViewPager = new ViewPager(getContext());
mViewPager.setId(R.id.autoloopswitch_viewpager_id);
mViewPager.addOnPageChangeListener(this);
addView(mViewPager, generalLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
controlViewPagerSpeed();
LayoutParams params;
mPageShowView = new PageShowView(getContext());
mPageShowView.setId(R.id.autoloopswitch_pagershow_id);//此处以及上面的id为values下ids中的id 自己添加就好
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
params = generalLayoutParams(LayoutParams.MATCH_PARENT, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, displayMetrics));
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
params.addRule(RelativeLayout.CENTER_HORIZONTAL);
addView(mPageShowView, params);
mHandler = new LoopHandler(this);
}
private LayoutParams generalLayoutParams(int w, int h) {
LayoutParams params = new LayoutParams(w, h);
return params;
}
@Override
public void onPageScrolled(int i, float v, int i1) {
}
@Override
public void onPageSelected(int i) {
if (isLoopSwitch) {
isLoopSwitch = false;
return;
}
mCurrentItem = i;
int datacount = mPagerAdapter.getDataCount();
if (datacount > 1) {
int index = mPagerAdapter.getActualIndex(i) % datacount;
mPageShowView.setCurrentView(index, datacount);
onSwitch(index, mPagerAdapter.getItem(index));
}
}
@Override
public void onPageScrollStateChanged(int i) {
if (i == ViewPager.SCROLL_STATE_DRAGGING) {
mIsDragging = true;
} else if (i == ViewPager.SCROLL_STATE_IDLE) {
if (mViewPager.getCurrentItem() == 0) {
isLoopSwitch = true;
mViewPager.setCurrentItem(mPagerAdapter.getCount() - 2, false);
} else if (mViewPager.getCurrentItem() == mPagerAdapter.getCount() - 1) {
isLoopSwitch = true;
mViewPager.setCurrentItem(1, false);
}
mCurrentItem = mViewPager.getCurrentItem();
if (mIsDragging && mHandler != null) {
//如果从dragging状态到不是mIsDragging
mHandler.sendEmptyMessageDelayed(LoopHandler.MSG_UPDATE, getDurtion());
}
mIsDragging = false;
Log.e("ryze", "onPageScrollStateChanged " + i);
}
}
private void notifyDataSetChanged() {
if (mPagerAdapter != null) {
int datacount = mPagerAdapter.getDataCount();
int currentIndex = 0;
if (datacount > 1) {
mCurrentItem = mPagerAdapter.getCount() / 2;
currentIndex = mPagerAdapter.getActualIndex(mCurrentItem) % datacount;
} else {
mCurrentItem = 1;
currentIndex = 0;
}
mViewPager.setCurrentItem(mCurrentItem);
mPageShowView.setCurrentView(currentIndex, datacount);
if (mFailtView != null && datacount > 0) {
removeView(mFailtView);
mFailtView = null;
}
updateView();
}
}
private void updateView() {
for (int i = 0; i < mViewPager.getChildCount(); i++) {
View v = mViewPager.getChildAt(i);
if (v != null) {
int position = (Integer) v.getTag();
mPagerAdapter.updateView(v, position);
}
}
}
public void setAdapter(AutoLoopSwitchBaseAdapter adapter) {
if (mPagerAdapter != null) {
mPagerAdapter.unregisterDataSetObserver(mObserver);
}
this.mPagerAdapter = adapter;
if (mPagerAdapter != null) {
if (mObserver == null) {
mObserver = new PagerObserver();
}
mPagerAdapter.registerDataSetObserver(mObserver);
if (mViewPager != null) {
mViewPager.setAdapter(mPagerAdapter);
}
//如果没有数据,同时没有网络的情况
if (mPagerAdapter.getDataCount() <= 0) {
mFailtView = getFailtView();
if (mFailtView != null) {
addView(mFailtView, generalLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
}
}
} else {
throw new NullPointerException("AutoLoopSwitchBaseAdapter can not null");
}
}
public void destory() {
if (mHandler != null) {
mHandler.close();
}
}
protected static class LoopHandler extends Handler {
//请求更新显示的View。
private static final int MSG_UPDATE = 1;
//请求暂停轮播。
public static final int MSG_STOP = 2;
//请求恢复轮播。
public static final int MSG_REGAIN = 3;
private AutoLoopSwitchBaseView mView;
private boolean mIsStop = false;
public LoopHandler(AutoLoopSwitchBaseView mView) {
this.mView = new WeakReference<AutoLoopSwitchBaseView>(mView).get();
}
public boolean isStop() {
return mIsStop;
}
public void close() {
removeMessages(MSG_UPDATE);
removeMessages(MSG_REGAIN);
removeMessages(MSG_STOP);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (mView == null || mView.mHandler == null || mView.mPagerAdapter == null || mView.mIsDragging) {
return;
}
Log.e("ryze", "stop: " + mIsStop);
switch (msg.what) {
case MSG_UPDATE:
if (mIsStop || hasMessages(MSG_UPDATE)) {
return;
}
if (mView.mPagerAdapter.getCount() > 1) {
mView.mCurrentItem++;
mView.mCurrentItem %= mView.mPagerAdapter.getCount();
mView.mViewPager.setCurrentItem(mView.mCurrentItem, true);
sendEmptyMessageDelayed(MSG_UPDATE, mView.getDurtion());
}
break;
case MSG_STOP:
if (hasMessages(MSG_UPDATE)) {
removeMessages(MSG_UPDATE);
}
mIsStop = true;
Log.e("ryze", "stop: MSG_STOP " + mIsStop);
break;
case MSG_REGAIN:
if (hasMessages(MSG_UPDATE)) {
removeMessages(MSG_UPDATE);
}
sendEmptyMessageDelayed(MSG_UPDATE, mView.getDurtion());
mIsStop = false;
Log.e("ryze", "stop: MSG_REGAIN " + mIsStop);
break;
}
}
}
private class PagerObserver extends DataSetObserver {
private PagerObserver() {
}
public void onChanged() {
Log.e("ryze", "PagerObserver onChanged ");
notifyDataSetChanged();
}
public void onInvalidated() {
Log.e("ryze", "PagerObserver onInvalidated ");
notifyDataSetChanged();
}
}
public ViewPager getViewPager() {
return mViewPager;
}
private void controlViewPagerSpeed() {
try {
Field mField;
mField = ViewPager.class.getDeclaredField("mScroller");
mField.setAccessible(true);
FixedSpeedScroller mScroller = new FixedSpeedScroller(getContext(),
new DecelerateInterpolator());
mScroller.setmDuration(VIEWPAGER_SCROLL_DURTION);
mField.set(mViewPager, mScroller);
mField = ViewPager.class.getDeclaredField("mFlingDistance");
mField.setAccessible(true);
mField.set(mViewPager, 20);
} catch (Exception e) {
e.printStackTrace();
}
}
private class FixedSpeedScroller extends Scroller {
private int mDuration = 600; // default time is 600ms
public FixedSpeedScroller(Context context) {
super(context);
}
public FixedSpeedScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
// Ignore received duration, use fixed one instead
super.startScroll(startX, startY, dx, dy, mDuration);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy) {
// Ignore received duration, use fixed one instead
super.startScroll(startX, startY, dx, dy, mDuration);
}
/**
* set animation time
*/
public void setmDuration(int time) {
mDuration = time;
}
/**
* get current animation time
*/
public int getmDuration() {
return mDuration;
}
}
}
AutoSwitchView.java
public class AutoSwitchView extends AutoLoopSwitchBaseView {
public AutoSwitchView(Context context) {
super(context);
}
public AutoSwitchView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AutoSwitchView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public AutoSwitchView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onSwitch(int index, Object o) {
GoodsPojo model = (GoodsPojo) o;
if (model != null) {
}
}
@Override
protected View getFailtView() {
return null;
}
@Override
protected long getDurtion() {
return 3000;
}
@Override
public void setAdapter(AutoLoopSwitchBaseAdapter adapter) {
super.setAdapter(adapter);
mHandler.sendEmptyMessage(LoopHandler.MSG_REGAIN);
}
public void setFocusable(boolean f){
mViewPager.setFocusable(f);
}
}
PageShowView.java
public class PageShowView extends View {
int colorCurrent = 0;
int colorOther = 0;
int total = 0;
int current = 0;
private Paint mPaint = null;
public PageShowView(Context context) {
this(context, null);
}
public PageShowView(Context context, AttributeSet attrs) {
super(context, attrs);
initColor();
}
protected void initColor() {
colorCurrent = getResources().getColor(R.color.colorPrimary);//当前显示的图片页码颜色
colorOther = getResources().getColor(R.color.gray_99);//其余的页码颜色
mPaint = new Paint();
}
public void setCurrentView(int current, int total) {
this.current = current;
this.total = total;
invalidate();
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
int view_height = getHeight() - getPaddingBottom() - getPaddingBottom();
int view_width = getWidth() - getPaddingLeft() - getPaddingRight();
int height = view_height / 6;
int width = height * 4;
if (total > 1) {
if (width * total + height * (total - 1) > view_width) {
width = (view_width - (height * (total - 1))) / total;
}
int posX = view_width / 2 - (width * total + height * (total - 1) * 3) / 2;
mPaint.setStrokeWidth(height);
mPaint.setAntiAlias(false);
for (int i = 0; i < total; i++) {
if (i != current) {
mPaint.setColor(colorOther);
} else {
mPaint.setColor(colorCurrent);
}
canvas.drawCircle(posX, view_height / 3, view_height / 3, mPaint);
posX += height * 3 + width;
}
}
}
/**
* 获取当前显示的位置
*/
public int getCurrent() {
return this.current;
}
}
AutoSwitchAdapter.java
public class AutoSwitchAdapter extends AutoLoopSwitchBaseAdapter {
private Context mContext;
//GoodsPojo是实体类 你可以根据你自己的需求替换
private List<GoodsPojo> mDatas;
public AutoSwitchAdapter() {
super();
}
public AutoSwitchAdapter(Context mContext, List<GoodsPojo> mDatas) {
this.mContext = mContext;
this.mDatas = mDatas;
}
@Override
public int getDataCount() {
return mDatas == null ? 0 : mDatas.size();
}
@Override
public View getView(final int position) {
ImageView imageView = new ImageView(mContext);
imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT));
final GoodsPojo pojo = (GoodsPojo) getItem(position);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
GlideImageLoader.onDisplayImage(mContext,imageView,mDatas.get(position).url);
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View _view) {
//此处写图片点击事件
}
});
return imageView;
}
@Override
public Object getItem(int position) {
if (position >= 0 && position < getDataCount()) {
return mDatas.get(position);
}
return null;
}
@Override
public View getEmptyView() {
return null;
}
@Override
public void updateView(View view, int position) {
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
}
}
xml布局文件中使用
<com.****.****.AutoSwitchView /*此处为AutoSwitchView的绝对路径*/
android:id="@+id/vp"
android:layout_width="match_parent"
android:layout_height="160dp"
app:layout_scrollFlags="scroll"/>
代码中调用
vp.setAdapter(new AutoSwitchAdapter(Context,GoodsPojos));