标签:
一.概述
Android 下拉刷新几乎是每个应用都必带的功能, 并且现在下拉刷新第三方库也越来越多了,很方便就能实现该功能, 下面我介绍一下 自己常用的几个方法.
二.例子
第一种方式:就是集成ListView实现自定义控件完成上下拉刷新
public class PullToRefreshListView extends ListView implements OnScrollListener, OnClickListener { /** * 下拉状态 */ private static final int PULL_TO_REFRESH = 1; //下拉-默认为初始状态 准备下拉刷新 private static final int RELEASE_TO_REFRESH = 2; //释放刷新 private static final int REFRESHING = 3; //正在刷新 private static final String TAG = "PullRefreshListView"; private OnRefreshListener mOnRefreshListener; /** * 组件滑动监听器 scroll 当view在进行下拉滑动的时候,判断滑动的距离, * 如果达到可以进行刷新的临界点时候,回调当前接口中的方法 * Listener that will receive notifications every time the list scrolls. */ private OnScrollListener mOnScrollListener; //下拉刷新的的头部view private LinearLayout mRefreshView; private ImageView mRefreshViewImage; private ProgressBar mRefreshViewProgress; private TextView mRefreshViewText; private TextView mRefreshViewLastUpdated; private int mRefreshState; private int mCurrentScrollState; private RotateAnimation mFlipAnimation; private RotateAnimation mReverseFlipAnimation; private int mRefreshViewHeight; private int mRefreshOriginalTopPadding; private int mLastMotionY; public PullToRefreshListView(Context context) { super(context); init(context); } public PullToRefreshListView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } private void init(Context context) { mFlipAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); mFlipAnimation.setInterpolator(new LinearInterpolator()); mFlipAnimation.setDuration(250); mFlipAnimation.setFillAfter(true); mReverseFlipAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); mReverseFlipAnimation.setInterpolator(new LinearInterpolator()); mReverseFlipAnimation.setDuration(250); mReverseFlipAnimation.setFillAfter(true); mRefreshView = (LinearLayout) View.inflate(context, R.layout.pull_to_refresh_header, null); mRefreshViewText = (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_text); mRefreshViewImage = (ImageView) mRefreshView.findViewById(R.id.pull_to_refresh_image); mRefreshViewProgress = (ProgressBar) mRefreshView.findViewById(R.id.pull_to_refresh_progress); mRefreshViewLastUpdated = (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_updated_at); mRefreshState = PULL_TO_REFRESH; mRefreshViewImage.setMinimumHeight(50); //设置下拉最小的高度为50 setFadingEdgeLength(0); setHeaderDividersEnabled(false); //把refreshview加入到listview的头部 addHeaderView(mRefreshView); super.setOnScrollListener(this); mRefreshView.setOnClickListener(this); mRefreshView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); mRefreshViewHeight = mRefreshView.getMeasuredHeight(); mRefreshOriginalTopPadding = -mRefreshViewHeight; resetHeaderPadding(); } /** * Set the listener that will receive notifications every time the list scrolls. * * @param l The scroll listener. */ @Override public void setOnScrollListener(OnScrollListener l) { mOnScrollListener = l; } /** * 注册listview下拉刷新回到接口 * Register a callback to be invoked when this list should be refreshed. * * @param onRefreshListener The callback to run. */ public void setOnRefreshListener(OnRefreshListener onRefreshListener) { mOnRefreshListener = onRefreshListener; } /** * 进行设置设置上一次更新的时候 * * Set a text to represent when the list was last updated. * @param lastUpdated Last updated at. */ public void setLastUpdated(CharSequence lastUpdated) { if (lastUpdated != null) { mRefreshViewLastUpdated.setVisibility(View.VISIBLE); mRefreshViewLastUpdated.setText(lastUpdated); } else { mRefreshViewLastUpdated.setVisibility(View.GONE); } } /** * touch事件处理 * @param event * @return */ @Override public boolean onTouchEvent(MotionEvent event) { final int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mLastMotionY = y; break; case MotionEvent.ACTION_MOVE: int offsetY = (int) event.getY(); int deltY = Math.round(offsetY - mLastMotionY); mLastMotionY = offsetY; if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) { deltY = deltY / 2; mRefreshOriginalTopPadding += deltY; if (mRefreshOriginalTopPadding < -mRefreshViewHeight) { mRefreshOriginalTopPadding = -mRefreshViewHeight; } resetHeaderPadding(); } break; case MotionEvent.ACTION_UP: //当手指抬开得时候 进行判断下拉的距离 ,如果>=临界值,那么进行刷洗,否则回归原位 if (!isVerticalScrollBarEnabled()) { setVerticalScrollBarEnabled(true); } if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) { if (mRefreshView.getBottom() >= mRefreshViewHeight && mRefreshState == RELEASE_TO_REFRESH) { //准备开始刷新 prepareForRefresh(); } else { // Abort refresh resetHeader(); } } break; } return super.onTouchEvent(event); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL && mRefreshState != REFRESHING) { if (firstVisibleItem == 0) { if ((mRefreshView.getBottom() >= mRefreshViewHeight) && mRefreshState != RELEASE_TO_REFRESH) { mRefreshViewText.setText(R.string.pull_to_refresh_release_label_it); mRefreshViewImage.clearAnimation(); mRefreshViewImage.startAnimation(mFlipAnimation); mRefreshState = RELEASE_TO_REFRESH; } else if (mRefreshView.getBottom() < mRefreshViewHeight && mRefreshState != PULL_TO_REFRESH) { mRefreshViewText.setText(R.string.pull_to_refresh_pull_label_it); mRefreshViewImage.clearAnimation(); mRefreshViewImage.startAnimation(mReverseFlipAnimation); mRefreshState = PULL_TO_REFRESH; } } } if (mOnScrollListener != null) { mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); } } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { mCurrentScrollState = scrollState; if (mOnScrollListener != null) { mOnScrollListener.onScrollStateChanged(view, scrollState); } } /** * Sets the header padding back to original size. */ private void resetHeaderPadding() { mRefreshView.setPadding( mRefreshView.getPaddingLeft(), mRefreshOriginalTopPadding, mRefreshView.getPaddingRight(), mRefreshView.getPaddingBottom()); } public void prepareForRefresh() { if (mRefreshState != REFRESHING) { mRefreshState = REFRESHING; mRefreshOriginalTopPadding = 0; resetHeaderPadding(); mRefreshViewImage.clearAnimation(); mRefreshViewImage.setVisibility(View.GONE); mRefreshViewProgress.setVisibility(View.VISIBLE); mRefreshViewText.setText(R.string.pull_to_refresh_refreshing_label_it); onRefresh(); } } private void resetHeader() { mRefreshState = PULL_TO_REFRESH; mRefreshOriginalTopPadding = -mRefreshViewHeight; resetHeaderPadding(); mRefreshViewImage.clearAnimation(); mRefreshViewImage.setVisibility(View.VISIBLE); mRefreshViewProgress.setVisibility(View.GONE); mRefreshViewText.setText(R.string.pull_to_refresh_pull_label_it); } /** * 开始回调刷新 */ public void onRefresh() { Log.d(TAG, "onRefresh"); if (mOnRefreshListener != null) { mOnRefreshListener.onRefresh(); } } /** * Resets the list to a normal state after a refresh. */ public void onRefreshComplete() { Log.d(TAG, "onRefreshComplete"); resetHeader(); } @Override public void onClick(View v) { Log.d(TAG, "onClick"); } /** * Interface definition for a callback to be invoked when list should be * refreshed. */ public interface OnRefreshListener { /** * Called when the list should be refreshed. * <p> * A call to {@link PullToRefreshListView #onRefreshComplete()} is * expected to indicate that the refresh has completed. */ public void onRefresh(); } }
上面代码就完成了,上下拉刷新工作, 直接拷贝到工程无需任何修改就可使用
当然它还需一个"头布局"
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pull_to_refresh_header" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#F3F3F3" android:orientation="vertical" > <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingTop="23dip" > <LinearLayout android:id="@+id/pull_to_refresh_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:orientation="vertical" > <TextView android:id="@+id/pull_to_refresh_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:text="@string/pull_to_refresh_pull_label" android:textColor="#777777" android:textSize="16sp" /> <TextView android:id="@+id/pull_to_refresh_updated_at" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:text="@string/pull_to_refresh_updated_at" android:textColor="#999999" android:textSize="14sp" /> </LinearLayout> <ProgressBar android:id="@+id/pull_to_refresh_progress" android:layout_width="30dip" android:layout_height="30dip" android:layout_marginRight="22dip" android:layout_marginTop="5dip" android:layout_toLeftOf="@+id/pull_to_refresh_view" android:indeterminate="true" android:indeterminateDrawable="@anim/ic_loading_refresh" android:visibility="gone" /> <ImageView android:id="@+id/pull_to_refresh_image" android:layout_width="32dip" android:layout_height="32dip" android:layout_marginRight="20dip" android:layout_marginTop="5dip" android:layout_toLeftOf="@+id/pull_to_refresh_view" android:contentDescription="@string/app_name" android:gravity="center" android:src="@drawable/ic_refresh_down" /> </RelativeLayout> <View android:layout_width="fill_parent" android:layout_height="15dip" /> </LinearLayout>
此外代码中还用到了 时间的工具类: 如下
public class SharedPreferencesHelper { private static final String SHARED_PATH = "fda_shared"; private static SharedPreferencesHelper instance; private SharedPreferences sp; private SharedPreferences.Editor editor; public static SharedPreferencesHelper getInstance(Context context) { if (instance == null && context != null) { instance = new SharedPreferencesHelper(context); } return instance; } private SharedPreferencesHelper(Context context) { sp = context.getSharedPreferences(SHARED_PATH, Context.MODE_PRIVATE); editor = sp.edit(); } public long getLongValue(String key) { if (key != null && !key.equals("")) { return sp.getLong(key, 0); } return 0; } public String getStringValue(String key) { if (key != null && !key.equals("")) { return sp.getString(key, null); } return null; } public int getIntValue(String key) { if (key != null && !key.equals("")) { return sp.getInt(key, 0); } return 0; } public int getIntValueByDefault(String key) { if (key != null && !key.equals("")) { return sp.getInt(key, 0); } return 0; } public boolean getBooleanValue(String key) { if (key != null && !key.equals("")) { return sp.getBoolean(key, false); } return true; } public float getFloatValue(String key) { if (key != null && !key.equals("")) { return sp.getFloat(key, 0); } return 0; } public void putStringValue(String key, String value) { if (key != null && !key.equals("")) { editor = sp.edit(); editor.putString(key, value); editor.commit(); } } public void putIntValue(String key, int value) { if (key != null && !key.equals("")) { editor = sp.edit(); editor.putInt(key, value); editor.commit(); } } public void putBooleanValue(String key, boolean value) { if (key != null && !key.equals("")) { editor = sp.edit(); editor.putBoolean(key, value); editor.commit(); } } public void putLongValue(String key, long value) { if (key != null && !key.equals("")) { editor = sp.edit(); editor.putLong(key, value); editor.commit(); } } public void putFloatValue(String key, Float value) { if (key != null && !key.equals("")) { editor = sp.edit(); editor.putFloat(key, value); editor.commit(); } } }
public class SharedPreferencesTag { public static final String DEMO_KEY="demo_key"; }
public class UIUtils { /** * 设置上次更新数据时间 * @param listView * @param key key表示具体某个列表 */ public static void setPullToRefreshLastUpdated(PullToRefreshListView listView, String key,Context pContext) { SharedPreferencesHelper spHelper = SharedPreferencesHelper.getInstance(pContext); long lastUpdateTimeStamp = spHelper.getLongValue(key); listView.setLastUpdated(getUpdateTimeString(lastUpdateTimeStamp)); } /** * 保存更新数据时间 * @param listView * @param key key表示具体某个列表 */ public static void savePullToRefreshLastUpdateAt(PullToRefreshListView listView, String key,Context pContext) { listView.onRefreshComplete(); SharedPreferencesHelper spHelper = SharedPreferencesHelper.getInstance(pContext); long lastUpdateTimeStamp=System.currentTimeMillis(); spHelper.putLongValue(key, lastUpdateTimeStamp); listView.setLastUpdated(getUpdateTimeString(lastUpdateTimeStamp)); } /** * 更新时间字符串 * @param timestamp * @return */ @SuppressLint("SimpleDateFormat") public static String getUpdateTimeString(long timestamp) { if (timestamp <= 0) { return "上次更新时间:"; } else { String textDate = "上次更新时间:"; Calendar now = Calendar.getInstance(); Calendar c = Calendar.getInstance(); c.setTimeInMillis(timestamp); if (c.get(Calendar.YEAR) == now.get(Calendar.YEAR) && c.get(Calendar.MONTH) == now.get(Calendar.MONTH) && c.get(Calendar.DATE) == now.get(Calendar.DATE)) { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); return textDate += sdf.format(c.getTime()); } else if (c.get(Calendar.YEAR) == now.get(Calendar.YEAR)) { SimpleDateFormat sdf = new SimpleDateFormat("MM/dd HH:mm"); return textDate += sdf.format(c.getTime()); } else { SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm"); return textDate += sdf.format(c.getTime()); } } } }
这样就完成了, 测试效果图
源码地址:https://yunpan.cn/cryrD4r7PIgWb (提取码:fcb1)
--------------------------------------------------------------------------------------------------------
如果觉得上面的写法太麻烦,或者根本就不想自己写代码,那就用第三方库吧,PullToRefresh
使用步骤:
1. https://github.com/cardview/Android-PullToRefresh 下载源码
2. 解压下载文件, 把library 作为Module导入 Android studio
3. 把该library 最为库,引入 自己工程中
引用文章:http://blog.csdn.net/hantangsongming/article/details/42490277
标签:
原文地址:http://www.cnblogs.com/android-zcq/p/5135859.html