自定义ScrollView的刷新加载

准备工作:
创建一个library
资源文件:
color:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <color name="white">#ffffffff</color>
    <color name="black">#ff000000</color>
    <color name="transparent">#00000000</color>
</resources>

strings.xml

<resources>
    <string name="app_name">Refreshlayout</string>

    <string name="xscrollview_header_hint_normal">下拉刷新</string>
    <string name="xscrollview_header_hint_ready">松开刷新</string>
    <string name="xscrollview_header_hint_loading">加载数据...</string>
    <string name="xscrollview_header_last_time">最近刷新</string>
    <string name="xscrollview_footer_hint_normal">加载更多</string>
    <string name="xscrollview_footer_hint_ready">松开加载</string>
</resources>

layout:

1.xscrollview.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="1200dp"
    android:orientation="vertical" >

    <FrameLayout
        android:id="@+id/head_ly"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_marginTop="-60dp" >
    </FrameLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <RelativeLayout
            android:id="@+id/content_ly"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />

        <FrameLayout
            android:id="@+id/foot_ly"
            android:layout_width="match_parent"
            android:layout_height="40dp" >
        </FrameLayout>
    </LinearLayout>

</LinearLayout>

2.xscrollview_header.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="bottom" >

    <RelativeLayout
        android:id="@+id/xscrollview_header_content"
        android:layout_width="fill_parent"
        android:layout_height="60dp" >

        <LinearLayout
            android:id="@+id/xscrollview_header_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:gravity="center"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/xscrollview_header_hint_textview"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/xscrollview_header_hint_normal" />

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="3dp" >

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/xscrollview_header_last_time"
                    android:textSize="12sp" />

                <TextView
                    android:id="@+id/xscrollview_header_time"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="12sp" />
            </LinearLayout>
        </LinearLayout>

        <ImageView
            android:id="@+id/xscrollview_header_arrow"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@id/xscrollview_header_text"
            android:layout_centerVertical="true"
            android:layout_marginLeft="-75dp"
            android:src="@mipmap/xscrollview_arrow" />

        <ProgressBar
            android:id="@+id/xscrollview_header_progressbar"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_alignLeft="@id/xscrollview_header_text"
            android:layout_centerVertical="true"
            android:layout_marginLeft="-80dp"
            android:visibility="invisible" />
    </RelativeLayout>

</LinearLayout>

3.xscrollview_footer.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >

    <RelativeLayout
        android:id="@+id/xscrollview_footer_content"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="10dp" >

        <ProgressBar
            android:id="@+id/xscrollview_footer_progressbar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:visibility="invisible" />

        <TextView
            android:id="@+id/xscrollview_footer_hint_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="@string/xscrollview_footer_hint_normal" />
    </RelativeLayout>

</LinearLayout>

Java

1.XScrollView

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * 可以下拉刷新的scrollView
 * 
 */
public class XScrollView extends ScrollView {

    private static final int PULL_TO_REFRESH_STATUS = 0x00;    // 下拉刷新
    private static final int RELEASE_TO_REFRESH_STATUS = 0x01; // 释放刷新
    protected static final int REFRESHING_STATUS = 0x02;
    private static final int NORMAL_STATUS = 0x03;

    // mode head or foot
    private static final int HEAD_MODE = 0x00;
    private static final int FOOT_MODE = 0x01;
    protected int mStatus = NORMAL_STATUS;
    private int mMode = HEAD_MODE;
    protected RelativeLayout mContentLy;
    private float mLastY = -1000;
    private FrameLayout mHeadViewLy;
    private FrameLayout mFootViewLy;
    private TextView mHeaderTimeView;

    private float mDowY;

    private final static int PULL_LOAD_MORE_DELTA = 50;

    private ILoadingLayout mHeadLoadingView;
    private ILoadingLayout mFootLoadingView;

    private boolean mIsAnimation;
    private int mDefautlTopMargin;
    private boolean mEnablePullRefresh = true;
    private boolean mEnablePullLoad = true;

