我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android学习教程之下拉刷新实现代码(11)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android学习教程之下拉刷新实现代码(11)

本文实例为大家分享了Android下拉刷新的具体代码,供大家参考,具体内容如下

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;
 
 @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("正常状态");
   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("正常状态");
   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) { // 允许父控件拦截,即不允许父控件拦截设为false
   parentRequestDisallowInterceptTouchEvent(false);
   return false;
  } else { // 不允许父控件拦截,即不允许父控件拦截设为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;
 }
 
 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);
 }
 
 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;
 // 刷新状态监听
 private RefreshableHelper refreshableHelper;
 
 private View refreshHeaderView;
 
 private int originRefreshHeight;
 
 private int refreshArrivedStateHeight;
 
 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);
 // 计算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);
 }
 // 初始化各个高度
 if (isUseDefault) {
  refreshArrivedStateHeight = originRefreshHeight;
  refreshingHeight = originRefreshHeight;
  refreshNormalHeight = 0;
 }
 Log.d(TAG, "[onSizeChanged]refreshHeaderView origin height: " + originRefreshHeight);
 changeViewHeight(refreshHeaderView, refreshNormalHeight);
 // 初始化为正常状态
 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) { // 正常状态,手指往上(列表往下滚动)
   super.onTouchEvent(ev);
   } else {
   // 如果当前没有处在正在刷新状态,则更新刷新状态
   if (STATE_REFRESHING != refreshState) {
    if (curHeight >= refreshArrivedStateHeight) { // 达到可刷新状态
    setRefreshState(STATE_REFRESH_ARRIVED);
    } else if (curHeight == refreshNormalHeight) { // 正常状态
    setRefreshState(STATE_REFRESH_NORMAL);
    } else { // 未达到可刷新状态
    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);
  // 如果是达到刷新状态,则设置正在刷新状态的高度
  if (STATE_REFRESH_ARRIVED == refreshState) { // 达到了刷新的状态
   startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshingHeight);
   setRefreshState(STATE_REFRESHING);
  } else if (STATE_REFRESHING == refreshState) { // 正在刷新的状态
   startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshingHeight);
  } else {
   // 执行动画后回归正常状态
   startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshNormalHeight, normalAnimatorListener);
  }
  break;
 }
 return true;
 }
 
 public void onCompleteRefresh() {
 if (STATE_REFRESHING == refreshState) {
  setRefreshState(STATE_REFRESH_NORMAL);
  startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshNormalHeight);
 }
 }
 
 private void setRefreshState(int expectRefreshState) {
 if (expectRefreshState != refreshState) {
  refreshState = expectRefreshState;
  if (null != refreshableHelper) {
  refreshableHelper.onRefreshStateChanged(refreshHeaderView, refreshState);
  }
 }
 }
 
 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);
 }
 
 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);
 heightAnimator.start();
 }
 AnimatorListenerAdapter normalAnimatorListener = new AnimatorListenerAdapter() {
 @Override
 public void onAnimationEnd(Animator animation) {
  super.onAnimationEnd(animation);
  setRefreshState(STATE_REFRESH_NORMAL); // 回归正常状态
 }
 };
 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);
 }
 
 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;
 // 刷新状态监听
 private RefreshableHelper refreshableHelper;
 public void setRefreshableHelper(RefreshableHelper refreshableHelper) {
 this.refreshableHelper = refreshableHelper;
 }
 private Context context;
 
 private View refreshHeaderView;
 
 private int originRefreshHeight;
 
 private int refreshArrivedStateHeight;
 
 private int refreshingHeight;
 
 private int refreshNormalHeight;
 
 private boolean disallowIntercept = true;
 
 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);
 // 计算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);
 }
 // 初始化各个高度
 if (isUseDefault) {
  refreshArrivedStateHeight = originRefreshHeight;
  refreshingHeight = originRefreshHeight;
  refreshNormalHeight = 0;
 }
 Log.d(TAG, "[onSizeChanged]refreshHeaderView origin height: " + originRefreshHeight);
 changeViewHeight(refreshHeaderView, refreshNormalHeight);
 // 初始化为正常状态
 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;
 }
 // 如果设置了拦截所有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;
  // 是否是有效的往下拖动事件(则需要显示加载header)
  boolean isDropDownValidate = Float.MAX_VALUE != downY;
  
  requestDisallowInterceptTouchEvent(!isDropDownValidate);
  downY = curY;
  Log.d(TAG, "Move --> deltaY(curY - downY): " + deltaY);
  int curHeight = refreshHeaderView.getMeasuredHeight();
  int exceptHeight = curHeight + (int) (deltaY / 2);
  // 如果当前没有处在正在刷新状态,则更新刷新状态
  if (STATE_REFRESHING != refreshState) {
   if (curHeight >= refreshArrivedStateHeight) { // 达到可刷新状态
   setRefreshState(STATE_REFRESH_ARRIVED);
   } else { // 未达到可刷新状态
   setRefreshState(STATE_REFRESH_NOT_ARRIVED);
   }
  }
  if (isDropDownValidate) {
   changeViewHeight(refreshHeaderView, Math.max(refreshNormalHeight, exceptHeight));
  } else { // 防止从子控件修改拦截后引发的downY为Float.MAX_VALUE的问题
   changeViewHeight(refreshHeaderView, Math.max(curHeight, exceptHeight));
  }
  break;
  case MotionEvent.ACTION_UP:
  downY = Float.MAX_VALUE;
  Log.d(TAG, "Up --> downY: " + downY);
  requestDisallowInterceptTouchEvent(true); // 保证事件可往下传递
  // 如果是达到刷新状态,则设置正在刷新状态的高度
  if (STATE_REFRESH_ARRIVED == refreshState) { // 达到了刷新的状态
   startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshingHeight);
   setRefreshState(STATE_REFRESHING);
  } else if (STATE_REFRESHING == refreshState) { // 正在刷新的状态
   startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshingHeight);
  } else {
   // 执行动画后回归正常状态
   startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshNormalHeight, normalAnimatorListener);
  }
  break;
  case MotionEvent.ACTION_CANCEL:
  Log.d(TAG, "cancel");
  break;
 }
 return true;
 }
 
 public void onCompleteRefresh() {
 if (STATE_REFRESHING == refreshState) {
  setRefreshState(STATE_REFRESH_NORMAL);
  startHeightAnimation(refreshHeaderView, refreshHeaderView.getMeasuredHeight(), refreshNormalHeight);
 }
 }
 
 private void setRefreshState(int expectRefreshState) {
 if (expectRefreshState != refreshState) {
  refreshState = expectRefreshState;
  if (null != refreshableHelper) {
  refreshableHelper.onRefreshStateChanged(refreshHeaderView, refreshState);
  }
 }
 }
 
 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);
 }
 
 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);
 heightAnimator.start();
 }
 AnimatorListenerAdapter normalAnimatorListener = new AnimatorListenerAdapter() {
 @Override
 public void onAnimationEnd(Animator animation) {
  super.onAnimationEnd(animation);
  setRefreshState(STATE_REFRESH_NORMAL); // 回归正常状态
 }
 };
 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 onInitRefreshHeaderView();
 
 boolean onInitRefreshHeight(int originRefreshHeight);
 
 void onRefreshStateChanged(View refreshView, int refreshState);
}

