Android學(xué)習(xí)教程之下拉刷新實(shí)現(xiàn)代碼(11)
本文實(shí)例為大家分享了Android下拉刷新的具體代碼,供大家參考,具體內(nèi)容如下
MainActivity.java代碼:
package siso.refreshablev;
import android.app.Activity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import refreshableview.RefreshableView;
import refreshableview.refreshablehelper.RefreshableHelper;
public class MainActivity extends Activity implements View.OnClickListener {
private static final String TAG = MainActivity.class.getSimpleName();
private RefreshableView refreshableView;
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.main_tv).setOnClickListener(this);
refreshableView = (RefreshableView) findViewById(R.id.main_refresh_view);
refreshableView.setRefreshableHelper(new RefreshableHelper() {
@Override
public View onInitRefreshHeaderView() {
return LayoutInflater.from(MainActivity.this).inflate(R.layout.refresh_head, null);
}
@Override
public boolean onInitRefreshHeight(int originRefreshHeight) {
refreshableView.setRefreshNormalHeight(refreshableView.getOriginRefreshHeight() / 3);
refreshableView.setRefreshingHeight(refreshableView.getOriginRefreshHeight());
refreshableView.setRefreshArrivedStateHeight(refreshableView.getOriginRefreshHeight());
return false;
}
@Override
public void onRefreshStateChanged(View refreshView, int refreshState) {
TextView tv = (TextView) refreshView.findViewById(R.id.refresh_head_tv);
switch (refreshState) {
case RefreshableView.STATE_REFRESH_NORMAL:
tv.setText("正常狀態(tài)");
break;
case RefreshableView.STATE_REFRESH_NOT_ARRIVED:
tv.setText("往下拉可以刷新");
break;
case RefreshableView.STATE_REFRESH_ARRIVED:
tv.setText("放手可以刷新");
break;
case RefreshableView.STATE_REFRESHING:
tv.setText("正在刷新");
new Thread(
new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000l);
runOnUiThread(new Runnable() {
@Override
public void run() {
refreshableView.onCompleteRefresh();
}
});
} catch (InterruptedException e) {
Log.e(TAG, "_", e);
}
}
}
).start();
break;
}
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.main_tv:
Log.d(TAG, "content clicked");
startActivity(new Intent(this, RefreshableListActivity.class));
break;
}
}
}
RefreshableListActivity.java代碼:
package siso.refreshablev;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import refreshableview.RefreshableListView;
import refreshableview.RefreshableView;
import refreshableview.refreshablehelper.RefreshableHelper;
public class RefreshableListActivity extends Activity {
private static final String TAG = RefreshableListActivity.class.getSimpleName();
RefreshableListView lv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.refreshable_list);
lv = (RefreshableListView) findViewById(R.id.refreshable_lv);
lv.setRefreshableHelper(new RefreshableHelper() {
@Override
public View onInitRefreshHeaderView() {
return LayoutInflater.from(RefreshableListActivity.this).inflate(R.layout.refresh_head, null);
}
@Override
public boolean onInitRefreshHeight(int originRefreshHeight) {
lv.setRefreshNormalHeight(lv.getOriginRefreshHeight() / 3);
lv.setRefreshingHeight(lv.getOriginRefreshHeight());
lv.setRefreshArrivedStateHeight(lv.getOriginRefreshHeight());
return false;
}
@Override
public void onRefreshStateChanged(View refreshView, int refreshState) {
TextView tv = (TextView) refreshView.findViewById(R.id.refresh_head_tv);
switch (refreshState) {
case RefreshableView.STATE_REFRESH_NORMAL:
tv.setText("正常狀態(tài)");
break;
case RefreshableView.STATE_REFRESH_NOT_ARRIVED:
tv.setText("往下拉可以刷新");
break;
case RefreshableView.STATE_REFRESH_ARRIVED:
tv.setText("放手可以刷新");
break;
case RefreshableView.STATE_REFRESHING:
tv.setText("正在刷新");
new Thread(
new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000l);
runOnUiThread(new Runnable() {
@Override
public void run() {
lv.onCompleteRefresh();
}
});
} catch (InterruptedException e) {
Log.e(TAG, "_", e);
}
}
}
).start();
break;
}
}
});
List<String> data = new ArrayList<String>();
for (int i = 0; i < 30; i++) {
data.add("item_" + i);
}
ArrayAdapter adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data);
lv.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
NestScrollView.java代碼:
package refreshableview;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewParent;
import android.widget.ScrollView;
public class NestScrollView extends ScrollView {
private static final String TAG = NestScrollView.class.getSimpleName();
public NestScrollView(Context context) {
super(context);
}
public NestScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NestScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.d(TAG, "___[dispatchTouchEvent]ev action: " + ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
super.onInterceptTouchEvent(ev);
Log.d(TAG, "___[onInterceptTouchEvent]ev action: " + ev.getAction());
if (MotionEvent.ACTION_MOVE == ev.getAction()) {
return true;
}
return false;
}
float lastDownY;
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastDownY = event.getY();
parentRequestDisallowInterceptTouchEvent(true); // 保證事件可往下傳遞
Log.d(TAG, "___Down");
return true;
// break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG, "___move, this.getScrollY(): " + this.getScrollY());
boolean isTop = event.getY() - lastDownY > 0 && this.getScrollY() == 0;
if (isTop) { // 允許父控件攔截,即不允許父控件攔截設(shè)為false
parentRequestDisallowInterceptTouchEvent(false);
return false;
} else { // 不允許父控件攔截,即不允許父控件攔截設(shè)為true
parentRequestDisallowInterceptTouchEvent(true);
return true;
}
// break;
case MotionEvent.ACTION_UP:
Log.d(TAG, "___up, this.getScrollY(): " + this.getScrollY());
parentRequestDisallowInterceptTouchEvent(true); // 保證事件可往下傳遞
break;
case MotionEvent.ACTION_CANCEL:
Log.d(TAG, "___cancel");
break;
}
return false;
}
/**
* 是否允許父控件攔截事件
* @param disallowIntercept
*/
private void parentRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
ViewParent vp = getParent();
if (null == vp) {
return;
}
vp.requestDisallowInterceptTouchEvent(disallowIntercept);
}
}
RefreshableListView.java代碼:
package refreshableview;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.ListAdapter;
import android.widget.ListView;
import refreshableview.refreshablehelper.RefreshableHelper;
public class RefreshableListView extends ListView {
private static final String TAG = RefreshableListView.class.getSimpleName();
public RefreshableListView(Context context) {
super(context);
init(context);
}
public RefreshableListView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public RefreshableListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
/**
* 刷新?tīng)顟B(tài)
*/
public static final int STATE_REFRESH_NORMAL = 0x21;
public static final int STATE_REFRESH_NOT_ARRIVED = 0x22;
public static final int STATE_REFRESH_ARRIVED = 0x23;
public static final int STATE_REFRESHING = 0x24;
private int refreshState;
// 刷新?tīng)顟B(tài)監(jiān)聽(tīng)
private RefreshableHelper refreshableHelper;
/**
* 刷新的view
*/
private View refreshHeaderView;
/**
* 刷新的view的真實(shí)高度
*/
private int originRefreshHeight;
/**
* 有效下拉刷新需要達(dá)到的高度
*/
private int refreshArrivedStateHeight;
/**
* 刷新時(shí)顯示的高度
*/
private int refreshingHeight;
/**
* 正常未刷新高度
*/
private int refreshNormalHeight;
public void setRefreshableHelper(RefreshableHelper refreshableHelper) {
this.refreshableHelper = refreshableHelper;
}
private Context context;
private void init(Context context) {
this.context = context;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Log.d(TAG, "[onSizeChanged]w: " + w + ", h: " + h);
Log.d(TAG, "[onSizeChanged]oldw: " + oldw + ", oldh: " + oldh);
Log.d(TAG, "[onSizeChanged]child counts: " + this.getChildCount());
}
@Override
public void setAdapter(ListAdapter adapter) {
if (null == refreshHeaderView) {
addHeaderView();
}
super.setAdapter(adapter);
}
private void addHeaderView() {
if (null != refreshableHelper) {
refreshHeaderView = refreshableHelper.onInitRefreshHeaderView();
}
if (null == refreshHeaderView) {
Log.e(TAG, "refreshHeaderView is null!");
return;
}
this.addHeaderView(refreshHeaderView);
// 計(jì)算refreshHeadView尺寸
int width = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
refreshHeaderView.measure(width, expandSpec);
originRefreshHeight = refreshHeaderView.getMeasuredHeight();
boolean isUseDefault = true;
if (null != refreshableHelper) {
isUseDefault = refreshableHelper.onInitRefreshHeight(originRefreshHeight);
}
// 初始化各個(gè)高度
if (isUseDefault) {
refreshArrivedStateHeight = originRefreshHeight;
refreshingHeight = originRefreshHeight;
refreshNormalHeight = 0;
}
Log.d(TAG, "[onSizeChanged]refreshHeaderView origin height: " + originRefreshHeight);
changeViewHeight(refreshHeaderView, refreshNormalHeight);
// 初始化為正常狀態(tài)
setRefreshState(STATE_REFRESH_NORMAL);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
super.dispatchTouchEvent(ev);
// if(MotionEvent.ACTION_MOVE == ev.getAction()){
// return true;
// }
// return false;
return true;
}
private float lastDownY = Float.MAX_VALUE;
@Override
public boolean onTouchEvent(MotionEvent ev) {
// super.onTouchEvent(ev);
Log.d(TAG, "[onTouchEvent]ev action: " + ev.getAction());
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
super.onTouchEvent(ev);
lastDownY = ev.getY();
Log.d(TAG, "Down --> lastDownY: " + lastDownY);
break;
case MotionEvent.ACTION_MOVE:
float curY = ev.getY();
float deltaY = curY - lastDownY;
Log.d(TAG, "Move --> deltaY(curY - downY): " + deltaY);
int curHeight = refreshHeaderView.getMeasuredHeight();
int exceptHeight = curHeight + (int) (deltaY / 2);
// boolean isTop = this.getScrollY() == 0;
boolean isTop = 0 == this.getChildAt(0).getTop();
boolean isDropDown = curY - lastDownY > 0;
Log.d(TAG, "isTop: " + isTop + ", getTop(): " + this.getChildAt(0).getTop());
if (isTop) {
if (refreshState == STATE_REFRESH_NORMAL && !isDropDown) { // 正常狀態(tài),手指往上(列表往下滾動(dòng))
super.onTouchEvent(ev);
} else {
// 如果當(dāng)前沒(méi)有處在正在刷新?tīng)顟B(tài),則更新刷新?tīng)顟B(tài)
if (STATE_REFRESHING != refreshState) {
if (curHeight >= refreshArrivedStateHeight) { // 達(dá)到可刷新?tīng)顟B(tài)
setRefreshState(STATE_REFRESH_ARRIVED);
} else if (curHeight == refreshNormalHeight) { // 正常狀態(tài)
setRefreshState(STATE_REFRESH_NORMAL);
} else { // 未達(dá)到可刷新?tīng)顟B(tài)
setRefreshState(STATE_REFRESH_NOT_ARRIVED);
}
changeViewHeight(refreshHeaderView, Math.max(refreshNormalHeight, exceptHeight));
} else {
super.onTouchEvent(ev);
}
}
} else {
super.onTouchEvent(ev);
}
lastDownY = curY;
break;
case MotionEvent.ACTION_UP:
super.onTouchEvent(ev);
lastDownY = Float.MAX_VALUE;
Log.d(TAG, "Up --> lastDownY: " + lastDownY);
// 如果是達(dá)到刷新?tīng)顟B(tài),則設(shè)置正在刷新?tīng)顟B(tài)的高度
if (STATE_REFRESH_ARRIVED == refreshState) { // 達(dá)到了刷新的狀態(tài)
startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshingHeight);
setRefreshState(STATE_REFRESHING);
} else if (STATE_REFRESHING == refreshState) { // 正在刷新的狀態(tài)
startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshingHeight);
} else {
// 執(zhí)行動(dòng)畫(huà)后回歸正常狀態(tài)
startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshNormalHeight, normalAnimatorListener);
}
break;
}
return true;
}
/**
* 刷新完畢后調(diào)用此方法
*/
public void onCompleteRefresh() {
if (STATE_REFRESHING == refreshState) {
setRefreshState(STATE_REFRESH_NORMAL);
startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshNormalHeight);
}
}
/**
* 修改當(dāng)前的刷新?tīng)顟B(tài)
*
* @param expectRefreshState
*/
private void setRefreshState(int expectRefreshState) {
if (expectRefreshState != refreshState) {
refreshState = expectRefreshState;
if (null != refreshableHelper) {
refreshableHelper.onRefreshStateChanged(refreshHeaderView, refreshState);
}
}
}
/**
* 改變某控件的高度
*
* @param view
* @param height
*/
private void changeViewHeight(View view, int height) {
Log.d(TAG, "[changeViewHeight]change Height: " + height);
ViewGroup.LayoutParams lp = view.getLayoutParams();
if (null == lp) {
lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
}
lp.height = height;
view.setLayoutParams(lp);
}
/**
* 改變某控件的高度動(dòng)畫(huà)
*
* @param view
* @param fromHeight
* @param toHeight
*/
private void startHeightAnimation(final View view, int fromHeight, int toHeight) {
startHeightAnimation(view, fromHeight, toHeight, null);
}
private void startHeightAnimation(final View view, int fromHeight, int toHeight, Animator.AnimatorListener animatorListener) {
if (toHeight == view.getMeasuredHeight()) {
return;
}
ValueAnimator heightAnimator = ValueAnimator.ofInt(fromHeight, toHeight);
heightAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
Integer value = (Integer) valueAnimator.getAnimatedValue();
if (null == value) return;
changeViewHeight(view, value);
}
});
if (null != animatorListener) {
heightAnimator.addListener(animatorListener);
}
heightAnimator.setInterpolator(new LinearInterpolator());
heightAnimator.setDuration(300/*ms*/);
heightAnimator.start();
}
AnimatorListenerAdapter normalAnimatorListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
setRefreshState(STATE_REFRESH_NORMAL); // 回歸正常狀態(tài)
}
};
public void setRefreshArrivedStateHeight(int refreshArrivedStateHeight) {
this.refreshArrivedStateHeight = refreshArrivedStateHeight;
}
public void setRefreshingHeight(int refreshingHeight) {
this.refreshingHeight = refreshingHeight;
}
public void setRefreshNormalHeight(int refreshNormalHeight) {
this.refreshNormalHeight = refreshNormalHeight;
}
public int getOriginRefreshHeight() {
return originRefreshHeight;
}
}
RefreshableView.java代碼:
package refreshableview;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.LinearLayout;
import refreshableview.refreshablehelper.RefreshableHelper;
import siso.refreshablev.R;
public class RefreshableView extends LinearLayout {
private static final String TAG = RefreshableView.class.getSimpleName();
public RefreshableView(Context context) {
super(context);
init(context);
}
public RefreshableView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.refreshableView);
for (int i = 0, len = a.length(); i < len; i++) {
int attrIndex = a.getIndex(i);
switch (attrIndex) {
case R.styleable.refreshableView_interceptAllMoveEvents:
interceptAllMoveEvents = a.getBoolean(i, false);
break;
}
}
a.recycle();
init(context);
}
public RefreshableView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
/**
* 刷新?tīng)顟B(tài)
*/
public static final int STATE_REFRESH_NORMAL = 0x21;
public static final int STATE_REFRESH_NOT_ARRIVED = 0x22;
public static final int STATE_REFRESH_ARRIVED = 0x23;
public static final int STATE_REFRESHING = 0x24;
private int refreshState;
// 刷新?tīng)顟B(tài)監(jiān)聽(tīng)
private RefreshableHelper refreshableHelper;
public void setRefreshableHelper(RefreshableHelper refreshableHelper) {
this.refreshableHelper = refreshableHelper;
}
private Context context;
/**
* 刷新的view
*/
private View refreshHeaderView;
/**
* 刷新的view的真實(shí)高度
*/
private int originRefreshHeight;
/**
* 有效下拉刷新需要達(dá)到的高度
*/
private int refreshArrivedStateHeight;
/**
* 刷新時(shí)顯示的高度
*/
private int refreshingHeight;
/**
* 正常未刷新高度
*/
private int refreshNormalHeight;
/**
* 默認(rèn)不允許攔截(即,往子view傳遞事件),該屬性只有在interceptAllMoveEvents為false的時(shí)候才有效
*/
private boolean disallowIntercept = true;
/**
* xml中可設(shè)置它的值為false,表示不把移動(dòng)的事件傳遞給子控件
*/
private boolean interceptAllMoveEvents;
private void init(Context context) {
this.context = context;
this.setOrientation(VERTICAL);
// Log.d(TAG, "[init]originRefreshHeight: " + refreshHeaderView.getMeasuredHeight());
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (null != refreshableHelper) {
refreshHeaderView = refreshableHelper.onInitRefreshHeaderView();
}
// refreshHeaderView = LayoutInflater.from(context).inflate(R.layout.refresh_head, null);
if (null == refreshHeaderView) {
Log.e(TAG, "refreshHeaderView is null!");
return;
}
this.removeView(refreshHeaderView);
this.addView(refreshHeaderView, 0);
// 計(jì)算refreshHeadView尺寸
int width = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
refreshHeaderView.measure(width, expandSpec);
Log.d(TAG, "[onSizeChanged]w: " + w + ", h: " + h);
Log.d(TAG, "[onSizeChanged]oldw: " + oldw + ", oldh: " + oldh);
Log.d(TAG, "[onSizeChanged]child counts: " + this.getChildCount());
originRefreshHeight = refreshHeaderView.getMeasuredHeight();
boolean isUseDefault = true;
if (null != refreshableHelper) {
isUseDefault = refreshableHelper.onInitRefreshHeight(originRefreshHeight);
}
// 初始化各個(gè)高度
if (isUseDefault) {
refreshArrivedStateHeight = originRefreshHeight;
refreshingHeight = originRefreshHeight;
refreshNormalHeight = 0;
}
Log.d(TAG, "[onSizeChanged]refreshHeaderView origin height: " + originRefreshHeight);
changeViewHeight(refreshHeaderView, refreshNormalHeight);
// 初始化為正常狀態(tài)
setRefreshState(STATE_REFRESH_NORMAL);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.d(TAG, "[dispatchTouchEvent]ev action: " + ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d(TAG, "[onInterceptTouchEvent]ev action: " + ev.getAction());
if (!interceptAllMoveEvents) {
return !disallowIntercept;
}
// 如果設(shè)置了攔截所有move事件,即interceptAllMoveEvents為true
if (MotionEvent.ACTION_MOVE == ev.getAction()) {
return true;
}
return false;
}
@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
if (this.disallowIntercept == disallowIntercept) {
return;
}
this.disallowIntercept = disallowIntercept;
super.requestDisallowInterceptTouchEvent(disallowIntercept);
}
private float downY = Float.MAX_VALUE;
@Override
public boolean onTouchEvent(MotionEvent event) {
// super.onTouchEvent(event);
Log.d(TAG, "[onTouchEvent]ev action: " + event.getAction());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downY = event.getY();
Log.d(TAG, "Down --> downY: " + downY);
requestDisallowInterceptTouchEvent(true); // 保證事件可往下傳遞
break;
case MotionEvent.ACTION_MOVE:
float curY = event.getY();
float deltaY = curY - downY;
// 是否是有效的往下拖動(dòng)事件(則需要顯示加載header)
boolean isDropDownValidate = Float.MAX_VALUE != downY;
/**
* 修改攔截設(shè)置
* 如果是有效往下拖動(dòng)事件,則事件需要在本ViewGroup中處理,所以需要攔截不往子控件傳遞,即不允許攔截設(shè)為false
* 如果不是有效往下拖動(dòng)事件,則事件傳遞給子控件處理,所以不需要攔截,并往子控件傳遞,即不允許攔截設(shè)為true
*/
requestDisallowInterceptTouchEvent(!isDropDownValidate);
downY = curY;
Log.d(TAG, "Move --> deltaY(curY - downY): " + deltaY);
int curHeight = refreshHeaderView.getMeasuredHeight();
int exceptHeight = curHeight + (int) (deltaY / 2);
// 如果當(dāng)前沒(méi)有處在正在刷新?tīng)顟B(tài),則更新刷新?tīng)顟B(tài)
if (STATE_REFRESHING != refreshState) {
if (curHeight >= refreshArrivedStateHeight) { // 達(dá)到可刷新?tīng)顟B(tài)
setRefreshState(STATE_REFRESH_ARRIVED);
} else { // 未達(dá)到可刷新?tīng)顟B(tài)
setRefreshState(STATE_REFRESH_NOT_ARRIVED);
}
}
if (isDropDownValidate) {
changeViewHeight(refreshHeaderView, Math.max(refreshNormalHeight, exceptHeight));
} else { // 防止從子控件修改攔截后引發(fā)的downY為Float.MAX_VALUE的問(wèn)題
changeViewHeight(refreshHeaderView, Math.max(curHeight, exceptHeight));
}
break;
case MotionEvent.ACTION_UP:
downY = Float.MAX_VALUE;
Log.d(TAG, "Up --> downY: " + downY);
requestDisallowInterceptTouchEvent(true); // 保證事件可往下傳遞
// 如果是達(dá)到刷新?tīng)顟B(tài),則設(shè)置正在刷新?tīng)顟B(tài)的高度
if (STATE_REFRESH_ARRIVED == refreshState) { // 達(dá)到了刷新的狀態(tài)
startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshingHeight);
setRefreshState(STATE_REFRESHING);
} else if (STATE_REFRESHING == refreshState) { // 正在刷新的狀態(tài)
startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshingHeight);
} else {
// 執(zhí)行動(dòng)畫(huà)后回歸正常狀態(tài)
startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshNormalHeight, normalAnimatorListener);
}
break;
case MotionEvent.ACTION_CANCEL:
Log.d(TAG, "cancel");
break;
}
return true;
}
/**
* 刷新完畢后調(diào)用此方法
*/
public void onCompleteRefresh() {
if (STATE_REFRESHING == refreshState) {
setRefreshState(STATE_REFRESH_NORMAL);
startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshNormalHeight);
}
}
/**
* 修改當(dāng)前的刷新?tīng)顟B(tài)
*
* @param expectRefreshState
*/
private void setRefreshState(int expectRefreshState) {
if (expectRefreshState != refreshState) {
refreshState = expectRefreshState;
if (null != refreshableHelper) {
refreshableHelper.onRefreshStateChanged(refreshHeaderView, refreshState);
}
}
}
/**
* 改變某控件的高度
*
* @param view
* @param height
*/
private void changeViewHeight(View view, int height) {
Log.d(TAG, "[changeViewHeight]change Height: " + height);
ViewGroup.LayoutParams lp = view.getLayoutParams();
lp.height = height;
view.setLayoutParams(lp);
}
/**
* 改變某控件的高度動(dòng)畫(huà)
*
* @param view
* @param fromHeight
* @param toHeight
*/
private void startHeightAnimation(final View view, int fromHeight, int toHeight) {
startHeightAnimation(view, fromHeight, toHeight, null);
}
private void startHeightAnimation(final View view, int fromHeight, int toHeight, Animator.AnimatorListener animatorListener) {
if (toHeight == view.getMeasuredHeight()) {
return;
}
ValueAnimator heightAnimator = ValueAnimator.ofInt(fromHeight, toHeight);
heightAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
Integer value = (Integer) valueAnimator.getAnimatedValue();
if (null == value) return;
changeViewHeight(view, value);
}
});
if (null != animatorListener) {
heightAnimator.addListener(animatorListener);
}
heightAnimator.setInterpolator(new LinearInterpolator());
heightAnimator.setDuration(300/*ms*/);
heightAnimator.start();
}
AnimatorListenerAdapter normalAnimatorListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
setRefreshState(STATE_REFRESH_NORMAL); // 回歸正常狀態(tài)
}
};
public void setRefreshArrivedStateHeight(int refreshArrivedStateHeight) {
this.refreshArrivedStateHeight = refreshArrivedStateHeight;
}
public void setRefreshingHeight(int refreshingHeight) {
this.refreshingHeight = refreshingHeight;
}
public void setRefreshNormalHeight(int refreshNormalHeight) {
this.refreshNormalHeight = refreshNormalHeight;
}
public int getOriginRefreshHeight() {
return originRefreshHeight;
}
}
RefreshableHelper.java代碼:
package refreshableview.refreshablehelper;
import android.view.View;
public interface RefreshableHelper {
/**
* 初始化刷新View
*
* @return
*/
View onInitRefreshHeaderView();
/**
* 初始化各個(gè)尺寸高度
*
* @param originRefreshHeight
* @return
*/
boolean onInitRefreshHeight(int originRefreshHeight);
/**
* 刷新?tīng)顟B(tài)改變
*
* @param refreshView
* @param refreshState
*/
void onRefreshStateChanged(View refreshView, int refreshState);
}
main.xml內(nèi)容:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:rv="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <refreshableview.RefreshableView android:id="@+id/main_refresh_view" android:layout_width="match_parent" android:layout_height="match_parent" rv:interceptAllMoveEvents="false" > <refreshableview.NestScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:fillViewport="true" > <TextView android:id="@+id/main_tv" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:padding="20dp" android:textSize="18sp" android:text="下拉刷新\n\n\n\n\n\n\n\n\n\n\n下拉刷新\n下拉刷新\n\n\n\n\n\n\n\n\n\n\n下拉刷新\n下拉刷新\n\n\n\n\n\n\n\n\n\n\n下拉刷新\n下拉刷新\n\n\n\n\n\n\n\n\n\n\n下拉刷新---下拉刷新\n\n\n\n\n\n\n\n\n\n\n" /> </refreshableview.NestScrollView> </refreshableview.RefreshableView> </LinearLayout>
activity_refreshable_list.xml內(nèi)容:
<?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" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="siso.refreshablev.RefreshableListActivity"> </RelativeLayout>
refresh_head.xml內(nèi)容:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="70dp" android:gravity="center" android:background="#aa000000" > <TextView android:id="@+id/refresh_head_tv" android:layout_width="fill_parent" android:layout_height="70dp" android:gravity="center" android:background="#aabbcc" android:textSize="18sp" android:text="refreshing" /> </LinearLayout>
refreshable_list.xml內(nèi)容:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <refreshableview.RefreshableListView android:id="@+id/refreshable_lv" android:layout_width="match_parent" android:layout_height="match_parent" android:cacheColorHint="@android:color/transparent" /> </LinearLayout>
運(yùn)行結(jié)果如圖:



以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android中使用RecyclerView實(shí)現(xiàn)下拉刷新和上拉加載
- Android下拉刷新上拉加載控件(適用于所有View)
- Android實(shí)現(xiàn)上拉加載更多以及下拉刷新功能(ListView)
- Android RecyclerView實(shí)現(xiàn)下拉刷新和上拉加載
- Android下拉刷新上拉加載更多左滑動(dòng)刪除
- Android ListView實(shí)現(xiàn)上拉加載更多和下拉刷新功能
- Android RecyclerView 上拉加載更多及下拉刷新功能的實(shí)現(xiàn)方法
- Android程序開(kāi)發(fā)之使用PullToRefresh實(shí)現(xiàn)下拉刷新和上拉加載
- Android自定義下拉刷新上拉加載
- Android使用PullToRefresh實(shí)現(xiàn)上拉加載和下拉刷新效果的代碼
相關(guān)文章
Android Studio無(wú)法打開(kāi)得問(wèn)題解決方法
這篇文章主要詳細(xì)介紹了Android Studio無(wú)法打開(kāi)問(wèn)題解決辦法,文中有詳細(xì)的解決步驟和圖文介紹,對(duì)我們解決這個(gè)問(wèn)題有一定的幫助,需要的朋友可以參考下2023-07-07
Android VideoView類(lèi)實(shí)例講解
本文主要介紹Android VideoView類(lèi),這里對(duì)VideoView類(lèi)詳細(xì)說(shuō)明了使用方法,以及示例代碼,有興趣的朋友可以參考下,希望能幫助Android 開(kāi)發(fā)的朋友2016-08-08
詳解Flutter如何使用Completer實(shí)現(xiàn)防抖功能
防抖是用于確保時(shí)間內(nèi)的所有觸發(fā)被合并成單一請(qǐng)求,在Flutter中,我們可以使用Completer 來(lái)實(shí)現(xiàn)防抖功能,下面我們就來(lái)看看具體實(shí)現(xiàn)方法吧2024-03-03
Android實(shí)現(xiàn)網(wǎng)絡(luò)圖片瀏覽器
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)網(wǎng)絡(luò)圖片瀏覽器的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
基于Flutter實(shí)現(xiàn)愛(ài)心三連動(dòng)畫(huà)效果
Animation是一個(gè)抽象類(lèi),它并不參與屏幕的繪制,而是在設(shè)定的時(shí)間范圍內(nèi)對(duì)一段區(qū)間值進(jìn)行插值。本文將利用Animation制作一個(gè)愛(ài)心三連動(dòng)畫(huà)效果,感興趣的可以學(xué)習(xí)一下2022-03-03
Android開(kāi)發(fā)實(shí)現(xiàn)多進(jìn)程彈窗效果
這篇文章主要為大家詳細(xì)介紹了Android開(kāi)發(fā)實(shí)現(xiàn)多進(jìn)程彈窗效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
Compose?for?Desktop?鼠標(biāo)事件示例demo
這篇文章主要為大家介紹了Compose?for?Desktop?鼠標(biāo)事件示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Android自定義view實(shí)現(xiàn)日歷打卡簽到
這篇文章主要為大家詳細(xì)介紹了Android自定義view實(shí)現(xiàn)日歷打卡簽到,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05