    private final static int SCROLL_DURATION = 200;

    private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm",
            Locale.getDefault());

    public interface OnScrollUpDownListener {
        public void onScrollUp(boolean isUp);
    }

    private OnScrollUpDownListener mScrollUpDown;
    private IXScrollViewListener mScrollViewListener;

    public XScrollView(Context context) {
        this(context, null);
    }

    public XScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);

        View view = LayoutInflater.from(context).inflate(R.layout.xscrollview,
                null, false);
        ViewGroup.LayoutParams params = generateLayoutParams(attrs);
        super.addView(view, params);

        mContentLy = (RelativeLayout) findViewById(R.id.content_ly);
        mHeadViewLy = (FrameLayout) findViewById(R.id.head_ly);
        mFootViewLy = (FrameLayout) findViewById(R.id.foot_ly);
        mHeadLoadingView = new HeadLoadingView(context);
        mHeaderTimeView = (TextView) ((View) mHeadLoadingView)
                .findViewById(R.id.xscrollview_header_time);

        mFootLoadingView = new FootLoadingView(context);
        mHeadViewLy.addView((View) mHeadLoadingView);
        mFootViewLy.addView((View) mFootLoadingView);
        mHeadLoadingView.normal();
        mFootLoadingView.normal();

        mHeadViewLy.getViewTreeObserver().addOnGlobalLayoutListener(
                new OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        mDefautlTopMargin = -mHeadViewLy.getHeight();
                        getViewTreeObserver()
                                .removeGlobalOnLayoutListener(this);
                    }
                });

        setFadingEdgeLength(0);
        setRefreshTime();
    }

    public void addView(View child, ViewGroup.LayoutParams params) {
        mContentLy.addView(child, params);
    }

    public void setOnScrollUpDownListener(OnScrollUpDownListener listener) {
        mScrollUpDown = listener;
    }

    public void stopRefresh() {
        MaginAnimation maginAnim = new MaginAnimation(0,
                (int) mDefautlTopMargin, SCROLL_DURATION);
        maginAnim.startAnimation(mHeadViewLy);
        maginAnim.setOnAnimationOverListener(new OnAnimationOverListener() {
            @Override
            public void onOver() {
                updateStatus(NORMAL_STATUS, mHeadLoadingView);
            }
        });
        setRefreshTime();
    }

    public void stopLoadMore() {
        updateStatus(NORMAL_STATUS, mFootLoadingView);
    }

    /**
     * 显示和隐藏下拉刷新
     * @param enable
     */
    public void setPullRefreshEnable(boolean enable) {
        if (enable) {
            mEnablePullRefresh = true;
            mHeadViewLy.setVisibility(View.VISIBLE);
        } else {
            mEnablePullRefresh = false;
            mHeadViewLy.setVisibility(View.INVISIBLE);
        }
    }

    /**
     * 显示和隐藏上拉加载
     * @param enable
     */
    public void setPullLoadEnable(boolean enable) {
        if (enable) {
            mEnablePullLoad = true;
            mFootViewLy.setVisibility(View.VISIBLE);
        } else {
            mEnablePullLoad = false;
            mFootViewLy.setVisibility(View.INVISIBLE);
            LinearLayout.LayoutParams lllp = (LinearLayout.LayoutParams) mFootViewLy
                    .getLayoutParams();
            lllp.height = 0;
            mFootViewLy.setLayoutParams(lllp);
        }
    }

    private void setRefreshTime() {
        mHeaderTimeView.setText(sdf.format(new Date()));
    }

    public void setToRefreshing() {
        MaginAnimation maginAnim = new MaginAnimation(getHeadViewTopMargin(),
                0, SCROLL_DURATION);
        maginAnim.startAnimation(mHeadViewLy);
        maginAnim.setOnAnimationOverListener(new OnAnimationOverListener() {
            @Override
            public void onOver() {
                updateStatus(REFRESHING_STATUS, mHeadLoadingView);
            }
        });
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (mIsAnimation) {
            return super.onTouchEvent(ev);
        }
        int action = ev.getAction();
        switch (action) {
        case MotionEvent.ACTION_DOWN:
            mLastY = ev.getY();
            mDowY = ev.getY();
            break;
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            if (null != mScrollUpDown) {
                if (ev.getY() - mDowY >= 20) {
                    mScrollUpDown.onScrollUp(true);
                } else if (ev.getY() - mDowY <= -30) {
                    mScrollUpDown.onScrollUp(false);
                }
            }
            release(mStatus);
            mLastY = -1000;
            break;
        case MotionEvent.ACTION_MOVE:
            // 判断是不是首次移动
            if (-1000 == mLastY) {
                mLastY = ev.getY();
                mDowY = ev.getY();
                return super.onTouchEvent(ev);
            }
            final float lastY = mLastY;
            float nowY = ev.getY();
            int deltaY = (int) (lastY - nowY);
            mLastY = nowY;
            if (deltaY < 0) {
                // down
                if (getScrollY() == 0 && mStatus != REFRESHING_STATUS) {

                    updateMode(HEAD_MODE);
                    updateHeadMargin(deltaY / 2);

                    if (getHeadViewTopMargin() >= 0) {
                        updateStatus(RELEASE_TO_REFRESH_STATUS,
                                mHeadLoadingView);
                    } else {
                        updateStatus(PULL_TO_REFRESH_STATUS, mHeadLoadingView);
                    }

                    return super.onTouchEvent(ev);
                }

                if (mStatus != REFRESHING_STATUS && mStatus != NORMAL_STATUS) {
                    // foot
                    updateMode(FOOT_MODE);
                    updateFootPadding(deltaY / 2);

                    if (getPaddingBottom() > 0
                            && getPaddingBottom() < PULL_LOAD_MORE_DELTA) {

                        updateStatus(PULL_TO_REFRESH_STATUS, mFootLoadingView);

                    } else if (getPaddingBottom() >= PULL_LOAD_MORE_DELTA) {
                        updateStatus(RELEASE_TO_REFRESH_STATUS,
                                mFootLoadingView);
                    } else if (getPaddingBottom() == 0) {
                        updateStatus(NORMAL_STATUS, mFootLoadingView);
                    }

                }

            } else {
                // up
                if (mMode == HEAD_MODE && mStatus != REFRESHING_STATUS
                        && mStatus != NORMAL_STATUS) {
                    // head

                    updateMode(HEAD_MODE);
                    updateHeadMargin(deltaY / 2);
                    if (getHeadViewTopMargin() > mDefautlTopMargin
                            && getHeadViewTopMargin() < 0) {
                        if (mEnablePullRefresh) {
                            updateStatus(PULL_TO_REFRESH_STATUS,
                                    mHeadLoadingView);
                        }
                    } else if (getHeadViewTopMargin() == mDefautlTopMargin) {
                        updateStatus(NORMAL_STATUS, mHeadLoadingView);
                    }
                    return super.onTouchEvent(ev);
                }
                if (getScrollY() + getHeight() >= mContentLy.getHeight()
                        + mFootViewLy.getHeight()
                        && mStatus != REFRESHING_STATUS) {
                    // foot

                    updateMode(FOOT_MODE);
                    updateFootPadding(deltaY / 2);
                    if (getPaddingBottom() >= PULL_LOAD_MORE_DELTA) {
                        updateStatus(RELEASE_TO_REFRESH_STATUS,
                                mFootLoadingView);
                    } else {
                        updateStatus(PULL_TO_REFRESH_STATUS, mFootLoadingView);
                    }
                }
            }

            break;
        default:
            break;
        }
        return super.onTouchEvent(ev);
    }

    private void updateHeadMargin(int deltaY) {
        LinearLayout.LayoutParams param = (LinearLayout.LayoutParams) mHeadViewLy
                .getLayoutParams();
        param.topMargin -= deltaY;
        if (param.topMargin <= mDefautlTopMargin) {
            param.topMargin = (int) mDefautlTopMargin;
        }

        mHeadViewLy.setLayoutParams(param);
    }

    private void updateFootPadding(int deltaY) {
        int bottomPadding = getPaddingBottom() + deltaY;
        if (bottomPadding <= 0) {
            bottomPadding = 0;
        }
        setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(),
                bottomPadding);
    }

    private void updateStatus(int status, ILoadingLayout layout) {
        if (mStatus == status) {
            return;
        }
        mStatus = status;
        switch (status) {
        case PULL_TO_REFRESH_STATUS:
            layout.pullToRefresh();  // 下拉刷新
            break;
        case RELEASE_TO_REFRESH_STATUS:
            layout.releaseToRefresh();
            break;
        case REFRESHING_STATUS:
            layout.refreshing();
            break;
        case NORMAL_STATUS:
            layout.normal();
            break;
        default:
            break;
        }
    }

    private void updateMode(int mode) {
        mMode = mode;
    }

    private int getHeadViewTopMargin() {
        LinearLayout.LayoutParams param = (LinearLayout.LayoutParams) mHeadViewLy
                .getLayoutParams();
        return param.topMargin;
    }

    private void release(int status) {
        if (HEAD_MODE == mMode) {
            headReleas();
        } else if (FOOT_MODE == mMode) {
            footReleas();
        }

    }

    private void headReleas() {
        int toMagin;
        if (RELEASE_TO_REFRESH_STATUS == mStatus) {
            toMagin = 0;
        } else if (PULL_TO_REFRESH_STATUS == mStatus) {
            toMagin = (int) mDefautlTopMargin;
        } else {
            return;
        }
        MaginAnimation maginAnim = new MaginAnimation(getHeadViewTopMargin(),
                toMagin, SCROLL_DURATION);
        maginAnim.startAnimation(mHeadViewLy);
        maginAnim.setOnAnimationOverListener(new OnAnimationOverListener() {
            @Override
            public void onOver() {
                if (mStatus == RELEASE_TO_REFRESH_STATUS) {
                    if (null != mScrollViewListener) {
                        updateStatus(REFRESHING_STATUS, mHeadLoadingView);
                        if (mEnablePullRefresh) {
                            mScrollViewListener.onRefresh();
                        } else {
                            stopRefresh();
                        }
                    }
                } else if (mStatus == PULL_TO_REFRESH_STATUS) {
                    updateStatus(NORMAL_STATUS, mHeadLoadingView);
                }
            }
        });
    }

    private void footReleas() {
        if (getPaddingBottom() > PULL_LOAD_MORE_DELTA) {
            if (null != mScrollViewListener) {
                updateStatus(REFRESHING_STATUS, mFootLoadingView);
                if (mEnablePullLoad) {
                    mScrollViewListener.onLoadMore();
                } else {
                    stopLoadMore();
                }
            }
        } else {
            updateStatus(NORMAL_STATUS, mFootLoadingView);
        }
        updateFootPadding(-getPaddingBottom());
    }

    public interface IXScrollViewListener {
        public void onRefresh();

        public void onLoadMore();
    }

    public void setXScrollViewListener(IXScrollViewListener l) {
        mScrollViewListener = l;
    }
}

2.OnAnimationOverListener

public interface OnAnimationOverListener {
    void onOver();
}

3.MaginAnimation

import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;

import java.util.Timer;
import java.util.TimerTask;

public class MaginAnimation {
    // top magin

    private int mStep = 5;
    private int mPeriod = 10;
    private int mToMaing;
    private boolean mIsOver = false;
    private OnAnimationOverListener mOverListener;

    public MaginAnimation(int startMagin, int toMagin, int duration) {
        float abs = Math.abs(startMagin - toMagin);
        float a = abs / (float) mStep;
        mToMaing = toMagin;
        Log.d("abs / mStep > ", "start " + startMagin + " to margin" + toMagin);
        mPeriod = (int) ((float) duration / a);
        Log.d("the period period is ", mPeriod + "");
    }

    public void setOnAnimationOverListener(OnAnimationOverListener l) {
        mOverListener = l;
    }

    public void startAnimation(final View view) {
        mIsOver = false;
        final Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                view.post(new Runnable() {
                    @Override
                    public void run() {
                        LinearLayout.LayoutParams param = (LinearLayout.LayoutParams) view
                                .getLayoutParams();
                        param.topMargin -= mStep;
                        if (param.topMargin <= mToMaing) {
                            param.topMargin = mToMaing;
                            timer.cancel();
                            mIsOver = true;
                        }
                        view.setLayoutParams(param);
                        if (mIsOver && null != mOverListener) {
                            mOverListener.onOver();
                        }
                    }
                });
            }
        }, 0, mPeriod);
    }
}

