diff --git a/README.md b/README.md index de56d9e..5974cba 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,7 @@ # goRefresh ### Apk下载体验 ![image](https://github.com/yanyiqun001/goRefresh/blob/master/screenshots/icon.png) -### 使用 - -![image](https://jitpack.io/v/yanyiqun001/goRefresh.svg) +## 使用方式 项目gradle文件添加 ``` @@ -22,7 +20,214 @@ dependencies{ compile 'com.github.yanyiqun001.goRefresh:refreshlayout_lottie:0.6' (需要使用lottie动画时添加) } ``` -### 截图 + + + +#### 根布局文件 +``` + + + +``` + +#### 下拉刷新 + +###### 简单实现 + +``` + // 设置下拉监听 + goRefreshLayout.setOnRefreshListener(new RefreshListener() { + @Override + public void onRefresh() { + //添加你自己的代码 + } + }); + + // 结束刷新 + goRefreshLayout.finishRefresh(); +``` +###### 自定义实现 + + 自定义header需要实现IHeaderView接口,具体请参看demo + +###### 自定义头部使用lottie动画 (注意添加依赖) +##### 说明:lottie所使用的文件全部来源于 https://www.lottiefiles.com/ 并且不断添加新的动画效果。demo中只是选取了其中几个样式。大家可自由选择合适的样式作为刷新动画 + +##### 集成步骤: +1. 下载动画文件(xxx.json) +2. 在自己洗项目中建立assets文件夹,将动画文件拷贝其中 +3. 头部布局文件中添加LottieAnimationView: lottie_fileName属性添加动画文件名 +``` + + + +``` +4.代码中设置 + ``` + //参数2 头部布局文件layoutid 参数3 LottieAnimationView的id + LottieView lottieView = new LottieView(this, R.layout.lottle_loading_animation, R.id.animation_view); + goRefreshLayout.setHeaderView(lottieView); + ``` +#### 上拉加载 +##### 说明:为了更自然流畅的体验,footerview并没有添加在gorefresh上面,还是使用传统的adapter中添加footer的方式实现,gorefresh只是提供一个统一的入口方便调用。由于listview 和recyclerview添加上拉的实现方式是不同的(lv有setFooterView方法,rv没有),所以在使用方法上也略有不同。 +##### lv使用: +``` + //必须设置 + goRefreshLayout.setHasFooter(true); + + //设置加载状态的footerview (不设置使用默认) + goRefreshLayout.setLoadingView(R.layout.footer_loading); + + //设置加载完毕没有更多数据的footerview(不设置使用默认) + goRefreshLayout.setFinishWithNodataView(R.layout.footer_finish); + + //设置错误状态并且具有重试功能的footerview 第二个参数为重试控件的id (不设置使用默认) + goRefreshLayout.setErrorViewWithRetry(R.layout.footerview_error, R.id.tips); + + //设置监听 + goRefreshLayout.setOnLoadMoreListener(new LoadMoreListener() { + @Override + public void onLoadmore() { + //添加自己的代码 + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + //结束刷新 + rvLoadMoreWrapper.finishLoadMore(); + //结束刷新,没有更多数据 + // rvLoadMoreWrapper.finishLoadMoreWithNoData(); + //加载错误 + // rvLoadMoreWrapper.finishLoadMoreWithError(); + } + }, 2000); + } + }); +``` + +##### rv使用: +``` + //方式1 与lv类似 + goRefreshLayout.setHasFooter(true); + + goRefreshLayout.setLoadingView(R.layout.footer_loading); + + goRefreshLayout.setFinishWithNodataView(R.layout.footer_finish); + + goRefreshLayout.setErrorViewWithRetry(R.layout.footerview_error, R.id.tips); + //构建上拉加载adapter + RvLoadMoreWrapper rvLoadMoreWrapper=goRefreshLayout.buildRvLoadMoreAdapter(adapter); + + recyclerView.setAdapter(rvLoadMoreWrapper); + + goRefreshLayout.setOnLoadMoreListener(new LoadMoreListener() { + @Override + public void onLoadmore() { + //添加自己的代码 + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + //结束刷新 + rvLoadMoreWrapper.finishLoadMore(); + //结束刷新,没有更多数据 + // rvLoadMoreWrapper.finishLoadMoreWithNoData(); + //加载错误 + // rvLoadMoreWrapper.finishLoadMoreWithError(); + } + }, 2000); + } + }); + + //方式2 直接使用RvLoadMoreWrapper进行操作(推荐) + //构建上拉加载adapter + RvLoadMoreWrapper rvLoadMoreWrapper=goRefreshLayout.buildRvLoadMoreAdapter(adapter); + + rvLoadMoreWrapper.setHasFooter(true) + .setLoadingView(R.layout.lottle_loading_animation_footer) + .setFinishView(R.layout.footer_finish) + .setErrorViewWithRetry(R.layout.footer_error,R.id.tips) + .setLoadMoreListener(new LoadMoreListener() { + @Override + public void onLoadmore() { + //添加自己的代码 + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + //结束刷新 + rvLoadMoreWrapper.finishLoadMore(); + //结束刷新,没有更多数据 + // rvLoadMoreWrapper.finishLoadMoreWithNoData(); + //加载错误 + // rvLoadMoreWrapper.finishLoadMoreWithError(); + } + }, 2000); + } + }); + recyclerView.setAdapter(rvLoadMoreWrapper); +``` +##### 自定义footer: + +自定义footer需要实现IFooterView接口 + +示例 + +``` + public class CustomFooter implements IFooterView { + private LayoutInflater inflater; + public CustomFooter(Context context) { + inflater=LayoutInflater.from(context); + } + + @Override + public View getLoadingView() { + return inflater.inflate(R.layout.lottle_loading_animation_footer,null); + } + + @Override + public View getFinishView() { + return inflater.inflate(R.layout.footer_finish,null); + } + + @Override + public View getFailureView() { + return inflater.inflate(R.layout.footer_error,null); + } + + @Override + public int getRetryId() { + return R.id.tips; + } + } +``` +使用 +``` + CustomFooter customFooter = new CustomFooter(this); + goRefreshLayout.setFooterView(customFooter); + //或者 + rvLoadMoreWrapper.setFooterView(customFooter) + //...其余代码略 +``` + +## demo gif + + ![image](https://github.com/yanyiqun001/goRefresh/blob/master/screenshots/gif.gif?raw=true) ![image](https://github.com/yanyiqun001/goRefresh/blob/master/screenshots/gif2.gif?raw=true) diff --git a/app/src/main/java/com/refreshDemo/CustomFooter.java b/app/src/main/java/com/refreshDemo/CustomFooter.java index e1de33a..2f64b95 100644 --- a/app/src/main/java/com/refreshDemo/CustomFooter.java +++ b/app/src/main/java/com/refreshDemo/CustomFooter.java @@ -4,17 +4,15 @@ import android.view.LayoutInflater; import android.view.View; -import com.GoRefresh.DefaultFooterView; +import com.GoRefresh.interfaces.IFooterView; /** * Created by Administrator on 2017/11/24 0024. - * 这里继承了DefaultFooterView 也可直接实现IFooterView接口 */ -public class CustomFooter extends DefaultFooterView { +public class CustomFooter implements IFooterView { private LayoutInflater inflater; public CustomFooter(Context context) { - super(context); inflater=LayoutInflater.from(context); } @@ -25,12 +23,17 @@ public View getLoadingView() { @Override public View getFinishView() { - return super.getFinishView(); + return inflater.inflate(R.layout.footer_finish,null); } @Override public View getFailureView() { - return super.getFailureView(); + return inflater.inflate(R.layout.footer_error,null); + } + + @Override + public int getRetryId() { + return R.id.tips; } diff --git a/app/src/main/java/com/refreshDemo/ListViewActivity.java b/app/src/main/java/com/refreshDemo/ListViewActivity.java index 549271c..2389c8a 100644 --- a/app/src/main/java/com/refreshDemo/ListViewActivity.java +++ b/app/src/main/java/com/refreshDemo/ListViewActivity.java @@ -31,7 +31,7 @@ public class ListViewActivity extends AppCompatActivity { private MyAdapter adapter = new MyAdapter(); private List list = new ArrayList<>(); private int page = 1; - + private Handler handler=new Handler(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -54,7 +54,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { goRefreshLayout.setOnRefreshListener( new RefreshListener() { @Override public void onRefresh() { - new Handler().postDelayed(new Runnable() { + handler.postDelayed(new Runnable() { @Override public void run() { list.clear(); @@ -71,24 +71,24 @@ public void run() { goRefreshLayout.setOnLoadMoreListener(new LoadMoreListener() { @Override public void onLoadmore() { - new Handler().postDelayed(new Runnable() { + handler.postDelayed(new Runnable() { @Override public void run() { if (page == 2) { //加载错误时调用 - goRefreshLayout.finishLoadmoreWithError(); + goRefreshLayout.finishLoadMoreWithError(); page++; return; } if (page == 3) { //无更多数据时调用 - goRefreshLayout.finishLoadmoreWithNoData(); + goRefreshLayout.finishLoadMoreWithNoData(); return; } page++; addData(); //加载完成时调用 - goRefreshLayout.finishLoadmore(); + goRefreshLayout.finishLoadMore(); } }, 2000); } diff --git a/app/src/main/java/com/refreshDemo/LottieActivity.java b/app/src/main/java/com/refreshDemo/LottieActivity.java index ae3ea3a..c815e5b 100644 --- a/app/src/main/java/com/refreshDemo/LottieActivity.java +++ b/app/src/main/java/com/refreshDemo/LottieActivity.java @@ -79,7 +79,7 @@ public void onLoadmore() { @Override public void run() { addData(); - refreshLayout.finishLoadmore(); + refreshLayout.finishLoadMore(); } }, 2000); } diff --git a/app/src/main/java/com/refreshDemo/RecyclerViewActivity.java b/app/src/main/java/com/refreshDemo/RecyclerViewActivity.java index 180be3a..2180e6b 100644 --- a/app/src/main/java/com/refreshDemo/RecyclerViewActivity.java +++ b/app/src/main/java/com/refreshDemo/RecyclerViewActivity.java @@ -11,7 +11,6 @@ import android.widget.ImageView; import android.widget.TextView; -import com.GoRefesh_core.LottieView; import com.GoRefresh.GoRefreshLayout; import com.GoRefresh.RvLoadMoreWrapper; import com.GoRefresh.interfaces.LoadMoreListener; @@ -31,7 +30,6 @@ public class RecyclerViewActivity extends AppCompatActivity { private MyAdapter adapter; private List list = new ArrayList<>(); private final int COUNT = 10; - private LottieView lottieView; private int page = 1; private RvLoadMoreWrapper rvLoadMoreWrapper; @Override @@ -50,30 +48,50 @@ protected void onCreate(Bundle savedInstanceState) { CustomHeader customHeader = new CustomHeader(this); refreshLayout.setHeaderView(customHeader); - //需要上拉刷新必须设置 - refreshLayout.setHasFooter(true); //自定义footer CustomFooter customFooter = new CustomFooter(this); - //设置footerview方式1 直接设置 - refreshLayout.setFooterView(customFooter); - //只设置加载状态的footerview + //设置footerview方式1 + // refreshLayout.setHasFooter(true); + // refreshLayout.setFooterView(customFooter); + //设置加载状态的footerview // refreshLayout.setLoadingView(R.layout.lottle_loading_animation_footer); //上拉加载通过包装adapter实现 通过此方法获得包装后的adapter rvLoadMoreWrapper=refreshLayout.buildRvLoadMoreAdapter(adapter); - - //设置footerview方式2 通过包装后的adapter设置 - rvLoadMoreWrapper.setFooterView(customFooter); - - //只设置加载状态的footerview - // rvLoadMoreWrapper.setLoadingView(R.layout.lottle_loading_animation_footer); + rvLoadMoreWrapper.setHasFooter(true) + .setFooterView(customFooter) +// .setLoadingView(R.layout.lottle_loading_animation_footer) +// .setFinishView(R.layout.footer_finish) +// .setErrorViewWithRetry(R.layout.footer_error,R.id.tips) + .setLoadMoreListener(new LoadMoreListener() { + @Override + public void onLoadmore() { + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + page++; + if (page == 3) { + rvLoadMoreWrapper.finishLoadMoreWithError(); + return; + } + if (page == 5) { + rvLoadMoreWrapper.finishLoadMoreWithNoData(); + return; + } else { + addData(); + rvLoadMoreWrapper.finishLoadMore(); + } + } + }, 2000); + } + }); recyclerView.setAdapter(rvLoadMoreWrapper); - + //设置下拉监听 refreshLayout.setOnRefreshListener(new RefreshListener() { @Override public void onRefresh() { @@ -86,38 +104,34 @@ public void run() { } }); - refreshLayout.setOnLoadMoreListener(new LoadMoreListener() { - @Override - public void onLoadmore() { - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - page++; - if (page == 3) { - refreshLayout.finishLoadmoreWithError(); - return; - } - if (page == 5) { - refreshLayout.finishLoadmoreWithNoData(); - return; - } else { - addData(); - refreshLayout.finishLoadmore(); - } - - } - }, 2000); - } - }); -// rvLoadMoreWrapper.setLoadMoreListener(new LoadMoreListener() { + //设置上拉监听 +// refreshLayout.setOnLoadMoreListener(new LoadMoreListener() { // @Override // public void onLoadmore() { +// new Handler().postDelayed(new Runnable() { +// @Override +// public void run() { +// page++; +// if (page == 3) { +// refreshLayout.finishLoadmoreWithError(); +// return; +// } +// if (page == 5) { +// refreshLayout.finishLoadmoreWithNoData(); +// return; +// } else { +// addData(); +// refreshLayout.finishLoadmore(); +// } // +// } +// }, 2000); // } // }); + //自动刷新 - refreshLayout.startRefresh(); + // refreshLayout.startRefresh(); addData(); } diff --git a/app/src/main/res/layout/activity_recyclerview.xml b/app/src/main/res/layout/activity_recyclerview.xml index 507d26f..be806c9 100644 --- a/app/src/main/res/layout/activity_recyclerview.xml +++ b/app/src/main/res/layout/activity_recyclerview.xml @@ -1,14 +1,12 @@ + android:background="@color/defaultbg"> - + android:background="#fff"/> \ No newline at end of file diff --git a/refreshlayout/src/main/java/com/GoRefresh/GoRefreshLayout.java b/refreshlayout/src/main/java/com/GoRefresh/GoRefreshLayout.java index 8eee665..32fd54d 100644 --- a/refreshlayout/src/main/java/com/GoRefresh/GoRefreshLayout.java +++ b/refreshlayout/src/main/java/com/GoRefresh/GoRefreshLayout.java @@ -9,12 +9,10 @@ import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; -import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; -import android.widget.ListView; import com.GoRefresh.interfaces.IFooterView; import com.GoRefresh.interfaces.IHeaderView; @@ -81,8 +79,6 @@ public class GoRefreshLayout extends ViewGroup { private AbsListView.OnScrollListener mScrollListener; //是否在加载状态 private boolean isLoadingMore; - // //footer显示时true -// private boolean isLoadingMore2; //是否显示hasHeader private boolean hasHeader = true; //是否显示footer @@ -97,7 +93,6 @@ public class GoRefreshLayout extends ViewGroup { private int mOrignY; private int mLastY; private float mCurrentLastY; - private float velocity; //内容固定状态下当前头部偏移 private float fixOffset; @@ -236,9 +231,6 @@ protected void onLayout(boolean b, int i0, int i1, int i2, int i3) { child.layout(0, -child.getMeasuredHeight(), child.getMeasuredWidth(), 0); } } -// else if (child == mFooterView) { -// child.layout(0, getHeight(), child.getMeasuredWidth(), getHeight() + child.getMeasuredHeight()); -// } else { child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight()); } @@ -252,7 +244,6 @@ public boolean onInterceptTouchEvent(MotionEvent event) { int y = (int) event.getY(); switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: - Log.d("onInterceptTouchEvent", "onInterceptTouchEvent==ACTION_DOWN"); mLastY = 0; mOrignY = y; //有偏移时再次按下 ,计算得到mCurrentLastY @@ -271,7 +262,6 @@ public boolean onInterceptTouchEvent(MotionEvent event) { break; case ACTION_MOVE: int dy = y - mLastY; - Log.d("onInterceptTouchEvent", "onInterceptTouchEvent==ACTION_MOVE"); // 内容固定时刷新状态不拦截滑动 // 下拉拦截滑动事件 // 刷新时Y方向有偏移时上拉拦截滑动事件 @@ -369,7 +359,6 @@ else if (mStatus == STATUS_READY) { if (refresrhListener != null) { refresrhListener.onRefresh(); } - // postDelayed(runnable, 4000); } else if (mStatus == STATUS_BACK) { break; } @@ -529,10 +518,6 @@ private void finishToTop() { reset(); } - //-------------------------------------------------------------------------------- - //------------------------------footer相关-------------------------------------- - //-------------------------------------------------------------------------------- - private void reset() { hasY = false; mOrignY = -1; @@ -546,33 +531,6 @@ private void removeHeaderView() { } } - private void removeFooterView() { - if (mFooterView != null) { - if (mContentView instanceof AbsListView) { - ((ListView) mContentView).removeFooterView(mFooterView); - } - } - } - - private boolean valid(int flag) { - if (mFooter != null) { - if (flag == LOADING) { - if (mFooter.getLoadingView() != null) { - return true; - } - } else if (flag == FINISH) { - if (mFooter.getFinishView() != null) { - return true; - } - - } else if (flag == ERROR) { - if (mFooter.getFailureView() != null) { - return true; - } - } - } - return false; - } //-------------------------------------------------------------------------------- //------------------------------对外提供api-------------------------------------- @@ -681,22 +639,22 @@ public void finishRefresh() { /** * 隐藏footerview,加载数据完毕时调用 */ - public void finishLoadmore() { + public void finishLoadMore() { loadMoreHelper.finishLoadMore(mContentView); } /** * 加载数据完毕没有更多数据时调用 */ - public void finishLoadmoreWithNoData() { - loadMoreHelper.finishLoadmoreWithNoData(mContentView); + public void finishLoadMoreWithNoData() { + loadMoreHelper.finishLoadMoreWithNoData(mContentView); } /** * 加载数据出错时调用 */ - public void finishLoadmoreWithError() { - loadMoreHelper.finishLoadmoreWithError(mContentView); + public void finishLoadMoreWithError() { + loadMoreHelper.finishLoadMoreWithError(mContentView); } /** @@ -840,11 +798,11 @@ public void setLoadingView(View view) { * * @param layoutID */ - public void setFinishWithNodataView(int layoutID) { + public void setFinishView(int layoutID) { loadMoreHelper.setFinishWithNodataView(layoutID); } - public void setFinishWithNodataView(View view) { + public void setFinishView(View view) { loadMoreHelper.setFinishWithNodataView(view); } diff --git a/refreshlayout/src/main/java/com/GoRefresh/LoadMoreHelper.java b/refreshlayout/src/main/java/com/GoRefresh/LoadMoreHelper.java index 2d49fcd..edd70de 100644 --- a/refreshlayout/src/main/java/com/GoRefresh/LoadMoreHelper.java +++ b/refreshlayout/src/main/java/com/GoRefresh/LoadMoreHelper.java @@ -103,7 +103,7 @@ public void finishLoadMore(View contentView) { isLoadingMore = false; } - public void finishLoadmoreWithNoData(View contentView) { + public void finishLoadMoreWithNoData(View contentView) { if (contentView instanceof RecyclerView) { if (valid(FINISH)) { if (rvloadMoreWrapper != null) { @@ -118,7 +118,7 @@ public void finishLoadmoreWithNoData(View contentView) { } - public void finishLoadmoreWithError(final View contentView) { + public void finishLoadMoreWithError(final View contentView) { if (contentView instanceof RecyclerView) { if (valid(ERROR)) { if (rvloadMoreWrapper != null) { diff --git a/refreshlayout/src/main/java/com/GoRefresh/RvLoadMoreWrapper.java b/refreshlayout/src/main/java/com/GoRefresh/RvLoadMoreWrapper.java index f12555c..fa39cf7 100644 --- a/refreshlayout/src/main/java/com/GoRefresh/RvLoadMoreWrapper.java +++ b/refreshlayout/src/main/java/com/GoRefresh/RvLoadMoreWrapper.java @@ -20,7 +20,6 @@ public class RvLoadMoreWrapper extends RecyclerView.Adapter T getView(int viewId) { } } - public void setLoadMoreListener(LoadMoreListener loadMoreListener) { + public RvLoadMoreWrapper setLoadMoreListener(LoadMoreListener loadMoreListener) { this.mLoadMoreListener = loadMoreListener; + return this; } - public void setFooterView(IFooterView loadMoreView) { + public RvLoadMoreWrapper setFooterView(IFooterView loadMoreView) { mFooterView = loadMoreView; mLoadMoreView = mFooterView.getLoadingView(); mFinishView = mFooterView.getFinishView(); mErrorView = mFooterView.getFailureView(); mErrorid = mFooterView.getRetryId(); + return this; } @@ -197,14 +198,13 @@ public RvLoadMoreWrapper setFinishView(int finishlayoutID) { return this; } - - public RvLoadMoreWrapper setErrorView(int errorID, int retryOnclicklayoutid) { + public RvLoadMoreWrapper setErrorViewWithRetry(int errorID, int retryOnclicklayoutid) { mErrorlayoutID = errorID; mErrorid = retryOnclicklayoutid; return this; } - public RvLoadMoreWrapper setErrorView(View errorView, int retryOnclicklayoutid) { + public RvLoadMoreWrapper setErrorViewWithRetry(View errorView, int retryOnclicklayoutid) { mErrorid = retryOnclicklayoutid; mErrorView = errorView; return this; @@ -278,12 +278,13 @@ public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { } } - public void setHasFooter(boolean hasFooter) { + public RvLoadMoreWrapper setHasFooter(boolean hasFooter) { if (hasFooter) { LOAD_MORE_STATUS = LOADING; } else { LOAD_MORE_STATUS = NONE; } + return this; } diff --git a/refreshlayout/src/main/res/layout/footer_error.xml b/refreshlayout/src/main/res/layout/footer_error.xml index 8b67f2c..0ecd7a9 100644 --- a/refreshlayout/src/main/res/layout/footer_error.xml +++ b/refreshlayout/src/main/res/layout/footer_error.xml @@ -1,7 +1,7 @@