PullRefreshRecyclerView.java
/** * 类说明:下拉刷新上拉加载更多的RecyclerView * Author: gaobaiq * Date: 2016/5/9 18:09 */ public class PullRefreshRecyclerView extends PullRefreshView { /** * 内置的RecyclerView; */ private RecyclerView mRecyclerView; /** * 可见的最后一个item */ private int lastVisibleItem; /** * 可见的第一个item */ private int firstVisibleItem; /** * 空数据提示布局容器 */ private LinearLayout mEmptyLayout; /** * 是否自动上拉刷新 */ private boolean isAutomaticUp = false; public PullRefreshRecyclerView(Context context) { this(context, null); } public PullRefreshRecyclerView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public PullRefreshRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mRecyclerView = new RecyclerView(context); mRecyclerView.setClipToPadding(false); this.addView(mRecyclerView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); initListener(); } private void initListener() { mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (isAutomaticUp && newState == RecyclerView.SCROLL_STATE_IDLE && pullUp()) { triggerPullUpRefresh(); } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); getVisibleItem(); } }); } private int getMax(int[] arr) { int max = arr[0]; for (int x = 1; x < arr.length; x++) { if (arr[x] > max) max = arr[x]; } return max; } private int getMin(int[] arr) { int min = arr[0]; for (int x = 1; x < arr.length; x++) { if (arr[x] < min) min = arr[x]; } return min; } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: getVisibleItem(); break; } return super.onTouchEvent(event); } /** * 获取当前第一个显示的item 和 最后一个显示的item. */ private void getVisibleItem() { RecyclerView.LayoutManager layout = mRecyclerView.getLayoutManager(); if (layout != null) { if (layout instanceof LinearLayoutManager) { lastVisibleItem = ((LinearLayoutManager) layout).findLastVisibleItemPosition(); firstVisibleItem = ((LinearLayoutManager) layout).findFirstVisibleItemPosition(); } else if (layout instanceof GridLayoutManager) { lastVisibleItem = ((GridLayoutManager) layout).findLastVisibleItemPosition(); firstVisibleItem = ((GridLayoutManager) layout).findFirstVisibleItemPosition(); } else if (layout instanceof StaggeredGridLayoutManager) { int[] lastPositions = new int[((StaggeredGridLayoutManager) layout).getSpanCount()]; ((StaggeredGridLayoutManager) layout).findLastVisibleItemPositions(lastPositions); lastVisibleItem = getMax(lastPositions); int[] firstPositions = new int[((StaggeredGridLayoutManager) layout).getSpanCount()]; ((StaggeredGridLayoutManager) layout).findFirstVisibleItemPositions(firstPositions); firstVisibleItem = getMin(lastPositions); } } } @Override protected boolean isChildBottom(ViewGroup viewGroup) { boolean resultValue = false; int childNum = viewGroup.getChildCount(); if (childNum == 0 || mRecyclerView.getChildCount() == 0) { resultValue = false; } else { if (mRecyclerView.equals(getChildAt(2)) && lastVisibleItem != mRecyclerView.getAdapter().getItemCount() - 1) { return false; } View view = viewGroup.getChildAt(childNum - 1); int bottomMargin = ((MarginLayoutParams) view.getLayoutParams()).bottomMargin; if (view.getBottom() + bottomMargin + viewGroup.getPaddingBottom() <= getHeight()) { resultValue = true; } } return resultValue; } @Override protected boolean isChildTop(ViewGroup viewGroup) { boolean resultValue = false; int childNum = viewGroup.getChildCount(); if (childNum == 0) { resultValue = true; } else { if (mRecyclerView.equals(getChildAt(2)) && firstVisibleItem != 0) { return false; } View view = viewGroup.getChildAt(0); int topMargin = ((MarginLayoutParams) view.getLayoutParams()).topMargin; if (view.getTop() - topMargin - viewGroup.getPaddingTop() >= 0) { resultValue = true; } } return resultValue; } @Override public void triggerPullDownRefresh() { mRecyclerView.scrollToPosition(0); super.triggerPullDownRefresh(); } /** * 设置空布局 * * @param emptyView * @param layoutGravity 空布局在父布局的方向 */ public void setEmptyView(View emptyView, int layoutGravity) { if (mEmptyLayout == null) { initEmptyLayout(); } mEmptyLayout.setGravity(layoutGravity); mEmptyLayout.addView(emptyView); } /** * 显示空布局 */ public void showEmptyView() { if (mEmptyLayout != null && mEmptyLayout.getParent() == null) { addView(mEmptyLayout, 2); } if (mRecyclerView.getParent() != null) { removeView(mRecyclerView); } } /** * 隐藏空布局 */ public void hideEmptyView() { if (mRecyclerView.getParent() == null) { addView(mRecyclerView, 2); } if (mEmptyLayout != null && mEmptyLayout.getParent() != null) { removeView(mEmptyLayout); } } private void initEmptyLayout() { mEmptyLayout = new LinearLayout(mContext); LayoutParams lp = new LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); mEmptyLayout.setLayoutParams(lp); mEmptyLayout.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return true; } }); } /** * 滑动到底部时,是否自动触发上拉加载更多。 * * @param isAutomaticUp */ public void isAutomaticUp(boolean isAutomaticUp) { this.isAutomaticUp = isAutomaticUp; } //提供获取内置RecyclerView的方法 public RecyclerView getRecyclerView() { return mRecyclerView; } //********* 提供一系列对内置RecyclerView的操作方法 *********// public void setLayoutManager(RecyclerView.LayoutManager layoutManager) { mRecyclerView.setLayoutManager(layoutManager); } public void setAdapter(RecyclerView.Adapter adapter) { mRecyclerView.setAdapter(adapter); } public void setItemAnimator(RecyclerView.ItemAnimator animator) { mRecyclerView.setItemAnimator(animator); } public void addItemDecoration(RecyclerView.ItemDecoration decor) { mRecyclerView.addItemDecoration(decor); } public void addItemDecoration(RecyclerView.ItemDecoration decor, int index) { mRecyclerView.addItemDecoration(decor, index); } public void setViewPadding(int left, int top, int right, int bottom) { mRecyclerView.setPadding(left, top, right, bottom); } }
PullRefreshView.java
/** * 类说明: 自定义的上下拉刷新控件 * Author: gaobaiq * Date: 2016/5/9 17:27 */ public class PullRefreshView extends ViewGroup { private static final String TAG = PullRefreshView.class.getSimpleName(); protected Context mContext; //头部下拉的最小高度 private static final int HEAD_DEFAULT_HEIGHT = 100; //尾部上拉的最小高度 private static final int TAIL_DEFAULT_HEIGHT = 100; /** * 头部容器 */ private LinearLayout mHeadLayout; /** * 头部View */ private View mHead; /** * 头部的高度 */ private int mHeadHeight = HEAD_DEFAULT_HEIGHT; /** * 尾部容器 */ private LinearLayout mTailLayout; /** * 尾部View */ private View mTail; /** * 尾部的高度 */ private int mTailHeight = TAIL_DEFAULT_HEIGHT; /** * 滑动的偏移量 */ private int mScrollOffset = 0; /** * 标记 无状态(既不是上拉 也 不是下拉) */ private final int STATE_NOT = -1; /** * 标记 上拉状态 */ private final int STATE_UP = 1; /** * 标记 下拉状态 */ private final int STATE_DOWN = 2; /** * 当前状态 */ private int mCurrentState = STATE_NOT; /** * 是否处于下拉 正在更新状态 */ private boolean mIsPullDown = false; /** * 是否处于上拉 正在加载状态 */ private boolean mIsPullUp = false; /** * 是否启用下拉功能(默认不开启) */ private boolean mIsDownRefresh = true; /** * 是否启用上拉功能(默认不开启) */ private boolean mIsUpRefresh = false; /** * 加载状态 */ private boolean mIsLoading = false; private int mDamp = 4; /** * 头部状态监听器 */ private OnHeadStateListener mHeadStateListener; /** * 尾部状态监听器 */ private OnTailStateListener mTailStateListener; /** * 上拉监听器 */ private OnPullUpRefreshListener mPullUpRefreshListener; /** * 下拉监听器 */ private OnPullDownRefreshListener mPullDownRefreshListener; /** * 是否还有更多数据。 */ private boolean isMore = true; public PullRefreshView(Context context) { this(context, null); } public PullRefreshView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public PullRefreshView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; setClipToPadding(false); initHeadLayout(); initTailLayout(); } /** * 初始化头部 */ private void initHeadLayout() { mHeadLayout = new LinearLayout(mContext); LayoutParams lp = new LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); mHeadLayout.setGravity(Gravity.CENTER | Gravity.BOTTOM); mHeadLayout.setLayoutParams(lp); addView(mHeadLayout); } /** * 设置头部View * * @param head */ public void setHead(View head) { mHead = head; mHeadLayout.removeAllViews(); mHeadLayout.addView(mHead); //获取头部高度 mHeadLayout.post(new Runnable() { @Override public void run() { if (mHead.getHeight() > HEAD_DEFAULT_HEIGHT) { mHeadHeight = mHead.getHeight(); } else { mHeadHeight = HEAD_DEFAULT_HEIGHT; } Log.e(TAG, "mHeadHeight" + mHeadHeight); //当获取到头部高度的时候,如果正处于下拉刷新状态,应该把头部打开。 if (mIsPullDown) { scroll(-mHeadHeight); } invalidate(); } }); } /** * 初始化尾部 */ private void initTailLayout() { mTailLayout = new LinearLayout(mContext); LayoutParams lp = new LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); mTailLayout.setGravity(Gravity.CENTER | Gravity.BOTTOM); mTailLayout.setLayoutParams(lp); addView(mTailLayout); } /** * 设置尾部View * * @param tail */ public void setTail(View tail) { mTail = tail; mTailLayout.removeAllViews(); mTailLayout.addView(mTail); //获取尾部高度 mTailLayout.post(new Runnable() { @Override public void run() { if (mTail.getHeight() > TAIL_DEFAULT_HEIGHT) { mTailHeight = mTail.getHeight(); } else { mTailHeight = TAIL_DEFAULT_HEIGHT; } Log.e(TAG, "mTailHeight" + mTailHeight); //当获取到尾部高度的时候,如果正处于上拉刷新状态,应该把尾部打开。 if (mIsPullUp) { scroll(mTailHeight); } } }); invalidate(); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { //布局头部 View head = getChildAt(0); head.layout(getPaddingLeft(), -mHeadHeight, getPaddingLeft() + head.getMeasuredWidth(), 0); //布局尾部 View tail = getChildAt(1); tail.layout(getPaddingLeft(), getMeasuredHeight(), getPaddingLeft() + tail.getMeasuredWidth(), getMeasuredHeight() + mTailHeight); //布局内容容器 int count = getChildCount(); if (count > 2) { View content = getChildAt(2); content.layout(getPaddingLeft(), getPaddingTop(), getPaddingLeft() + content.getMeasuredWidth(), getPaddingTop() + content.getMeasuredHeight()); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //测量头部高度 View head = getChildAt(0); measureChild(head, widthMeasureSpec, heightMeasureSpec); //测量尾部高度 View tail = getChildAt(1); measureChild(tail, widthMeasureSpec, heightMeasureSpec); //测量内容容器宽高 int count = getChildCount(); int contentHeight = 0; int contentWidth = 0; if (count > 2) { View content = getChildAt(2); measureChild(content, widthMeasureSpec, heightMeasureSpec); contentHeight = content.getMeasuredHeight(); contentWidth = content.getMeasuredWidth(); } //设置PullRefresView的宽高 setMeasuredDimension(measureWidth(widthMeasureSpec, contentWidth), measureHeigth(heightMeasureSpec, contentHeight)); } private int measureWidth(int measureSpec, int contentWidth) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { result = contentWidth + getPaddingLeft() + getPaddingRight(); if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } private int measureHeigth(int measureSpec, int contentHeight) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { result = contentHeight + getPaddingTop() + getPaddingBottom(); if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } /** * 设置是否启用上下拉功能 * * @param isDownRefresh 是否开启下拉功能 默认开启 * @param isUpRefresh 是否开启上拉功能 默认不开启 */ public void setRefresh(boolean isDownRefresh, boolean isUpRefresh) { mIsDownRefresh = isDownRefresh; mIsUpRefresh = isUpRefresh; } /** * 还原 */ private void restore() { mCurrentState = STATE_NOT; scroll(0); } /** * 通知刷新完成 */ public void refreshFinish() { restore(); if (mIsLoading) { mIsLoading = false; if (mIsPullUp) { mIsPullUp = false; if (mTailStateListener != null && isMore) { mTailStateListener.onRetractTail(mTail); } } else if (mIsPullDown) { mIsPullDown = false; if (mHeadStateListener != null) { mHeadStateListener.onRetractHead(mHead); } } } } public void isMore(boolean isMore) { this.isMore = isMore; if (mTailStateListener != null) { if (isMore) { mTailStateListener.onHasMore(mTail); } else { mTailStateListener.onNotMore(mTail); } } } /** * 触发下拉刷新 */ public void triggerPullDownRefresh() { if (!mIsDownRefresh) { return; } if (!mIsLoading) { mIsLoading = true; mIsPullDown = true; mCurrentState = STATE_NOT; scroll(-mHeadHeight); if (mHeadStateListener != null) { mHeadStateListener.onRefreshHead(mHead); } if (mPullDownRefreshListener != null) { mPullDownRefreshListener.onRefresh(); } } } /** * 触发上拉刷新 */ public void triggerPullUpRefresh() { if (!mIsUpRefresh) { return; } if (!mIsLoading) { mIsLoading = true; mIsPullUp = true; mCurrentState = STATE_NOT; scroll(mTailHeight); if (mTailStateListener != null && isMore) { mTailStateListener.onRefreshTail(mTail); } if (isMore) { if (mPullUpRefreshListener != null) { mPullUpRefreshListener.onRefresh(); } } else { refreshFinish(); } } } /** * @param offset */ private void scroll(int offset) { if (offset < 0 && !mIsDownRefresh) { return; } if (offset > 0 && !mIsUpRefresh) { return; } scrollTo(0, offset); mScrollOffset = Math.abs(offset); if (mCurrentState == STATE_DOWN && mHeadStateListener != null) { mHeadStateListener.onScrollChange(mHead, mScrollOffset, mScrollOffset >= mHeadHeight ? 100 : mScrollOffset * 100 / mHeadHeight); } if (mCurrentState == STATE_UP && mTailStateListener != null && isMore) { mTailStateListener.onScrollChange(mTail, mScrollOffset, mScrollOffset >= mTailHeight ? 100 : mScrollOffset * 100 / mTailHeight); } } /** * 设置拉动阻力 (1到10) * * @param damp */ public void setDamp(int damp) { if (damp < 1) { mDamp = 1; } else if (damp > 10) { mDamp = 10; } else { mDamp = damp; } } @Override public boolean onTouchEvent(MotionEvent event) { int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: return true; case MotionEvent.ACTION_MOVE: if (mY > y) { if (mCurrentState == STATE_UP) { scroll((mY - y) / mDamp); } } else if (mCurrentState == STATE_DOWN) { scroll((mY - y) / mDamp); } break; case MotionEvent.ACTION_UP: if (!mIsPullDown && !mIsPullUp) { if (mCurrentState == STATE_DOWN) { if (mScrollOffset < mHeadHeight) { restore(); } else { triggerPullDownRefresh(); } } else if (mCurrentState == STATE_UP) { if (mScrollOffset < mTailHeight) { restore(); } else { triggerPullUpRefresh(); } } else { restore(); } } mY = 0; break; default: break; } return super.onTouchEvent(event); } int mY = 0; @Override public boolean onInterceptTouchEvent(MotionEvent ev) { int y = (int) ev.getY(); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mY = (int) ev.getY(); return false; case MotionEvent.ACTION_MOVE: if (mIsLoading) { return false; } if (pullDown() && y - mY > 20) { mCurrentState = STATE_DOWN; return true; } if (pullUp() && mY - y > 20) { mCurrentState = STATE_UP; return true; } return false; case MotionEvent.ACTION_UP: return false; } return false; } protected boolean pullDown() { return mCurrentState != STATE_UP && mIsDownRefresh && isTop(); } protected boolean pullUp() { return mCurrentState != STATE_DOWN && mIsUpRefresh && isBottom(); } protected boolean isTop() { if (getChildCount() < 2) { return true; } View view = getChildAt(2); if (view instanceof ViewGroup) { if (view instanceof ScrollView) { ScrollView scrollView = (ScrollView) view; return scrollView.getScrollY() <= 0; } else { return isChildTop((ViewGroup) view); } } else { return true; } } protected boolean isChildTop(ViewGroup viewGroup) { int minY = 0; int count = viewGroup.getChildCount(); for (int i = 0; i < count; i++) { View view = viewGroup.getChildAt(i); int topMargin = 0; LayoutParams lp = view.getLayoutParams(); if (lp instanceof MarginLayoutParams) { topMargin = ((MarginLayoutParams) lp).topMargin; } int top = view.getTop() - topMargin; minY = Math.min(minY, top); } return minY >= 0; } protected boolean isBottom() { if (getChildCount() < 2) { return false; } View view = getChildAt(2); if (view instanceof ViewGroup) { if (view instanceof ScrollView) { ScrollView scrollView = (ScrollView) view; if (scrollView.getChildCount() > 0) { return scrollView.getScrollY() >= scrollView.getChildAt(0).getHeight() - scrollView.getHeight(); } else { return true; } } else { return isChildBottom((ViewGroup) view); } } else { return true; } } protected boolean isChildBottom(ViewGroup viewGroup) { int maxY = 0; int count = viewGroup.getChildCount(); if (count == 0) { return false; } for (int i = 0; i < count; i++) { View view = viewGroup.getChildAt(i); int bottomMargin = 0; LayoutParams lp = view.getLayoutParams(); if (lp instanceof MarginLayoutParams) { bottomMargin = ((MarginLayoutParams) lp).bottomMargin; } int bottom = view.getBottom() + bottomMargin; maxY = Math.max(maxY, bottom); } int h = viewGroup.getMeasuredHeight() - viewGroup.getPaddingBottom(); return maxY <= h; } /** * 设置头部监听器 * * @param listener */ public void setOnHeadStateListener(OnHeadStateListener listener) { mHeadStateListener = listener; } /** * 设置尾部监听器 * * @param listener */ public void setOnTailStateListener(OnTailStateListener listener) { mTailStateListener = listener; } /** * 设置上拉监听器 * * @param listener */ public void setOnPullUpRefreshListener(OnPullUpRefreshListener listener) { mPullUpRefreshListener = listener; } /** * 设置下拉监听器 * * @param listener */ public void setOnPullDownRefreshListener(OnPullDownRefreshListener listener) { mPullDownRefreshListener = listener; } /** * 移除头部监听器 */ public void removeOnHeadStateListener() { mHeadStateListener = null; } /** * 移除尾部监听器 */ public void removeOnTailStateListener() { mTailStateListener = null; } /** * 移除上拉监听器 */ public void removeOnPullUpRefreshListener() { mPullUpRefreshListener = null; } /** * 移除下拉监听器 */ public void removeOnPullDownRefreshListener() { mPullDownRefreshListener = null; } //---------------- 监听接口 -------------------// /** * 头部状态监听器 */ public interface OnHeadStateListener { /** * 头部滑动变化 * * @param head 头部View * @param scrollOffset 滑动距离 * @param scrollRatio 从开始到触发阀值的滑动比率(0到100)如果滑动到达了阀值,就算在滑动,这个值也是100 */ void onScrollChange(View head, int scrollOffset, int scrollRatio); /** * 头部处于刷新状态 (触发下拉刷新的时候调用) * * @param head 头部View */ void onRefreshHead(View head); /** * 头部收起 * * @param head 头部View */ void onRetractHead(View head); } /** * 头部状态监听器 */ public interface OnTailStateListener { /** * 尾部滑动变化 * * @param tail 尾部View * @param scrollOffset 滑动距离 * @param scrollRatio 从开始到触发阀值的滑动比率(0到100)如果滑动到达了阀值,就算在滑动,这个值也是100 */ void onScrollChange(View tail, int scrollOffset, int scrollRatio); /** * 尾部处于加载状态 (触发上拉加载的时候调用) * * @param tail 尾部View */ void onRefreshTail(View tail); /** * 尾部收起 * * @param tail 尾部View */ void onRetractTail(View tail); /** * 没有更多 * * @param tail */ void onNotMore(View tail); /** * 有更多 * * @param tail */ void onHasMore(View tail); } /** * 上拉加载监听器 */ public interface OnPullUpRefreshListener { void onRefresh(); } /** * 下拉更新监听器 */ public interface OnPullDownRefreshListener { void onRefresh(); } }
HeadView.java
/** * 类说明: 下拉刷新头部View * Author: gaobaiq * Date: 2016/5/9 19:07 */ public class HeadView extends LinearLayout implements PullRefreshView.OnHeadStateListener { ImageView ivHeaderDownArrow; ImageView ivHeaderLoading; TextView textView; AnimationDrawable animationDrawable; private boolean isReach = false; public HeadView(Context context) { super(context); animationDrawable = (AnimationDrawable) getResources().getDrawable(R.drawable.progress_round); init(context); } private void init(Context context) { LayoutInflater inflater = LayoutInflater.from(context); View layout = inflater.inflate(R.layout.head_view_layout, this, false); this.addView(layout, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); initView(layout); restore(); this.setPadding(0, 30, 0, 20); } private void initView(View view){ ivHeaderDownArrow = (ImageView)view.findViewById(R.id.iv_header_down_arrow); ivHeaderLoading = (ImageView)view.findViewById(R.id.iv_header_loading); textView = (TextView)view.findViewById(R.id.tv_header_state); } @Override public void onScrollChange(View head, int scrollOffset, int scrollRatio) { if (scrollRatio == 100 && !isReach) { textView.setText("松开刷新"); ivHeaderDownArrow.setRotation(180); isReach = true; } else if (scrollRatio != 100 && isReach) { textView.setText("下拉刷新"); ivHeaderDownArrow.setRotation(0); isReach = false; } } @Override public void onRefreshHead(View head) { ivHeaderLoading.setVisibility(VISIBLE); ivHeaderDownArrow.setVisibility(GONE); ivHeaderLoading.setImageDrawable(animationDrawable); animationDrawable.start(); textView.setText("正在刷新"); } @Override public void onRetractHead(View head) { restore(); animationDrawable.stop(); isReach = false; } private void restore() { ivHeaderLoading.setVisibility(GONE); ivHeaderDownArrow.setVisibility(VISIBLE); ivHeaderLoading.setImageResource(R.drawable.loading1); ivHeaderDownArrow.setImageResource(R.drawable.icon_down_arrow); ivHeaderDownArrow.setRotation(0); textView.setText("下拉刷新"); } }
TailView.java
/** * 类说明: 尾部上拉加载更多 * Author: gaobaiq * Date: 2016/4/18 10:12 */ public class TailView extends LinearLayout implements PullRefreshView.OnTailStateListener { ImageView ivHeaderDownArrow; ImageView ivHeaderLoading; TextView textView; AnimationDrawable animationDrawable; private boolean isReach = false; private boolean isMore = true; public TailView(Context context) { super(context); animationDrawable = (AnimationDrawable) getResources().getDrawable(R.drawable.progress_round); init(context); } private void init(Context context) { LayoutInflater inflater = LayoutInflater.from(context); View layout = inflater.inflate(R.layout.head_view_layout, this, false); this.addView(layout, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); initView(layout); restore(); this.setPadding(0, 20, 0, 30); } private void initView(View view){ ivHeaderDownArrow = (ImageView)view.findViewById(R.id.iv_header_down_arrow); ivHeaderLoading = (ImageView)view.findViewById(R.id.iv_header_loading); textView = (TextView)view.findViewById(R.id.tv_header_state); } @Override public void onScrollChange(View tail, int scrollOffset, int scrollRatio) { if (isMore) { if (scrollRatio == 100 && !isReach) { textView.setText("松开加载"); ivHeaderDownArrow.setRotation(0); isReach = true; } else if (scrollRatio != 100 && isReach) { textView.setText("上拉加载"); isReach = false; ivHeaderDownArrow.setRotation(180); } } } @Override public void onRefreshTail(View tail) { if (isMore) { ivHeaderLoading.setVisibility(VISIBLE); ivHeaderDownArrow.setVisibility(GONE); ivHeaderLoading.setImageDrawable(animationDrawable); // AnimationDrawable animationDrawable = (AnimationDrawable) head.getBackground(); animationDrawable.start(); textView.setText("正在加载"); } } @Override public void onRetractTail(View tail) { // animationDrawable = (AnimationDrawable) head.getBackground(); if (isMore) { restore(); animationDrawable.stop(); isReach = false; } } @Override public void onNotMore(View tail) { ivHeaderLoading.setVisibility(GONE); ivHeaderDownArrow.setVisibility(GONE); textView.setText("已经全部加载完毕"); isMore = false; } @Override public void onHasMore(View tail) { ivHeaderLoading.setVisibility(GONE); ivHeaderDownArrow.setVisibility(VISIBLE); textView.setText("上拉加载"); isMore = true; } private void restore() { ivHeaderLoading.setVisibility(GONE); ivHeaderDownArrow.setVisibility(VISIBLE); ivHeaderLoading.setImageResource(R.drawable.loading1); ivHeaderDownArrow.setImageResource(R.drawable.icon_down_arrow); ivHeaderDownArrow.setRotation(180); textView.setText("上拉加载"); } }
PullRefreshUtil.java
/** * 类说明: * Author: gaobaiq * Date: 2016/5/9 20:04 */ public class PullRefreshUtil { /** * 刷新控件的基本配件 (头部、尾部都用默认的) * * @param view 刷新控件 * @param isDownRefresh 是否开启下拉刷新 * @param isUpRefresh 是否开启上拉加载 */ public static void setRefresh(PullRefreshView view, boolean isDownRefresh, boolean isUpRefresh) { HeadView headView = null; TailView tailView = null; if (isDownRefresh) { headView = new HeadView(view.getContext()); } if (isUpRefresh) { tailView = new TailView(view.getContext()); } setRefresh(view, isDownRefresh, isUpRefresh, headView, tailView, headView, tailView); } /** * 刷新控件的基本配件 (自定义头部、尾部用默认的) * * @param view 刷新控件 * @param isDownRefresh 是否开启下拉刷新 * @param isUpRefresh 是否开启上拉加载 * @param headView 头部View * @param headStateListener 头部监听器 */ public static void setRefresh(PullRefreshView view, boolean isDownRefresh, boolean isUpRefresh, View headView, PullRefreshView.OnHeadStateListener headStateListener) { TailView tailView = null; if (isUpRefresh) { tailView = new TailView(view.getContext()); } setRefresh(view, isDownRefresh, isUpRefresh, headView, tailView, headStateListener, tailView); } /** * 刷新控件的基本配件 (自定义尾部 、头部用默认的) * * @param view 刷新控件 * @param isDownRefresh 是否开启下拉刷新 * @param isUpRefresh 是否开启上拉加载 * @param tailView 尾部View * @param tailStateListener 尾部监听器 */ public static void setRefresh(PullRefreshView view, boolean isDownRefresh, boolean isUpRefresh, View tailView, PullRefreshView.OnTailStateListener tailStateListener) { HeadView headView = null; if (isDownRefresh) { headView = new HeadView(view.getContext()); } setRefresh(view, isDownRefresh, isUpRefresh, headView, tailView, headView, tailStateListener); } /** * 刷新控件的基本配件 (自定义头部、尾部) * * @param view 刷新控件 * @param isDownRefresh 是否开启下拉刷新 * @param isUpRefresh 是否开启上拉加载 * @param headView 头部View * @param tailView 尾部View * @param headStateListener 头部监听器 * @param tailStateListener 尾部监听器 */ public static void setRefresh(PullRefreshView view, boolean isDownRefresh, boolean isUpRefresh, View headView, View tailView, PullRefreshView.OnHeadStateListener headStateListener, PullRefreshView.OnTailStateListener tailStateListener) { view.setRefresh(isDownRefresh, isUpRefresh); if (isDownRefresh) { view.setHead(headView); view.setOnHeadStateListener(headStateListener); } if (isUpRefresh) { view.setTail(tailView); view.setOnTailStateListener(tailStateListener); } } }
progress_round.xml
<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/loading1" android:duration="50" /> <item android:drawable="@drawable/loading2" android:duration="50" /> <item android:drawable="@drawable/loading3" android:duration="50" /> <item android:drawable="@drawable/loading4" android:duration="50" /> <item android:drawable="@drawable/loading5" android:duration="50" /> <item android:drawable="@drawable/loading6" android:duration="50" /> <item android:drawable="@drawable/loading7" android:duration="50" /> <item android:drawable="@drawable/loading8" android:duration="50" /> <item android:drawable="@drawable/loading9" android:duration="50" /> <item android:drawable="@drawable/loading10" android:duration="50" /> <item android:drawable="@drawable/loading11" android:duration="50" /> <item android:drawable="@drawable/loading12" android:duration="50" /> </animation-list>
head_view_layout.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="5dp" android:gravity="center"> <ImageView android:id="@+id/iv_header_down_arrow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/icon_down_arrow" /> <ImageView android:id="@+id/iv_header_loading" android:layout_width="25dp" android:layout_height="25dp" android:src="@drawable/progress_round"/> <TextView android:id="@+id/tv_header_state" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:paddingLeft="5dp" android:textSize="13sp" android:textColor="#979797" android:text="Loading" /> </LinearLayout>
调用:
<com.app.gaobaiq.pullrefresh.PullRefreshRecyclerView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent"/> PullRefreshUtil.setRefresh(mList, true, true); mList.setOnPullDownRefreshListener(new PullRefreshView.OnPullDownRefreshListener() { @Override public void onRefresh() {
mList.isMore(true); pageNum = 1; loadData(); } });
mList.setOnPullUpRefreshListener( new PullRefreshView.OnPullUpRefreshListener() { @Override public void onRefresh() { pageNum++; loadData(); } }); // 加载完成 if (mList!= null) { mList.refreshFinish(); }
<com.app.gaobaiq.pullrefresh.PullRefreshView android:id="@+id/refresh_view" android:layout_width="match_parent" android:layout_height="match_parent"> <ScrollView android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> </LinearLayout> </ScrollView> </com.app.gaobaiq.pullrefresh.PullRefreshView> PullRefreshUtil.setRefresh(mRefreshView, true, true); mRefreshView.setOnPullDownRefreshListener( new PullRefreshView.OnPullDownRefreshListener() { @Override public void onRefresh() { pageNum = 1; mRefreshView.isMore(true); loadData(); } }); mRefreshView.setOnPullUpRefreshListener( new PullRefreshView.OnPullUpRefreshListener() { @Override public void onRefresh() { pageNum++; loadData(); } }); // 加载完成 if (mRefreshView != null) { mRefreshView.refreshFinish(); }
时间: 2024-10-29 19:08:56