4.ILoadingLayout

public interface ILoadingLayout {
    public void pullToRefresh();

    public void releaseToRefresh();

    public void refreshing();

    public void normal();
}

5.HeadLoadingView

public class HeadLoadingView extends LinearLayout implements ILoadingLayout {

    private Animation mRotateUpAnim;
    private Animation mRotateDownAnim;
    private View mLeftProgress;
    private ImageView mLeftImage;
    private TextView mTitle;
    private boolean mImageIsUp;

    private final int ROTATE_ANIM_DURATION = 180;

    public HeadLoadingView(Context context) {
        this(context, null);

        mRotateUpAnim = new RotateAnimation(0.0f, -180.0f,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                0.5f);
        mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);
        mRotateUpAnim.setFillAfter(true);
        mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                0.5f);
        mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);
        mRotateDownAnim.setFillAfter(true);

        LayoutInflater.from(context).inflate(R.layout.xscrollview_header, this);
        mLeftProgress = (ProgressBar) findViewById(R.id.xscrollview_header_progressbar);
        mLeftImage = (ImageView) findViewById(R.id.xscrollview_header_arrow);
        mTitle = (TextView) findViewById(R.id.xscrollview_header_hint_textview);
    }

    public HeadLoadingView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void pullToRefresh() {
        if (mImageIsUp) {
            mLeftImage.startAnimation(mRotateDownAnim);
            mImageIsUp = false;
        }
        mTitle.setText(getResources().getString(
                R.string.xscrollview_header_hint_normal));
    }

    @Override
    public void releaseToRefresh() {
        mLeftImage.startAnimation(mRotateUpAnim);
        mImageIsUp = true;
        mTitle.setText(getResources().getString(
                R.string.xscrollview_header_hint_ready));
    }

    @Override
    public void refreshing() {
        mImageIsUp = false;
        mLeftProgress.setVisibility(View.VISIBLE);
        mTitle.setText(getResources().getString(
                R.string.xscrollview_header_hint_loading));
        mLeftImage.clearAnimation();
        mLeftImage.setVisibility(View.INVISIBLE);
    }

    @Override
    public void normal() {
        mImageIsUp = false;
        mLeftImage.setVisibility(View.VISIBLE);
        mLeftProgress.setVisibility(View.GONE);
        mTitle.setText(getResources().getString(
                R.string.xscrollview_header_hint_normal));
    }

}

6.FootLoadingView

public class FootLoadingView extends LinearLayout implements ILoadingLayout {

    private TextView mTitleTv;
    private ProgressBar mProgress;

    public FootLoadingView(Context context) {
        this(context, null);
    }

    public FootLoadingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        inflate(context, R.layout.xscrollview_footer, this);
        mTitleTv = (TextView) findViewById(R.id.xscrollview_footer_hint_textview);
        mProgress = (ProgressBar) findViewById(R.id.xscrollview_footer_progressbar);
    }

    @Override
    public void pullToRefresh() {
        mTitleTv.setVisibility(View.VISIBLE);
        mTitleTv.setText(getResources().getString(
                R.string.xscrollview_footer_hint_normal));
    }

    @Override
    public void releaseToRefresh() {
        mTitleTv.setVisibility(View.VISIBLE);
        mTitleTv.setText(getResources().getString(
                R.string.xscrollview_footer_hint_ready));
    }

    @Override
    public void refreshing() {
        mTitleTv.setVisibility(View.INVISIBLE);
        mProgress.setVisibility(View.VISIBLE);
    }

    @Override
    public void normal() {
        mTitleTv.setVisibility(View.VISIBLE);
        mTitleTv.setText(getResources().getString(
                R.string.xscrollview_footer_hint_normal));
        mProgress.setVisibility(View.GONE);
    }

}

