无限循环的HorizontalScrollview

前几天有同学要我帮忙写一个无限循环的scrollview,恰好之前看过一篇博文,是讲自定义scrollview实现多个view存在的scrollview滚动,就把原作者的代码修改了一下,变成了可以无限循环左右滑动的scrollview,交差啦。。
原博客地址http://www.voidcn.com/article/p-xfdtlnon-kp.html
主要的修改是在自定义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,可以实现左右无限滑动

相关文章
相关标签/搜索