时间:2023-01-15 11:44:12 | 栏目:Android代码 | 点击:次
本文实例为大家分享了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; /** * 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("正常状态"); 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; } /** * 是否允许父控件拦截事件 * @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); } /** * 刷新状态 */ 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; /** * 刷新的view */ private View refreshHeaderView; /** * 刷新的view的真实高度 */ 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); } } /** * 修改当前的刷新状态 * * @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); } /** * 改变某控件的高度动画 * * @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); // 回归正常状态 } }; 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; /** * 刷新的view */ private View refreshHeaderView; /** * 刷新的view的真实高度 */ private int originRefreshHeight; /** * 有效下拉刷新需要达到的高度 */ private int refreshArrivedStateHeight; /** * 刷新时显示的高度 */ private int refreshingHeight; /** * 正常未刷新高度 */ private int refreshNormalHeight; /** * 默认不允许拦截(即,往子view传递事件),该属性只有在interceptAllMoveEvents为false的时候才有效 */ private boolean disallowIntercept = true; /** * xml中可设置它的值为false,表示不把移动的事件传递给子控件 */ 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; /** * 修改拦截设置 * 如果是有效往下拖动事件,则事件需要在本ViewGroup中处理,所以需要拦截不往子控件传递,即不允许拦截设为false * 如果不是有效往下拖动事件,则事件传递给子控件处理,所以不需要拦截,并往子控件传递,即不允许拦截设为true */ 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); } } /** * 修改当前的刷新状态 * * @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); } /** * 改变某控件的高度动画 * * @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); // 回归正常状态 } }; 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(); /** * 初始化各个尺寸高度 * * @param originRefreshHeight * @return */ boolean onInitRefreshHeight(int originRefreshHeight); /** * 刷新状态改变 * * @param refreshView * @param refreshState */ 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>
运行结果如图: