android上拉刷新的方案,Android RefreshListView上拉刷新下拉加载

RefreshListView上拉刷新下拉加载

/**

* Created by mark-lee on 2018/11/12.

*/

public class RefreshListView extends ListView implements AbsListView.OnScrollListener {

private final String TAG ="RefreshListView";

private View mRefreshHeaderView;

private int MAX_HEIGHT = 0;

private int mPaddingTop;

private AbsListView.OnScrollListener mOnScrollListener;

private float mLastTouchY;

private boolean isScrollAtTop;

private volatile boolean isRefreshing;

private View mRefreshFooterView;

private int mPaddingBottom;

private boolean isScrollAtBottom;

public RefreshListView(Context context) {

this(context,null);

}

public RefreshListView(Context context, AttributeSet attrs) {

this(context, attrs,0);

}

public RefreshListView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

initHeaderView();

setOnScrollListener(this);

}

private void initHeaderView() {

mRefreshHeaderView = createFooterOrHeaderView("下拉刷新");

mRefreshFooterView = createFooterOrHeaderView("加载更多");

addHeaderView(mRefreshHeaderView);

addFooterView(mRefreshFooterView);

MAX_HEIGHT = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,150,getContext().getResources().getDisplayMetrics());

final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); //宽度未指定,当然也可以设置为E(-1,EXACTLY)

final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(MAX_HEIGHT, MeasureSpec.AT_MOST); //高度最大值限制为150dip

mRefreshHeaderView.measure(widthMeasureSpec,heightMeasureSpec);

mRefreshFooterView.measure(widthMeasureSpec,heightMeasureSpec);

final int headerHeight = mRefreshHeaderView.getMeasuredHeight();

mPaddingTop = - headerHeight;

mRefreshHeaderView.setPadding(0,mPaddingTop,0,0);

final int footerHeight = mRefreshHeaderView.getMeasuredHeight();

mPaddingBottom = - footerHeight;

mRefreshFooterView.setPadding(0,0,0,mPaddingBottom);

}

private LinearLayout createFooterOrHeaderView(String msg){

final Context context = getContext();

final DisplayMetrics metrics = context.getResources().getDisplayMetrics();

final int padding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP ,10,metrics );

final int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP ,40, metrics);

LinearLayout headerPanel = new LinearLayout(context);

headerPanel.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));

headerPanel.setOrientation(LinearLayout.HORIZONTAL);

headerPanel.setBackgroundColor(0x33ff0000);

headerPanel.setGravity(Gravity.CENTER);

ProgressBar progressBar = new ProgressBar(context);

final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(size, size);

params.topMargin = padding;

params.bottomMargin = padding;

progressBar.setLayoutParams(params);

progressBar.setIndeterminate(true);

progressBar.setFocusable(true);

TextView tv = new TextView(context);

tv.setTextSize(12);

tv.setText(msg);

tv.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));

tv.setId(android.R.id.text1);

headerPanel.addView(progressBar);

headerPanel.addView(tv);

return headerPanel;

}

@Override

public boolean onTouchEvent(MotionEvent ev) {

if( !isScrollAtTop &&!isScrollAtBottom || isRefreshing ) {

mLastTouchY = ev.getY();

return super.onTouchEvent(ev);

}

switch (ev.getAction()){

case MotionEvent.ACTION_DOWN:

mLastTouchY = ev.getY();

break;

case MotionEvent.ACTION_MOVE:

startHandlePadding(ev);

break;

case MotionEvent.ACTION_UP:

case MotionEvent.ACTION_CANCEL:

endHandlePadding(ev);

break;

}

return super.onTouchEvent(ev);

}

private boolean endHandlePadding(MotionEvent ev) {

if(isScrollAtTop) {

float deltaY = (ev.getY() - mLastTouchY)/2;

if (deltaY < 0) return false;

if (deltaY < (MAX_HEIGHT *3) / 5) {

mRefreshHeaderView.setPadding(0, mPaddingTop, 0, 0);

} else {

isRefreshing = true;

mRefreshHeaderView.setPadding(0, mPaddingTop + MAX_HEIGHT, 0, 0);

mRefreshHeaderView.postDelayed(finishTask, 1500);

}

}else if(isScrollAtBottom){

float deltaY = (-ev.getY() + mLastTouchY)/2;

if (deltaY < 0) return false;

if (deltaY < (MAX_HEIGHT*3) / 5) {

mRefreshFooterView.setPadding(0, 0, 0, mPaddingBottom);

} else {

isRefreshing = true;

mRefreshFooterView.setPadding(0, 0, 0, MAX_HEIGHT + mPaddingBottom);

mRefreshFooterView.postDelayed(finishTask, 1500);

}

}

return true;

}

private boolean startHandlePadding(MotionEvent ev) {

if(isScrollAtTop) {

float deltaY = (ev.getY() - mLastTouchY)/2;// 这里 乘以 0.5作为弹性系数

if (deltaY < 0) return false;

deltaY = Math.min(deltaY, MAX_HEIGHT);

Log.d(TAG, " deltaY=" + deltaY);

mRefreshHeaderView.setPadding(0, (int) deltaY + mPaddingTop, 0, 0);

return true;

}else if(isScrollAtBottom){

float deltaY = (-ev.getY() + mLastTouchY)/2 ; // 这里 乘以 0.5作为弹性系数

if (deltaY < 0) return false;

deltaY = Math.min(deltaY, MAX_HEIGHT);

Log.d(TAG, " deltaY=" + deltaY);

mRefreshFooterView.setPadding(0, 0, 0, (int) deltaY + mPaddingBottom);

return true;

}

return false;

}

@Override

public void onScrollStateChanged(AbsListView view, int scrollState) {

if(mOnScrollListener!=null){

mOnScrollListener.onScrollStateChanged(view,scrollState);

}

}

@Override

public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

if(mOnScrollListener!=null){

mOnScrollListener.onScroll(view,firstVisibleItem,visibleItemCount,totalItemCount);

}

isScrollAtTop = (firstVisibleItem==0);

isScrollAtBottom = (totalItemCount==(firstVisibleItem+visibleItemCount));

}

private final Runnable finishTask = new Runnable() {

@Override

public void run() {

isRefreshing = false;

mRefreshHeaderView.setPadding(0, mPaddingTop, 0, 0);

mRefreshFooterView.setPadding(0, 0, 0, mPaddingBottom);

}

};

@Override

public void setAdapter(ListAdapter adapter) {

super.setAdapter(adapter);

}

@Override

protected void onScrollChanged(int l, int t, int oldl, int oldt) {

super.onScrollChanged(l, t, oldl, oldt);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值