最后补上一张图片:

这里写图片描述

到此,library中的内容已完成

附加两个常用的view 在ScrollView嵌套的时候用
1.BounceListView

public class BounceListView extends ListView {

    public BounceListView(Context context) {
        super(context);

    }

    public BounceListView(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    public BounceListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);

        super.onMeasure(widthMeasureSpec, expandSpec);
    }

}

2.BounceGridView

public class BounceGridView extends GridView {

    public BounceGridView(Context context) {
        super(context);

    }

    public BounceGridView(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    public BounceGridView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);

        super.onMeasure(widthMeasureSpec, expandSpec);
    }

}

创建一个项目,依赖上面的library

布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white" >

    <com.*****.refreshlibrary.view.XScrollView
        android:id="@+id/scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <com.*****.refreshlibrary.view.BounceListView
                android:id="@+id/item_list"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:divider="@null"
                android:listSelector="@color/transparent" />

        </LinearLayout>
    </com.*****.refreshlibrary.view.XScrollView>

</RelativeLayout>

调用代码:

public class XScrollViewActivity extends Activity {

    private XScrollView scrollView = null;
    private ArrayList<String> nameArray = new ArrayList<>();
    private ItemAdapter itemAdapter = null;
    private Random random = new Random();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.xscroll_view_activity);
        initView();
    }

    private void initView() {

        scrollView = (XScrollView) findViewById(R.id.scroll);
        scrollView.setXScrollViewListener(new XScrollView.IXScrollViewListener() {

            @Override
            public void onRefresh() {
                handler.sendMessageDelayed(handler.obtainMessage(1), 1000);
            }

            @Override
            public void onLoadMore() {
                handler.sendMessageDelayed(handler.obtainMessage(2), 1000);
            }
        });

        scrollView.setPullLoadEnable(false); // 取消上拉加载

        BounceListView itemListView = (BounceListView) findViewById(R.id.item_list);
        itemAdapter = new ItemAdapter(this,nameArray);
        itemListView.setAdapter(itemAdapter);
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1) {
                nameArray.clear();
                for (int i = 0; i < 20; i++) {
                    nameArray.add("name" + random.nextInt());
                }
                itemAdapter.notifyDataSetChanged();
                scrollView.stopRefresh();  // 停止刷新
                scrollView.smoothScrollTo(0, 0); // 滚动的时候平滑的效果
            } else if (msg.what == 2) {
                for (int i = 0; i < 20; i++) {
                    nameArray.add("name" + random.nextInt());
                }
                itemAdapter.notifyDataSetChanged();
                scrollView.stopLoadMore();  // 停止加载
            }
        }
    };
}

adapter:

public class ItemAdapter extends BaseAdapter {

    private Context context;
    private ArrayList<String> nameArray;

    public ItemAdapter(Context context, ArrayList<String> nameArray) {
        this.context = context;
        this.nameArray = nameArray;
    }

    @Override
    public int getCount() {
        if (nameArray != null && nameArray.size() > 0) {
            return nameArray.size();
        }else{
            return 0;
        }
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = LayoutInflater.from(context).inflate(R.layout.item, null, false);
            holder.leftNameView = (TextView) convertView.findViewById(R.id.name);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.leftNameView.setText(nameArray.get(position));
        return convertView;
    }

    class ViewHolder {
        TextView leftNameView;
    }
}

欢迎阅读

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值