1 效果圖
2 代碼
2.1 MainActivity
package com.example.zhq_zhao.testrefrush;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private DWRefreshLayout dwRefreshLayout ;
private ListView lv_list;
private List<Object> list=new ArrayList<>();
Handler mHandler = new Handler(Looper.getMainLooper());
private CommonAdapter commonAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list.add("asfd");
dwRefreshLayout= findViewById(R.id.dwRefreshLayout);
lv_list=findViewById(R.id.lv_list);
if(commonAdapter==null){
commonAdapter= new CommonAdapter<Object>(this, list, R.layout.text) {
@Override
public void convert(ViewHolder holder, Object o, int position) {
}
};
}
lv_list.setAdapter(commonAdapter);
dwRefreshLayout.setOnRefreshListener(new DWRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
dwRefreshLayout.setRefresh(false);
}
}, 2000);
}
@Override
public void onLoadMore() {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
dwRefreshLayout.setRefresh(false);
list.add("test");
commonAdapter.notifyDataSetChanged();
// commonAdapter.setDate(list);
}
}, 2000);
}
});
}
@Override
protected void onStart() {
super.onStart();
dwRefreshLayout.setRefresh(true);
}
}
2.2 CommonAdapter
package com.example.zhq_zhao.testrefrush;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.util.List;
/**
* Created by zhq_zhao on 2017/6/12.
*/
public abstract class CommonAdapter<T> extends BaseAdapter {
protected Context mContext;
protected LayoutInflater mInflater;
protected List<T> mDatas;
private int layoutId;
public CommonAdapter(Context context, List<T> datas, int layoutId) {
this.mContext = context;
mInflater = LayoutInflater.from(context);
this.mDatas = datas;
this.layoutId = layoutId;
}
@Override
public int getCount() {
return mDatas.size();
}
@Override
public T getItem(int position) {
return mDatas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = ViewHolder.get(mContext, convertView, parent, layoutId, position);
convert(holder, getItem(position),position);
return holder.getConvertView();
}
public void setDate(List<T> data) {
this.mDatas = data;
this.notifyDataSetChanged();
}
public abstract void convert(ViewHolder holder, T t,int position);
}
2.3 DefaultFootView
package com.example.zhq_zhao.testrefrush;
import android.content.Context;
import android.support.annotation.ColorRes;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
/**
* Created by zhq_zhao on 2019/6/28.
*/
public class DefaultFootView extends FrameLayout implements ILoadMoreFoot {
private TextView mTvStatus;
private FrameLayout.LayoutParams mLayoutParams =
new LayoutParams(LayoutParams.MATCH_PARENT, (int) DensityUtils.dipToPx(getContext(), 60));
public DefaultFootView(Context context) {
this(context, null);
}
public DefaultFootView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DefaultFootView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
View view = LayoutInflater.from(getContext()).inflate(R.layout.default_headview, null);
mTvStatus = (TextView) view.findViewById(R.id.tv_status);
this.addView(view, mLayoutParams);
}
/**
* 設置刷新頭的狀態顏色
*
* @param textColor
*/
public void setTextColor(@ColorRes int textColor) {
mTvStatus.setTextColor(getResources().getColor(textColor));
}
/**
* 設置刷新頭的狀態文字大小
*
* @param textSize
*/
public void setTextSize(int textSize) {
mTvStatus.setTextSize(textSize);
}
@Override
public void onStart() {
mTvStatus.setText("上拉");
}
@Override
public void onPullUp(int distance) {
mTvStatus.setText("上拉加載更多");
}
@Override
public void onBound() {
mTvStatus.setText("鬆開加載更多");
}
@Override
public void onFingerUp(int distance) {
mTvStatus.setText("加載更多...");
}
@Override
public void onStop() {
}
@Override
public int footViewHeight() {
return (int) DensityUtils.dipToPx(getContext(), 60);
}
}
2.4 DefaultHeadView
package com.example.zhq_zhao.testrefrush;
import android.content.Context;
import android.support.annotation.ColorRes;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
/**
* Created by zhq_zhao on 2019/6/28.
*/
public class DefaultHeadView extends FrameLayout implements IRefreshHead {
private TextView mTvStatus;
private FrameLayout.LayoutParams mLayoutParams =
new LayoutParams(LayoutParams.MATCH_PARENT, (int) DensityUtils.dipToPx(getContext(), 60));
public DefaultHeadView(Context context) {
this(context, null);
}
public DefaultHeadView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DefaultHeadView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
View view = LayoutInflater.from(getContext()).inflate(R.layout.default_headview, null);
mTvStatus = (TextView) view.findViewById(R.id.tv_status);
mTvStatus.setText("自定義view");
this.addView(view, mLayoutParams);
}
/**
* 設置刷新頭的狀態顏色
* @param textColor
*/
public void setTextColor(@ColorRes int textColor) {
mTvStatus.setTextColor(getResources().getColor(textColor));
}
/**
* 設置刷新頭的狀態文字大小
* @param textSize
*/
public void setTextSize(int textSize) {
mTvStatus.setTextSize(textSize);
}
@Override
public void onStart() {
mTvStatus.setText("開始下拉");
}
@Override
public void onPullDown(int distance) {
mTvStatus.setText("下拉刷新");
}
@Override
public void onBound() {
mTvStatus.setText("釋放刷新");
}
@Override
public void onFingerUp(int distance) {
mTvStatus.setText("刷新中...");
}
@Override
public void onStop() {
}
@Override
public int headViewHeight() {
return (int) DensityUtils.dipToPx(getContext(), 60);
}
}
2.5 DensityUtils
package com.example.zhq_zhao.testrefrush;
import android.content.Context;
import android.util.TypedValue;
/**
* Created by zhq_zhao on 2019/6/28.
*/
public class DensityUtils {
/**
* dip轉Px
*
* @param dip
* @return
*/
public static float dipToPx(Context context, int dip) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, context.getResources().getDisplayMetrics());
}
/**
* sp 轉px
*
* @param context
* @param sp
* @return
*/
public static float spToDx(Context context, int sp) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics());
}
}
2.6 DWRefreshLayout
package com.example.zhq_zhao.testrefrush;
/**
* Created by zhq_zhao on 2019/6/28.
*/
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
/**
* Created by: xudiwei
* <p>
* on: 2017/5/28.
* <p>
* 描述:版本4
*/
public class DWRefreshLayout extends FrameLayout {
private static final String TAG = "DWRefreshLayout";
private static final String HEAD_TAG = "head";
private static final String FOOT_TAG = "foot";
private View mHeadView;
private View mContentView;
private View mFootView;
private IRefreshHead mIRefreshHead;
private ILoadMoreFoot mILoadMoreFoot;
private int mHeadViewHeight;
private int mFootViewHeight;
private ValueAnimator mValueAnimator;
//view需要移動的的距離
int moveDistance = 0;
//靈敏度,moveDistance * mTact = 實際 需要移動的距離
private float mHeadViewTact = 0.6f;
private float mFootViewTact = 0.5f;
/*當前的刷新佈局狀態*/
private int mStatus = STATUS_NONE;
//狀態: 無
private static final int STATUS_NONE = 0;
//狀態:刷新
private static final int STATUS_REFRESH = 1;
//狀態:加載更多
private static final int STATUS_LOAD_MORE = 2;
//方向
private int mDirection = DIRECTION_NONE;
private static final int DIRECTION_NONE = 0;
//划動方向: 向下劃(刷新動作)
private static final int DIRECTION_UP = 1;
//划動方向:向上劃(加載更多動作)
private static final int DIRECTION_DOWN = 2;
//動畫的執行時間,默認是200ms
int mAnimatorDuration = ANIMATOR_DEFAULT_DURATION;
//動畫的默認執行時間
private static int ANIMATOR_DEFAULT_DURATION = 200;
//自動刷新的動畫默認執行時間
private static int ANIMATOR_AUTO_REFRESH_DURATION = 500;
//是否攔截事件
boolean interception;
//是否爲自動刷新
boolean isAutoRefresh = false;
//自動刷新動畫監聽器
private DWRefreshLayout.AutoRefreshAnimatorListener mAutoRefreshAnimatorListener = new DWRefreshLayout.AutoRefreshAnimatorListener();
//刷新佈局的排放方式
private int mRefreshStyle;
//刷新頭佈局在刷新內容之下
private static final int STYLE_BELOW = 1;
//刷新頭佈局與刷新內容並排
private static final int STYLE_DEFAULT = 2;
//刷新頭佈局在刷新內容之上
private static final int STYLE_MATERIAL = 3;
//是否禁止上拉加載更多默認是支持的
private boolean mDisenableLoadMore = false;
public DWRefreshLayout(Context context) {
this(context, null);
}
public DWRefreshLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DWRefreshLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttrs(attrs);
init();
}
private void initAttrs(AttributeSet attrs) {
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.DWRefreshLayout);
mRefreshStyle = ta.getInt(R.styleable.DWRefreshLayout_refresh_style, STYLE_DEFAULT);
Log.d(TAG, "RefreshStyle: " + mRefreshStyle);
ta.recycle();
}
private void init() {
mHeadView = new DefaultHeadView(getContext());
mHeadView.setTag(HEAD_TAG);
mIRefreshHead = (IRefreshHead) mHeadView;
mHeadViewHeight = mIRefreshHead.headViewHeight();
mFootView = new DefaultFootView(getContext());
mFootView.setTag(FOOT_TAG);
mILoadMoreFoot = (ILoadMoreFoot) mFootView;
mFootViewHeight = mILoadMoreFoot.footViewHeight();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if (getChildCount() > 1) {
throw new IllegalArgumentException(">>>>---- do refresh direct view count must equal 1 ----<<<<");
}
// LayoutParams headParams = new LayoutParams(LayoutParams.MATCH_PARENT, mHeadViewHeight);
// this.addView(mHeadView, 0, headParams);
mContentView = this.getChildAt(0);
addHeadView(mHeadView);
addFootView(mFootView);
// LayoutParams footParams = new LayoutParams(LayoutParams.MATCH_PARENT, mFootViewHeight);
// this.addView(mFootView, 2, footParams);
}
/**
* 添加刷新頭,添加的位置要根據{@link #mRefreshStyle}的值來添加
* 如果{@link #mRefreshStyle}的值爲{@link #STYLE_BELOW} headView
* 在當前刷新佈局的位置是0.也就是addView(headView,0);
* 如果{@link #mRefreshStyle}的值爲{@link #STYLE_DEFAULT}或是
* 爲{@link #STYLE_MATERIAL} headView在當前刷新佈局的位置是1
*
* @param headView 頭佈局
*/
private void addHeadView(View headView) {
this.removeView(findViewWithTag(HEAD_TAG));
//重新添加頭佈局
LayoutParams headParams = new LayoutParams(LayoutParams.MATCH_PARENT, mHeadViewHeight);
if (mRefreshStyle == STYLE_BELOW) {
this.addView(headView, 0, headParams);
Log.d(TAG, "add headView below");
} else {
this.addView(headView, 1, headParams);
Log.d(TAG, "add headView other > default or material");
}
headView.setTag(HEAD_TAG);
}
/**
* 添加腳佈局
*
* @param footView 腳佈局
*/
private void addFootView(View footView) {
this.removeView(findViewWithTag(FOOT_TAG));
LayoutParams footParams = new LayoutParams(LayoutParams.MATCH_PARENT, mFootViewHeight);
this.addView(footView, 2, footParams);
footView.setTag(FOOT_TAG);
}
/**
* 設置自定義的頭佈局
*
* @param headView 頭佈局
*/
public void setHeadView(View headView) {
if (!(headView instanceof IRefreshHead)) {
throw new IllegalArgumentException("頭佈局headView必須實現 IRefreshHead 接口");
}
mHeadView = headView;
mIRefreshHead = (IRefreshHead) headView;
mHeadViewHeight = mIRefreshHead.headViewHeight();
addHeadView(headView);
}
/**
* 設置自定義的腳佈局
*
* @param footView 腳佈局
*/
public void setFootView(View footView) {
if (!(footView instanceof ILoadMoreFoot)) {
throw new IllegalArgumentException("腳佈局footView必須實現 ILoadMoreFoot 接口");
}
mFootView = footView;
mILoadMoreFoot = (ILoadMoreFoot) footView;
mFootViewHeight = mILoadMoreFoot.footViewHeight();
addFootView(mFootView);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
b = getHeight();
if (mRefreshStyle == STYLE_BELOW) {
//below
mHeadView.layout(0, 0, r, mHeadViewHeight);
mContentView.layout(0, moveDistance, r, b + moveDistance);
mFootView.layout(0, b + moveDistance, r, b + mFootViewHeight + moveDistance);
} else if (mRefreshStyle == STYLE_DEFAULT) {
//default
mHeadView.layout(0, -mHeadViewHeight + moveDistance, r, moveDistance);
mContentView.layout(0, moveDistance, r, b + moveDistance);
mFootView.layout(0, b + moveDistance, r, b + mFootViewHeight + moveDistance);
} else {
//material
mHeadView.layout(0, -mHeadViewHeight + moveDistance, r, moveDistance);
if (mDirection == DIRECTION_DOWN) {
mContentView.layout(0, 0, r, b);
} else if (mDirection == DIRECTION_UP) {
mContentView.layout(0, moveDistance, r, b + moveDistance);
} else {
mContentView.layout(0, moveDistance, r, b + moveDistance);
}
mFootView.layout(0, b + moveDistance, r, b + mFootViewHeight + moveDistance);
}
}
int downY;
int downX;
int diffY;
int diffX;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
//如果此時是在刷新中或是在加載更多中就不要對事件進行自定義的攔截
if (mStatus == STATUS_REFRESH || mStatus == STATUS_LOAD_MORE) {
return super.dispatchTouchEvent(ev);
}
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downY = (int) ev.getY();
downX = (int) ev.getX();
mDirection = DIRECTION_NONE;
interception = false;
// Log.d(TAG, "dispatchTouchEvent down");
break;
case MotionEvent.ACTION_MOVE:
diffY = (int) (downY - ev.getY());
diffX = (int) (downX - ev.getX());
if(Math.abs(diffX) > Math.abs(diffY)){
return super.dispatchTouchEvent(ev);
}
if (diffY < 0) {
boolean contentViewCanScrollDown = ViewCompat.canScrollVertically(mContentView, -1);
if (!contentViewCanScrollDown) {
Log.d(TAG, "下拉 ");
mDirection = DIRECTION_DOWN;
if (!interception) {
mIRefreshHead.onStart();
}
interception = true;
}
} else if (diffY > 0) {
boolean contentViewCanScrollUp = ViewCompat.canScrollVertically(mContentView, 1);
if (!contentViewCanScrollUp) {
Log.d(TAG, "上拉 ");
mDirection = DIRECTION_UP;
if (!interception) {
mILoadMoreFoot.onStart();
}
interception = true;
}
}
break;
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//如果此時是在刷新中或是在加載更多中就不要對事件進行自定義的攔截
if (mStatus == STATUS_REFRESH || mStatus == STATUS_LOAD_MORE) {
return super.onInterceptTouchEvent(ev);
}
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(TAG, "onInterceptTouchEvent down:");
break;
case MotionEvent.ACTION_MOVE:
// if (mDirection == DIRECTION_DOWN) {
// mIRefreshHead.onStart();
// } else if (mDirection == DIRECTION_UP) {
// mILoadMoreFoot.onStart();
// }
Log.d(TAG, "onInterceptTouchEvent move:" + interception);
return interception;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//如果此時是在刷新中或是在加載更多中就不要對事件進行自定義的攔截
if (mStatus == STATUS_REFRESH || mStatus == STATUS_LOAD_MORE) {
return super.onTouchEvent(event);
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d(TAG, "onTouchEvent down:");
return true;
case MotionEvent.ACTION_MOVE:
move((int) event.getY());
Log.d(TAG, "onTouchEvent move:" + interception);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
int upY = (int) event.getY();
if (mDirection == DIRECTION_DOWN) {
mIRefreshHead.onFingerUp(moveDistance);
if (moveDistance >= mHeadViewHeight) {
//觸發刷新
reset((int) ((upY - downY) * mHeadViewTact), mHeadViewHeight);
mStatus = STATUS_REFRESH;
if (null != mOnRefreshListener) {
mOnRefreshListener.onRefresh();
}
} else {
//回彈
mStatus = STATUS_NONE;
reset((int) ((upY - downY) * mHeadViewTact), 0);
}
} else if (mDirection == DIRECTION_UP) {
if(mDisenableLoadMore){
//禁止加載更多
return super.onTouchEvent(event);
}
mILoadMoreFoot.onFingerUp(Math.abs(moveDistance));
if (Math.abs(moveDistance) >= mFootViewHeight) {
//觸發加載
reset((int) ((upY - downY) * mFootViewTact), -mFootViewHeight);
mStatus = STATUS_LOAD_MORE;
if (null != mOnRefreshListener) {
mOnRefreshListener.onLoadMore();
}
} else {
//回彈
mStatus = STATUS_NONE;
reset((int) ((upY - downY) * mFootViewTact), 0);
}
}
break;
}
return super.onTouchEvent(event);
}
/**
* 移動佈局
*
* @param moveY 手指移動的Y座標
*/
private void move(int moveY) {
if (mDirection == DIRECTION_DOWN) {
//下移
moveDistance = (int) ((moveY - downY) * mHeadViewTact);
if (moveDistance >= mHeadViewHeight) {
mIRefreshHead.onBound();
}/* else {*/
mIRefreshHead.onPullDown(moveDistance);
// }
} else {
//上移
if(mDisenableLoadMore){
//禁止加載更多
return;
}
moveDistance = (int) ((moveY - downY) * mFootViewTact);
if (moveDistance <= -mFootViewHeight) {
mILoadMoreFoot.onBound();
}/* else {*/
mILoadMoreFoot.onPullUp(Math.abs(moveDistance));
// }
}
Log.d(TAG, "moveDistance: " + moveDistance);
requestLayout();
}
/**
* 重置
*
* @param startY 起始Y
* @param endY 結束Y
*/
private void reset(int startY, int endY) {
Log.d(TAG, "startY: " + startY + " endY: " + endY);
mValueAnimator = ValueAnimator.ofInt(startY, endY);
mValueAnimator.setDuration(mAnimatorDuration);
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();
Log.d(TAG, "value: " + value);
moveDistance = value;
requestLayout();
}
});
mValueAnimator.addListener(mAutoRefreshAnimatorListener);
mValueAnimator.start();
}
private class AutoRefreshAnimatorListener implements Animator.AnimatorListener {
@Override
public void onAnimationStart(Animator animation) {
if (isAutoRefresh) {
mIRefreshHead.onStart();
}
}
@Override
public void onAnimationEnd(Animator animation) {
ValueAnimator valueAnimator = (ValueAnimator) animation;
int value = (int) valueAnimator.getAnimatedValue();
mIRefreshHead.onFingerUp(value);
if (isAutoRefresh && null != mOnRefreshListener) {
mOnRefreshListener.onRefresh();
}
isAutoRefresh = false;
mAnimatorDuration = ANIMATOR_DEFAULT_DURATION;
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
}
/**
* 設置刷新
*
* @param refresh true爲刷新,false爲關閉刷新
*/
public void setRefresh(boolean refresh) {
if (refresh) {
mDirection = DIRECTION_DOWN;
mStatus = STATUS_REFRESH;
isAutoRefresh = true;
mAnimatorDuration = ANIMATOR_AUTO_REFRESH_DURATION;
reset(0, mHeadViewHeight);
} else {
if (mStatus == STATUS_NONE) {
return;
}
if (mDirection == DIRECTION_DOWN) {
reset(mHeadViewHeight, 0);
mIRefreshHead.onStop();
} else if (mDirection == DIRECTION_UP) {
reset(-mFootViewHeight, 0);
mILoadMoreFoot.onStop();
}
mStatus = STATUS_NONE;
}
}
/**
* 當前是否在加載中或是刷新中
*
* @return
*/
public boolean isRefresh() {
return mStatus != STATUS_NONE;
}
/**
* 禁用上拉加載更多
* @param lockLoadMore
*/
public void lockLoadMore(boolean lockLoadMore){
this.mDisenableLoadMore = lockLoadMore;
}
DWRefreshLayout.OnRefreshListener mOnRefreshListener;
/**
* 設置刷新回調接口
*
* @param onRefreshListener 刷新回調接口
*/
public void setOnRefreshListener(DWRefreshLayout.OnRefreshListener onRefreshListener) {
mOnRefreshListener = onRefreshListener;
}
/**
* 刷新回調接口
*/
public interface OnRefreshListener {
/**
* 當刷新被觸發時會調用此方法
*/
void onRefresh();
/**
* 當加載更多時會調用此方法
*/
void onLoadMore();
}
}
2.7 ILoadMoreFoot
package com.example.zhq_zhao.testrefrush;
/**
* Created by zhq_zhao on 2019/6/28.
*/
public interface ILoadMoreFoot {
/**
* 開始上拉 調用一次
*/
void onStart();
/**
* 上拉中 多次被調用
*
* @param distance 腳佈局距離底部的距離
*/
void onPullUp(int distance);
/**
* 下拉到邊界 多次被調用
*/
void onBound();
/**
* 鬆手 多次被調用
*
* @param distance 腳佈局距離底部的距離
*/
void onFingerUp(int distance);
/**
* 結束
*/
void onStop();
/**
* 腳佈局的view高度
*
* @return 返回腳佈局view的高度(px)像素.
*/
int footViewHeight();
}
2.8 IRefreshHead
package com.example.zhq_zhao.testrefrush;
/**
* Created by zhq_zhao on 2019/6/28.
*/
public interface IRefreshHead {
/**
* 開始下拉,只調用一次
*/
void onStart();
/**
* 下拉中 多次被調用
*
* @param distance 頭佈局距離頂部的距離
*/
void onPullDown(int distance);
/**
* 下拉到邊界 多次被調用
*/
void onBound();
/**
* 鬆手 多次被調用
*
* @param distance 頭佈局距離頂部的距離
*/
void onFingerUp(int distance);
/**
* 結束
*/
void onStop();
/**
* 頭佈局的view高度
*
* @return 返回頭佈局view的高度(px)像素
*/
int headViewHeight();
}
2.9 ViewHolder
package com.example.zhq_zhao.testrefrush;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.util.Linkify;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.widget.Checkable;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RatingBar;
import android.widget.TextView;
/**
* Created by zhq_zhao on 2017/6/12.
*/
public class ViewHolder {
private SparseArray<View> mViews;
private int mPosition;
private View mConvertView;
private Context mContext;
private int mLayoutId;
public ViewHolder(Context context, ViewGroup parent, int layoutId,
int position) {
mContext = context;
mLayoutId = layoutId;
this.mPosition = position;
this.mViews = new SparseArray<View>();
mConvertView = LayoutInflater.from(context).inflate(layoutId, parent,
false);
mConvertView.setTag(this);
}
public static ViewHolder get(Context context, View convertView,
ViewGroup parent, int layoutId, int position) {
if (convertView == null) {
return new ViewHolder(context, parent, layoutId, position);
} else {
ViewHolder holder = (ViewHolder) convertView.getTag();
holder.mPosition = position;
return holder;
}
}
public int getPosition() {
return mPosition;
}
public int getLayoutId() {
return mLayoutId;
}
/**
* 通過viewId獲取控件
*
* @param viewId
* @return
*/
public <T extends View> T getView(int viewId) {
View view = mViews.get(viewId);
if (view == null) {
view = mConvertView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
}
public View getConvertView() {
return mConvertView;
}
/**
* 設置TextView的值
*
* @param viewId
* @param text
* @return
*/
public ViewHolder setText(int viewId, String text) {
TextView tv = getView(viewId);
tv.setText(text);
return this;
}
/**
* 設置TextView的值
*
* @param viewId
* @param text
* @return
*/
public ViewHolder setText(int viewId, CharSequence text) {
TextView tv = getView(viewId);
tv.setText(text);
return this;
}
public ViewHolder setImageResource(int viewId, int resId) {
ImageView view = getView(viewId);
view.setImageResource(resId);
return this;
}
public ViewHolder setImageBitmap(int viewId, Bitmap bitmap) {
ImageView view = getView(viewId);
view.setImageBitmap(bitmap);
return this;
}
public ViewHolder setImageDrawable(int viewId, Drawable drawable) {
ImageView view = getView(viewId);
view.setImageDrawable(drawable);
return this;
}
public ViewHolder setBackgroundColor(int viewId, int color) {
View view = getView(viewId);
view.setBackgroundColor(color);
return this;
}
public ViewHolder setBackgroundRes(int viewId, int backgroundRes) {
View view = getView(viewId);
view.setBackgroundResource(backgroundRes);
return this;
}
public ViewHolder setBackground(int viewId, int backgroundRes) {
View view = getView(viewId);
view.setBackgroundResource(backgroundRes);
return this;
}
public ViewHolder setTextColor(int viewId, int textColor) {
TextView view = getView(viewId);
view.setTextColor(textColor);
return this;
}
public ViewHolder setTextColorRes(int viewId, int textColorRes) {
TextView view = getView(viewId);
view.setTextColor(mContext.getResources().getColor(textColorRes));
return this;
}
@SuppressLint("NewApi")
public ViewHolder setAlpha(int viewId, float value) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getView(viewId).setAlpha(value);
} else {
// Pre-honeycomb hack to set Alpha value
AlphaAnimation alpha = new AlphaAnimation(value, value);
alpha.setDuration(0);
alpha.setFillAfter(true);
getView(viewId).startAnimation(alpha);
}
return this;
}
public ViewHolder setVisible(int viewId, boolean visible) {
View view = getView(viewId);
view.setVisibility(visible ? View.VISIBLE : View.GONE);
return this;
}
public ViewHolder linkify(int viewId) {
TextView view = getView(viewId);
Linkify.addLinks(view, Linkify.ALL);
return this;
}
public ViewHolder setTypeface(Typeface typeface, int... viewIds) {
for (int viewId : viewIds) {
TextView view = getView(viewId);
view.setTypeface(typeface);
view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
}
return this;
}
public ViewHolder setProgress(int viewId, int progress) {
ProgressBar view = getView(viewId);
view.setProgress(progress);
return this;
}
public ViewHolder setProgress(int viewId, int progress, int max) {
ProgressBar view = getView(viewId);
view.setMax(max);
view.setProgress(progress);
return this;
}
public ViewHolder setMax(int viewId, int max) {
ProgressBar view = getView(viewId);
view.setMax(max);
return this;
}
public ViewHolder setRating(int viewId, float rating) {
RatingBar view = getView(viewId);
view.setRating(rating);
return this;
}
public ViewHolder setRating(int viewId, float rating, int max) {
RatingBar view = getView(viewId);
view.setMax(max);
view.setRating(rating);
return this;
}
public ViewHolder setTag(int viewId, Object tag) {
View view = getView(viewId);
view.setTag(tag);
return this;
}
public ViewHolder setTag(int viewId, int key, Object tag) {
View view = getView(viewId);
view.setTag(key, tag);
return this;
}
public ViewHolder setChecked(int viewId, boolean checked) {
Checkable view = (Checkable) getView(viewId);
view.setChecked(checked);
return this;
}
/**
* 關於事件的
*/
public ViewHolder setOnClickListener(int viewId,
View.OnClickListener listener) {
View view = getView(viewId);
view.setOnClickListener(listener);
return this;
}
public ViewHolder setOnTouchListener(int viewId,
View.OnTouchListener listener) {
View view = getView(viewId);
view.setOnTouchListener(listener);
return this;
}
public ViewHolder setOnLongClickListener(int viewId,
View.OnLongClickListener listener) {
View view = getView(viewId);
view.setOnLongClickListener(listener);
return this;
}
}
2.10 avtivity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.zhq_zhao.testrefrush.MainActivity">
<com.example.zhq_zhao.testrefrush.DWRefreshLayout
android:id="@+id/dwRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/lv_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ListView>
</com.example.zhq_zhao.testrefrush.DWRefreshLayout>
</RelativeLayout>
2.11 default_headview.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#00ffffff">
<ProgressBar
style="?android:progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="50dp"/>
<TextView
android:id="@+id/tv_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="默認"
android:textColor="#000"
android:textSize="16sp"/>
</RelativeLayout>
2.12 text.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_gravity="top"
android:gravity="center|left"
android:layout_height="match_parent">
<TextView
android:text="test"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>