main.xml内容:


<?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内容:


<?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内容:


<?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内容:


<?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>

运行结果如图:

这里写图片描述

这里写图片描述

这里写图片描述

您可能感兴趣的文章:Android中使用RecyclerView实现下拉刷新和上拉加载Android下拉刷新上拉加载控件(适用于所有View)Android实现上拉加载更多以及下拉刷新功能(ListView)Android RecyclerView实现下拉刷新和上拉加载Android下拉刷新上拉加载更多左滑动删除Android ListView实现上拉加载更多和下拉刷新功能Android RecyclerView 上拉加载更多及下拉刷新功能的实现方法Android程序开发之使用PullToRefresh实现下拉刷新和上拉加载Android自定义下拉刷新上拉加载Android使用PullToRefresh实现上拉加载和下拉刷新效果的代码


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android学习教程之下拉刷新实现代码(11)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android学习教程之下拉刷新实现代码(11)

本文实例为大家分享了Android下拉刷新的具体代码,供大家参考,具体内容如下 MainActivity.java代码:package siso.refreshablev; import android.app.Activity; impo
2022-06-06

android开发教程之实现listview下拉刷新和上拉刷新效果

代码如下:public class PullToLoadListView extends ListView implements OnScrollListener { private static final String TAG = P
2022-06-06

Android中ListView下拉刷新的实现代码

Android中ListView下拉刷新实现效果图:ListView中的下拉刷新是非常常见的,也是经常使用的,看到有很多同学想要,那我就整理一下,供大家参考。那我就不解释,直接上代码了。这里需要自己重写一下ListView,重写代码如下:p
2023-05-31

Android下拉刷新框架实现代码实例

前段时间项目中用到了下拉刷新功能,之前在网上也找到过类似的demo,但这些demo的质量参差不齐,用户体验也不好,接口设计也不行。最张没办法,终于忍不了了,自己就写了一个下拉刷新的框架,这个框架是一个通用的框架,效果和设计感觉都还不错,现在
2022-06-06

android下拉刷新ListView的介绍和实现代码

大致上,我们发现,下拉刷新的列表和一般列表的区别是,当滚动条在顶端的时候,再往下拉动就会把整个列表拉下来,显示出松开刷新的提示。由此可以看出,在构建这个下拉刷新的组件的时候,只用继承ListView,然后重写onTouchEvent就能实现
2022-06-06

android编程之下拉刷新实现方法分析

本文实例讲述了android编程之下拉刷新实现方法。分享给大家供大家参考,具体如下: 现在android应用里面下拉刷新比较多 ,今天自己研究一下相关的资料public class MyListView extends ListView i
2022-06-06

android使用Ultra-PullToRefresh实现下拉刷新自定义代码

下拉刷新中Ultra-Pull-To-Refresh一直是我最喜欢用的了,这里自定义一个HeaderView的样式。和普通的样式略微有些区别。先看效果图一眼看上去和普通下拉刷新样式没啥区别,但仔细看会发现下拉时的头部是盖在内容上的(为了简便
2022-06-06

Android下拉刷新完全解析,教你如何一分钟实现下拉刷新功能(附源码)

最近项目中需要用到ListView下拉刷新的功能,一开始想图省事,在网上直接找一个现成的,可是尝试了网上多个版本的下拉刷新之后发现效果都不怎么理想。有些是因为功能不完整或有Bug,有些是因为使用起来太复杂,十全十美的还真没找到。因此我也是放
2022-06-06

Android实战教程第四十三篇之上拉加载与下拉刷新

ListView的下拉刷新很常见,很多开源的框架都能做到这个效果,当然也可以自己去实现。本篇案例是基于xlistview的。布局:2022-06-06

Android自定义控件开发实战之实现ListView下拉刷新实例代码

这篇博客为大家介绍一个android常见的功能——ListView下拉刷新:首先下拉未松手时候手机显示这样的界面:下面的代码是自定的扎样的控件:2022-06-06

Android使用PullToRefresh实现上拉加载和下拉刷新效果的代码

在没给大家介绍正文之前,先给大家介绍展示下运行图,如果大家感觉还不错,请继续往下阅读:相关阅读:分享Android中pullToRefresh的使用心得项目已同步至:https://github.com/nanchen2251/pullTo
2022-06-06

Android程序开发之使用PullToRefresh实现下拉刷新和上拉加载

PullToRefresh是一套实现非常好的下拉刷新库,它支持: 1.ListView 2.ExpandableListView 3.GridView 4.WebView 等多种常用的需要刷新的View类型,而且使用起来也十分方便。 (下载
2022-06-06

Android自定义组合控件之自定义下拉刷新和左滑删除实例代码

绪论 最近项目里面用到了下拉刷新和左滑删除,网上找了找并没有可以用的,有比较好的左滑删除,但是并没有和下拉刷新上拉加载结合到一起,要不就是一些比较水的结合,并不能在项目里面使用,小编一着急自己组合了一个,做完了和QQ的对比了一下,并没有太大
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录