前几天有同学要我帮忙写一个无限循环的scrollview,恰好之前看过一篇博文,是讲自定义scrollview实现多个view存在的scrollview滚动,就把原作者的代码修改了一下,变成了可以无限循环左右滑动的scrollview,交差啦。。
原博客地址http://blog.csdn.net/lmj623565791/article/details/38140505
主要的修改是在自定义scrollview的部分,其余部分可以完全参考上面的博客,建议先看完上面的文章再来读这篇博客,废话少说,上代码:
主要的修改是在loadNext()和loadPre();因为实现的目的是无限循环滑动,原文中的很多预留接口和监听都删掉了,需要的同学可以自己参照添加。
public class MyHorizontalScrollView extends HorizontalScrollView implements
View.OnClickListener {
private OnItemClickListener mOnClickListener;
private LinearLayout mContainer;
/**
* 子元素的宽度
*/
private int mChildWidth;
/**
* 子元素的高度
*/
private int mChildHeight;
/**
* 当前最后一张图片的index
*/
private int mCurrentIndex;
/**
* 当前第一张图片的下标
*/
private int mFristIndex;
/**
* 当前第一个View
*/
private View mFirstView;
/**
* 数据适配器
*/
// private HorizontalScrollViewAdapter mAdapter;
/**
* 每屏幕最多显示的个数
*/
private int mCountOneScreen;
/**
* 屏幕的宽度
*/
private int mScreenWitdh;
/**
* 保存View与位置的键值对
*/
private HorizontalScrollViewAdapter mAdapter;
private Map<View, Integer> mViewPos = new HashMap<View, Integer>();
public interface OnItemClickListener {
void onClick(View view, int pos);
}
public MyHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
mScreenWitdh = outMetrics.widthPixels;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mContainer = (LinearLayout) getChildAt(0);
}
public void initView(HorizontalScrollViewAdapter mAdapter) {
this.mAdapter = mAdapter;
mContainer = (LinearLayout) getChildAt(0);
View v = mAdapter.getView(0, null, mContainer);
;
mContainer.addView(v);// why add
if (mChildWidth == 0 && mChildHeight == 0) {
int w = View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
int h = View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
v.measure(w, h);
mChildHeight = v.getMeasuredHeight();
mChildWidth = v.getMeasuredWidth();
mCountOneScreen = mScreenWitdh / mChildWidth + 2;
}
initFirstScreenView(mCountOneScreen);
}
private void initFirstScreenView(int mCountOneScreen2) {
mContainer = (LinearLayout) getChildAt(0);
mContainer.removeAllViews();
mViewPos.clear();
for (int i = 0; i < mCountOneScreen; i++) {
View v = mAdapter.getView(i, null, mContainer);
v.setOnClickListener(this);
mContainer.addView(v);
mViewPos.put(v, i);
mCurrentIndex = i;
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_MOVE:
int scrollX = getScrollX();
if (scrollX >= mChildWidth) {
loadNext();
}
if (scrollX == 0) {
loadPre();
}
break;
}
return super.onTouchEvent(ev);
}
private void loadNext() {
View v;
scrollTo(0, 0);
mViewPos.remove(mContainer.getChildAt(0));
mContainer.removeViewAt(0);
if (mCurrentIndex == mAdapter.getCount() - 1) {
v = mAdapter.getView(0, null, mContainer);
mCurrentIndex = 0;
} else {
v = mAdapter.getView(++mCurrentIndex, null, mContainer);
}
v.setOnClickListener(this);
mContainer.addView(v);
mViewPos.put(v, mCurrentIndex);
mFristIndex++;
}
private void loadPre() {
int oldViewPos = mContainer.getChildCount() - 1;
if (mFristIndex == 0) {
mViewPos.remove(mContainer.getChildAt(oldViewPos));
mContainer.removeViewAt(oldViewPos);
View view = mAdapter.getView(mAdapter.getCount() - 1, null,
mContainer);
mViewPos.put(view, mAdapter.getCount() - 1);
mContainer.addView(view, 0);
view.setOnClickListener(this);
// 水平滚动位置向左移动view的宽度个像素
scrollTo(mChildWidth, 0);
mFristIndex = mAdapter.getCount() - 1;
} else {
int index = mCurrentIndex - mCountOneScreen;
if (index >= 0) {
mViewPos.remove(mContainer.getChildAt(oldViewPos));
mContainer.removeViewAt(oldViewPos);
View view = mAdapter.getView(index, null, mContainer);
mViewPos.put(view, index);
mContainer.addView(view, 0);
view.setOnClickListener(this);
// 水平滚动位置向左移动view的宽度个像素
scrollTo(mChildWidth, 0);
mFristIndex--;
} else {
mViewPos.remove(mContainer.getChildAt(oldViewPos));
mContainer.removeViewAt(oldViewPos);
View view = mAdapter.getView(index + mAdapter.getCount(), null,
mContainer);
mViewPos.put(view, index + mAdapter.getCount());
mContainer.addView(view, 0);
view.setOnClickListener(this);
// 水平滚动位置向左移动view的宽度个像素
scrollTo(mChildWidth, 0);
// 当前位置--,当前第一个显示的下标--
mFristIndex--;
}
}
mCurrentIndex = mViewPos
.get(mContainer.getChildAt(mCountOneScreen - 1));
}
@Override
public void onClick(View v) {
if (mOnClickListener != null) {
mOnClickListener.onClick(v, mViewPos.get(v));
}
}
}
最终效果
图片发不上来,最后的效果就是一个包含了很多控件的scrollview,可以实现左右无限滑动