├── .gitignore
├── BaseRecyclerAndAdapter
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── org
│ │ └── itheima
│ │ └── recycler
│ │ ├── L.java
│ │ ├── adapter
│ │ ├── BaseLoadMoreRecyclerAdapter.java
│ │ └── BaseRecyclerAdapter.java
│ │ ├── bean
│ │ ├── BasePageBean.java
│ │ └── SwipeRefreshBean.java
│ │ ├── header
│ │ └── RecyclerViewHeader.java
│ │ ├── listener
│ │ ├── ItemClickSupport.java
│ │ └── PullToMoreListener.java
│ │ ├── viewholder
│ │ └── BaseRecyclerViewHolder.java
│ │ └── widget
│ │ ├── BaseSwipeRefreshHeaderRecyclerView.java
│ │ ├── ItheimaHeaderRecyclerView.java
│ │ ├── ItheimaRecyclerView.java
│ │ ├── PullToLoadMoreRecyclerView.java
│ │ ├── RecyclerViewHeader.java
│ │ └── SwipeRefreshHeaderRecyclerView.java
│ └── res
│ ├── layout
│ ├── itheima_header_recyclerview_layout.xml
│ └── itheima_item_loadmore_layout.xml
│ └── values
│ ├── attrs.xml
│ ├── color.xml
│ └── ids.xml
├── README.md
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── img
├── jitpack.png
├── loadMoreAdapter.png
└── recyclerViewHeader.png
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 | /.idea
11 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | .idea
5 | .DS_Store
6 | /build
7 | /captures
8 | .externalNativeBuild
9 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'android-apt'
3 | android {
4 | compileSdkVersion 24
5 | buildToolsVersion "25.0.0"
6 |
7 | defaultConfig {
8 | minSdkVersion 11
9 | targetSdkVersion 24
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 |
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | }
23 |
24 | dependencies {
25 | compile 'com.android.support:appcompat-v7:24.2.1'
26 | compile 'com.android.support:recyclerview-v7:24.2.1'
27 | compile 'com.jakewharton:butterknife:8.4.0'
28 | apt 'com.jakewharton:butterknife-compiler:8.4.0'
29 | compile 'com.github.open-android:RetrofitUtils:0.4.13'
30 | }
31 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\_tools\_java\android\android-sdk\android-sdk-windows/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/java/org/itheima/recycler/L.java:
--------------------------------------------------------------------------------
1 | package org.itheima.recycler;
2 |
3 | import android.util.Log;
4 |
5 |
6 | public class L {
7 |
8 | public static boolean isDebug = false;
9 | private static final String TAG = "TAG_ADAPTER";
10 |
11 | public static void i(String tag, String message) {
12 | if (isDebug) {
13 | Log.i(tag, message);
14 | }
15 | }
16 |
17 | public static void i(String message) {
18 | i(TAG, message);
19 | }
20 |
21 | public static void e(String tag, String message) {
22 | if (isDebug) {
23 | Log.e(tag, message);
24 | }
25 | }
26 |
27 | public static void e(String message) {
28 | e(TAG, message);
29 | }
30 |
31 | public static void e(String tag, String message, Throwable e) {
32 | if (isDebug) {
33 | Log.e(tag, message, e);
34 | }
35 |
36 |
37 | }
38 |
39 | public static void e(String tag, Throwable e) {
40 | e(tag, "", e);
41 | }
42 |
43 | public static void e(Throwable e, String message) {
44 | e(TAG, message, e);
45 | }
46 |
47 | public static void e(Throwable e) {
48 | e(TAG, "", e);
49 | }
50 |
51 |
52 | public static void isDebug(boolean isDebug) {
53 | L.isDebug = isDebug;
54 | }
55 |
56 |
57 |
58 |
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/java/org/itheima/recycler/adapter/BaseLoadMoreRecyclerAdapter.java:
--------------------------------------------------------------------------------
1 | package org.itheima.recycler.adapter;
2 |
3 | import android.support.v7.widget.RecyclerView;
4 | import android.text.TextUtils;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.ProgressBar;
8 | import android.widget.TextView;
9 |
10 | import org.itheima.recycler.R;
11 | import org.itheima.recycler.listener.PullToMoreListener;
12 | import org.itheima.recycler.viewholder.BaseRecyclerViewHolder;
13 |
14 | import java.util.List;
15 |
16 | /**
17 | * Created by lyl on 2016/10/7.
18 | */
19 |
20 | public class BaseLoadMoreRecyclerAdapter extends BaseRecyclerAdapter {
21 | //加载更多类型
22 | protected final int ITHEIMA_FOOT_TYPE = "ITHEIMA_FOOT_TYPE".hashCode();
23 |
24 | protected PullToMoreListener mPullAndMoreListener;
25 |
26 |
27 | public BaseLoadMoreRecyclerAdapter(RecyclerView recyclerView, Class extends BaseRecyclerViewHolder> viewHolderClazz, int itemResId, List datas) {
28 | super(recyclerView, viewHolderClazz, itemResId, datas);
29 |
30 | }
31 |
32 | @Override
33 | public int getItemViewType(int position) {
34 | return (getItemCount() - 1 == position) ? ITHEIMA_FOOT_TYPE : super.getItemViewType(position);
35 | }
36 |
37 | @Override
38 | public int getItemCount() {
39 | int itemCount = super.getItemCount();
40 | return itemCount == 0 ? 0 : itemCount + 1;
41 | }
42 |
43 | @Override
44 | public final BaseRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
45 | if (viewType == ITHEIMA_FOOT_TYPE) {
46 | return new LoadMoreViewHolder(parent, R.layout.itheima_item_loadmore_layout);
47 | }
48 | return super.onCreateViewHolder(parent, viewType);
49 | }
50 |
51 | @Override
52 | public void onBindViewHolder(BaseRecyclerViewHolder holder, int position) {
53 | if (position == mItemCount) {
54 | holder.onBindData(position, null);
55 | } else {
56 | super.onBindViewHolder(holder, position);
57 | }
58 | }
59 |
60 | public void setPullAndMoreListener(PullToMoreListener listener) {
61 | mPullAndMoreListener = listener;
62 | }
63 |
64 |
65 | public class LoadMoreViewHolder extends BaseRecyclerViewHolder {
66 |
67 | ProgressBar mProgressBar;
68 |
69 | TextView tvLoading;
70 |
71 | public LoadMoreViewHolder(ViewGroup parentView, int itemResId) {
72 | super(parentView, itemResId);
73 | mProgressBar = (ProgressBar) itemView.findViewById(R.id.progress_bar);
74 | tvLoading = (TextView) itemView.findViewById(R.id.tv_loading);
75 | }
76 |
77 | @Override
78 | protected void onBindRealData() {
79 | if (mPullAndMoreListener != null) {
80 | mPullAndMoreListener.onRefreshLoadMore(this);
81 | }
82 | }
83 |
84 | public void loading(String txt) {
85 | mProgressBar.setVisibility(View.VISIBLE);
86 | tvLoading.setText(TextUtils.isEmpty(txt) ? "加载中..." : txt);
87 | }
88 |
89 | public void loadingFinish(String txt) {
90 | mProgressBar.setVisibility(View.GONE);
91 | tvLoading.setText(TextUtils.isEmpty(txt) ? "没有更多数据" : txt);
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/java/org/itheima/recycler/adapter/BaseRecyclerAdapter.java:
--------------------------------------------------------------------------------
1 | package org.itheima.recycler.adapter;
2 |
3 | import android.support.v7.widget.RecyclerView;
4 | import android.view.ViewGroup;
5 |
6 | import org.itheima.recycler.L;
7 | import org.itheima.recycler.viewholder.BaseRecyclerViewHolder;
8 |
9 | import java.lang.reflect.Constructor;
10 | import java.lang.reflect.ParameterizedType;
11 | import java.lang.reflect.Type;
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | /**
16 | * 通过反射创建viewHolder
17 | * Created by lyl on 2016/10/3.
18 | */
19 |
20 | public class BaseRecyclerAdapter extends RecyclerView.Adapter {
21 | protected List mDatas;
22 | protected int mItemCount;
23 | protected int mItemResId;
24 |
25 | protected Class mViewHolderClazz;
26 |
27 | /**
28 | * @param recyclerView
29 | * @param viewHolderClazz
30 | * @param itemResId recyclerView条目的资源id
31 | * @param datas recyclerView展示的数据集合(可以传null)
32 | */
33 | public BaseRecyclerAdapter(RecyclerView recyclerView, Class extends BaseRecyclerViewHolder> viewHolderClazz, int itemResId, List datas) {
34 | mDatas = datas != null ? datas : new ArrayList();
35 | mItemResId = itemResId;
36 | if (recyclerView != null) {
37 | recyclerView.setAdapter(this);
38 | }
39 | mViewHolderClazz = viewHolderClazz;
40 | }
41 |
42 | @Override
43 | public BaseRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
44 | // return ViewHolderFactory.onCreateRealViewHolder(parent, mItemResId);
45 | try {
46 | Constructor con = mViewHolderClazz.getConstructor(ViewGroup.class, int.class);
47 | return con.newInstance(parent, mItemResId);
48 | } catch (Exception e) {
49 | L.e(e);
50 | return null;
51 | }
52 |
53 | }
54 |
55 | @Override
56 | public void onBindViewHolder(BaseRecyclerViewHolder holder, int position) {
57 | holder.onBindData(position, mDatas.get(position));
58 | }
59 |
60 | /**
61 | * @param isLoadMore 数据是否累加
62 | * @param datas 数据
63 | */
64 | public void addDatas(boolean isLoadMore, List datas) {
65 | if (!isLoadMore) {
66 | clearAllData();
67 | }
68 | if (datas != null && datas.size() > 0) {
69 | mDatas.addAll(datas);
70 | notifyDataSetChanged();
71 | }
72 | }
73 |
74 | public void clearAllData() {
75 | if (mDatas != null && !mDatas.isEmpty()) {
76 | mDatas.clear();
77 | }
78 | }
79 |
80 |
81 | @Override
82 | public int getItemCount() {
83 | mItemCount = mDatas != null ? mDatas.size() : 0;
84 | return mItemCount;
85 | }
86 |
87 | public Class getClazz() {
88 | Type mySuperClass = getClass().getGenericSuperclass();
89 | Type type = ((ParameterizedType) mySuperClass).getActualTypeArguments()[0];
90 | return type.getClass();
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/java/org/itheima/recycler/bean/BasePageBean.java:
--------------------------------------------------------------------------------
1 | package org.itheima.recycler.bean;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * 分页的基类bean
7 | * Created by lyl on 2016/10/7.
8 | */
9 |
10 | public abstract class BasePageBean {
11 | //@SerializedName("totalCount")
12 | public int totalCount = 0;
13 | public int currentPage = 1;
14 | public int totalPage = 0;
15 | public int pageSize = 20;
16 |
17 | public abstract List getItemDatas();
18 |
19 | public int getTotalCount() {
20 | return totalCount;
21 | }
22 |
23 | public int getCurrentPage() {
24 | return currentPage;
25 | }
26 |
27 | public int getTotalPage() {
28 | return totalPage;
29 | }
30 |
31 | public int getPageSize() {
32 | return pageSize;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/java/org/itheima/recycler/bean/SwipeRefreshBean.java:
--------------------------------------------------------------------------------
1 | package org.itheima.recycler.bean;
2 |
3 | import org.itheima.recycler.viewholder.BaseRecyclerViewHolder;
4 |
5 | /**
6 | * Created by lyl on 2016/11/21.
7 | */
8 |
9 | public class SwipeRefreshBean {
10 |
11 | public int recyclerViewItemResId;
12 |
13 | public Class extends BaseRecyclerViewHolder> viewHolderClazz;
14 |
15 |
16 | public Class extends BasePageBean> httpResponseBeanClazz;
17 |
18 | public String apiUrl;
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/java/org/itheima/recycler/header/RecyclerViewHeader.java:
--------------------------------------------------------------------------------
1 | package org.itheima.recycler.header;
2 |
3 | import android.content.Context;
4 | import android.graphics.Rect;
5 | import android.support.annotation.CallSuper;
6 | import android.support.annotation.IntDef;
7 | import android.support.annotation.NonNull;
8 | import android.support.annotation.Nullable;
9 | import android.support.v7.widget.GridLayoutManager;
10 | import android.support.v7.widget.LinearLayoutManager;
11 | import android.support.v7.widget.RecyclerView;
12 | import android.support.v7.widget.StaggeredGridLayoutManager;
13 | import android.util.AttributeSet;
14 | import android.view.MotionEvent;
15 | import android.view.View;
16 | import android.widget.RelativeLayout;
17 |
18 | import java.lang.annotation.Retention;
19 | import java.lang.annotation.RetentionPolicy;
20 |
21 | public class RecyclerViewHeader extends RelativeLayout {
22 |
23 | @Visibility
24 | private int intendedVisibility = VISIBLE;
25 | private int downTranslation;
26 | private boolean hidden = false;
27 | private boolean recyclerWantsTouch;
28 | private boolean isVertical;
29 | private boolean isAttachedToRecycler;
30 | private RecyclerViewDelegate recyclerView;
31 | private LayoutManagerDelegate layoutManager;
32 |
33 | public RecyclerViewHeader(Context context) {
34 | super(context);
35 | }
36 |
37 | public RecyclerViewHeader(Context context, AttributeSet attrs) {
38 | super(context, attrs);
39 | }
40 |
41 | public RecyclerViewHeader(Context context, AttributeSet attrs, int defStyle) {
42 | super(context, attrs, defStyle);
43 | }
44 |
45 | /**
46 | * Attaches RecyclerViewHeader
to RecyclerView
.
47 | * Be sure that setLayoutManager(...)
has been called for RecyclerView
before calling this method.
48 | *
49 | * @param recycler RecyclerView
to attach RecyclerViewHeader
to.
50 | */
51 | public final void attachTo(@NonNull final RecyclerView recycler) {
52 | validate(recycler);
53 | this.recyclerView = RecyclerViewDelegate.with(recycler);
54 | this.layoutManager = LayoutManagerDelegate.with(recycler.getLayoutManager());
55 | isVertical = layoutManager.isVertical();
56 | isAttachedToRecycler = true;
57 | recyclerView.setHeaderDecoration(new HeaderItemDecoration());
58 | recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
59 | @Override
60 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
61 | onScrollChanged();
62 | }
63 | });
64 | recyclerView.setOnChildAttachListener(new RecyclerView.OnChildAttachStateChangeListener() {
65 | @Override
66 | public void onChildViewAttachedToWindow(View view) {
67 | }
68 |
69 | @Override
70 | public void onChildViewDetachedFromWindow(View view) {
71 | recycler.post(new Runnable() {
72 | @Override
73 | public void run() {
74 | recyclerView.invalidateItemDecorations();
75 | onScrollChanged();
76 | }
77 | });
78 | }
79 | });
80 | }
81 |
82 | /**
83 | * Detaches RecyclerViewHeader
from RecyclerView
.
84 | */
85 | public final void detach() {
86 | if (isAttachedToRecycler) {
87 | isAttachedToRecycler = false;
88 | recyclerWantsTouch = false;
89 | recyclerView.reset();
90 | recyclerView = null;
91 | layoutManager = null;
92 | }
93 | }
94 |
95 | private void onScrollChanged() {
96 | hidden = recyclerView.hasItems() && !layoutManager.isFirstRowVisible();
97 | RecyclerViewHeader.super.setVisibility(hidden ? INVISIBLE : intendedVisibility);
98 | if (!hidden) {
99 | final int translation = calculateTranslation();
100 | if (isVertical) {
101 | setTranslationY(translation);
102 | } else {
103 | setTranslationX(translation);
104 | }
105 | }
106 | }
107 |
108 | private int calculateTranslation() {
109 | int offset = recyclerView.getScrollOffset(isVertical);
110 | int base = layoutManager.isReversed() ? recyclerView.getTranslationBase(isVertical) : 0;
111 | return base - offset;
112 | }
113 |
114 | @Override
115 | public final void setVisibility(@Visibility int visibility) {
116 | this.intendedVisibility = visibility;
117 | if (!hidden) {
118 | super.setVisibility(intendedVisibility);
119 | }
120 | }
121 |
122 | @Visibility
123 | @Override
124 | public final int getVisibility() {
125 | return intendedVisibility;
126 | }
127 |
128 | @Override
129 | protected final void onLayout(boolean changed, int l, int t, int r, int b) {
130 | super.onLayout(changed, l, t, r, b);
131 | if (changed && isAttachedToRecycler) {
132 | int verticalMargins = 0;
133 | int horizontalMargins = 0;
134 | if (getLayoutParams() instanceof MarginLayoutParams) {
135 | final MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();
136 | verticalMargins = layoutParams.topMargin + layoutParams.bottomMargin;
137 | horizontalMargins = layoutParams.leftMargin + layoutParams.rightMargin;
138 | }
139 | recyclerView.onHeaderSizeChanged(getHeight() + verticalMargins, getWidth() + horizontalMargins);
140 | onScrollChanged();
141 | }
142 | }
143 |
144 | @Override
145 | @CallSuper
146 | public boolean onInterceptTouchEvent(MotionEvent ev) {
147 | recyclerWantsTouch = isAttachedToRecycler && recyclerView.onInterceptTouchEvent(ev);
148 | if (recyclerWantsTouch && ev.getAction() == MotionEvent.ACTION_MOVE) {
149 | downTranslation = calculateTranslation();
150 | }
151 | return recyclerWantsTouch || super.onInterceptTouchEvent(ev);
152 | }
153 |
154 | @Override
155 | @CallSuper
156 | public boolean onTouchEvent(@NonNull MotionEvent event) {
157 | if (recyclerWantsTouch) { // this cannot be true if recycler is not attached
158 | int scrollDiff = downTranslation - calculateTranslation();
159 | int verticalDiff = isVertical ? scrollDiff : 0;
160 | int horizontalDiff = isVertical ? 0 : scrollDiff;
161 | MotionEvent recyclerEvent =
162 | MotionEvent.obtain(event.getDownTime(),
163 | event.getEventTime(),
164 | event.getAction(),
165 | event.getX() - horizontalDiff,
166 | event.getY() - verticalDiff,
167 | event.getMetaState());
168 | recyclerView.onTouchEvent(recyclerEvent);
169 | return false;
170 | }
171 | return super.onTouchEvent(event);
172 | }
173 |
174 | private void validate(RecyclerView recyclerView) {
175 | if (recyclerView.getLayoutManager() == null) {
176 | throw new IllegalStateException("Be sure to attach RecyclerViewHeader after setting your RecyclerView's LayoutManager.");
177 | }
178 | }
179 |
180 | private class HeaderItemDecoration extends RecyclerView.ItemDecoration {
181 | private int headerHeight;
182 | private int headerWidth;
183 | private int firstRowSpan;
184 |
185 | public HeaderItemDecoration() {
186 | firstRowSpan = layoutManager.getFirstRowSpan();
187 | }
188 |
189 | public void setWidth(int width) {
190 | headerWidth = width;
191 | }
192 |
193 | public void setHeight(int height) {
194 | headerHeight = height;
195 | }
196 |
197 | @Override
198 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
199 | super.getItemOffsets(outRect, view, parent, state);
200 | final boolean headerRelatedPosition = parent.getChildLayoutPosition(view) < firstRowSpan;
201 | int heightOffset = headerRelatedPosition && isVertical ? headerHeight : 0;
202 | int widthOffset = headerRelatedPosition && !isVertical ? headerWidth : 0;
203 | if (layoutManager.isReversed()) {
204 | outRect.bottom = heightOffset;
205 | outRect.right = widthOffset;
206 | } else {
207 | outRect.top = heightOffset;
208 | outRect.left = widthOffset;
209 | }
210 | }
211 | }
212 |
213 | private static class RecyclerViewDelegate {
214 |
215 | @NonNull
216 | private final RecyclerView recyclerView;
217 | private HeaderItemDecoration decoration;
218 | private RecyclerView.OnScrollListener onScrollListener;
219 | private RecyclerView.OnChildAttachStateChangeListener onChildAttachListener;
220 |
221 | private RecyclerViewDelegate(final @NonNull RecyclerView recyclerView) {
222 | this.recyclerView = recyclerView;
223 | }
224 |
225 | public static RecyclerViewDelegate with(@NonNull RecyclerView recyclerView) {
226 | return new RecyclerViewDelegate(recyclerView);
227 | }
228 |
229 | public final void onHeaderSizeChanged(int height, int width) {
230 | if (decoration != null) {
231 | decoration.setHeight(height);
232 | decoration.setWidth(width);
233 | recyclerView.post(new Runnable() {
234 | @Override
235 | public void run() {
236 | invalidateItemDecorations();
237 | }
238 | });
239 | }
240 | }
241 |
242 | private void invalidateItemDecorations() {
243 | if (!recyclerView.isComputingLayout()) {
244 | recyclerView.invalidateItemDecorations();
245 | }
246 | }
247 |
248 | public final int getScrollOffset(boolean isVertical) {
249 | return isVertical ? recyclerView.computeVerticalScrollOffset() : recyclerView.computeHorizontalScrollOffset();
250 | }
251 |
252 | public final int getTranslationBase(boolean isVertical) {
253 | return isVertical ?
254 | recyclerView.computeVerticalScrollRange() - recyclerView.getHeight() :
255 | recyclerView.computeHorizontalScrollRange() - recyclerView.getWidth();
256 | }
257 |
258 | public final boolean hasItems() {
259 | return recyclerView.getAdapter() != null && recyclerView.getAdapter().getItemCount() != 0;
260 | }
261 |
262 | public final void setHeaderDecoration(HeaderItemDecoration decoration) {
263 | clearHeaderDecoration();
264 | this.decoration = decoration;
265 | recyclerView.addItemDecoration(this.decoration, 0);
266 | }
267 |
268 | public final void clearHeaderDecoration() {
269 | if (decoration != null) {
270 | recyclerView.removeItemDecoration(decoration);
271 | decoration = null;
272 | }
273 | }
274 |
275 | public final void setOnScrollListener(RecyclerView.OnScrollListener onScrollListener) {
276 | clearOnScrollListener();
277 | this.onScrollListener = onScrollListener;
278 | recyclerView.addOnScrollListener(this.onScrollListener);
279 | }
280 |
281 | public final void clearOnScrollListener() {
282 | if (onScrollListener != null) {
283 | recyclerView.removeOnScrollListener(onScrollListener);
284 | onScrollListener = null;
285 | }
286 | }
287 |
288 | public final void setOnChildAttachListener(RecyclerView.OnChildAttachStateChangeListener onChildAttachListener) {
289 | clearOnChildAttachListener();
290 | this.onChildAttachListener = onChildAttachListener;
291 | recyclerView.addOnChildAttachStateChangeListener(this.onChildAttachListener);
292 | }
293 |
294 | public final void clearOnChildAttachListener() {
295 | if (onChildAttachListener != null) {
296 | recyclerView.removeOnChildAttachStateChangeListener(onChildAttachListener);
297 | onChildAttachListener = null;
298 | }
299 | }
300 |
301 | public final void reset() {
302 | clearHeaderDecoration();
303 | clearOnScrollListener();
304 | clearOnChildAttachListener();
305 | }
306 |
307 | public boolean onInterceptTouchEvent(MotionEvent ev) {
308 | return recyclerView.onInterceptTouchEvent(ev);
309 | }
310 |
311 | public boolean onTouchEvent(MotionEvent ev) {
312 | return recyclerView.onTouchEvent(ev);
313 | }
314 |
315 | }
316 |
317 | private static class LayoutManagerDelegate {
318 | @Nullable
319 | private final LinearLayoutManager linear;
320 | @Nullable
321 | private final GridLayoutManager grid;
322 | @Nullable
323 | private final StaggeredGridLayoutManager staggeredGrid;
324 |
325 | private LayoutManagerDelegate(@NonNull RecyclerView.LayoutManager manager) {
326 | final Class extends RecyclerView.LayoutManager> managerClass = manager.getClass();
327 | if (managerClass == LinearLayoutManager.class) { //not using instanceof on purpose
328 | linear = (LinearLayoutManager) manager;
329 | grid = null;
330 | staggeredGrid = null;
331 | } else if (managerClass == GridLayoutManager.class) {
332 | linear = null;
333 | grid = (GridLayoutManager) manager;
334 | staggeredGrid = null;
335 | // } else if (manager instanceof StaggeredGridLayoutManager) { //TODO: 05.04.2016 implement staggered
336 | // linear = null;
337 | // grid = null;
338 | // staggeredGrid = (StaggeredGridLayoutManager) manager;
339 | } else {
340 | throw new IllegalArgumentException("Currently RecyclerViewHeader supports only LinearLayoutManager and GridLayoutManager.");
341 | }
342 | }
343 |
344 | public static LayoutManagerDelegate with(@NonNull RecyclerView.LayoutManager layoutManager) {
345 | return new LayoutManagerDelegate(layoutManager);
346 | }
347 |
348 | public final int getFirstRowSpan() {
349 | if (linear != null) {
350 | return 1;
351 | } else if (grid != null) {
352 | return grid.getSpanCount();
353 | // } else if (staggeredGrid != null) {
354 | // return staggeredGrid.getSpanCount(); //TODO: 05.04.2016 implement staggered
355 | }
356 | return 0; //shouldn't get here
357 | }
358 |
359 | public final boolean isFirstRowVisible() {
360 | if (linear != null) {
361 | return linear.findFirstVisibleItemPosition() == 0;
362 | } else if (grid != null) {
363 | return grid.findFirstVisibleItemPosition() == 0;
364 | // } else if (staggeredGrid != null) {
365 | // return staggeredGrid.findFirstCompletelyVisibleItemPositions() //TODO: 05.04.2016 implement staggered
366 | }
367 | return false; //shouldn't get here
368 | }
369 |
370 | public final boolean isReversed() {
371 | if (linear != null) {
372 | return linear.getReverseLayout();
373 | } else if (grid != null) {
374 | return grid.getReverseLayout();
375 | // } else if (staggeredGrid != null) {
376 | // return ; //TODO: 05.04.2016 implement staggered
377 | }
378 | return false; //shouldn't get here
379 | }
380 |
381 | public final boolean isVertical() {
382 | if (linear != null) {
383 | return linear.getOrientation() == LinearLayoutManager.VERTICAL;
384 | } else if (grid != null) {
385 | return grid.getOrientation() == LinearLayoutManager.VERTICAL;
386 | // } else if (staggeredGrid != null) {
387 | // return ; //TODO: 05.04.2016 implement staggered
388 | }
389 | return false; //shouldn't get here
390 | }
391 | }
392 |
393 | @IntDef({VISIBLE, INVISIBLE, GONE})
394 | @Retention(RetentionPolicy.SOURCE)
395 | private @interface Visibility {
396 | }
397 |
398 | }
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/java/org/itheima/recycler/listener/ItemClickSupport.java:
--------------------------------------------------------------------------------
1 | package org.itheima.recycler.listener;
2 |
3 | import android.support.v7.widget.RecyclerView;
4 | import android.view.View;
5 |
6 | import org.itheima.recycler.R;
7 |
8 | /**
9 | * Created by mwqi on 2017/2/25.
10 | */
11 |
12 | public class ItemClickSupport {
13 | private final RecyclerView mRecyclerView;
14 | private OnItemClickListener mOnItemClickListener;
15 | private OnItemLongClickListener mOnItemLongClickListener;
16 | private View.OnClickListener mOnClickListener = new View.OnClickListener() {
17 | @Override
18 | public void onClick(View v) {
19 | if (mOnItemClickListener != null) {
20 | RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
21 | mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);
22 | }
23 | }
24 | };
25 | private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() {
26 | @Override
27 | public boolean onLongClick(View v) {
28 | if (mOnItemLongClickListener != null) {
29 | RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
30 | return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v);
31 | }
32 | return false;
33 | }
34 | };
35 | private RecyclerView.OnChildAttachStateChangeListener mAttachListener
36 | = new RecyclerView.OnChildAttachStateChangeListener() {
37 | @Override
38 | public void onChildViewAttachedToWindow(View view) {
39 | if (mOnItemClickListener != null) {
40 | view.setOnClickListener(mOnClickListener);
41 | }
42 | if (mOnItemLongClickListener != null) {
43 | view.setOnLongClickListener(mOnLongClickListener);
44 | }
45 | }
46 |
47 | @Override
48 | public void onChildViewDetachedFromWindow(View view) {
49 |
50 | }
51 | };
52 |
53 | public ItemClickSupport(RecyclerView recyclerView) {
54 | mRecyclerView = recyclerView;
55 | mRecyclerView.setTag(R.id.item_click_support, this);
56 | mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);
57 | }
58 |
59 | public static ItemClickSupport addTo(RecyclerView view) {
60 | ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
61 | if (support == null) {
62 | support = new ItemClickSupport(view);
63 | }
64 | return support;
65 | }
66 |
67 | public static ItemClickSupport removeFrom(RecyclerView view) {
68 | ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
69 | if (support != null) {
70 | support.detach(view);
71 | }
72 | return support;
73 | }
74 |
75 | public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
76 | mOnItemClickListener = listener;
77 | return this;
78 | }
79 |
80 | public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
81 | mOnItemLongClickListener = listener;
82 | return this;
83 | }
84 |
85 | private void detach(RecyclerView view) {
86 | view.removeOnChildAttachStateChangeListener(mAttachListener);
87 | view.setTag(R.id.item_click_support, null);
88 | }
89 |
90 | public interface OnItemClickListener {
91 |
92 | void onItemClicked(RecyclerView recyclerView, int position, View v);
93 | }
94 |
95 | public interface OnItemLongClickListener {
96 |
97 | boolean onItemLongClicked(RecyclerView recyclerView, int position, View v);
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/java/org/itheima/recycler/listener/PullToMoreListener.java:
--------------------------------------------------------------------------------
1 | package org.itheima.recycler.listener;
2 |
3 | import android.support.v4.widget.SwipeRefreshLayout;
4 |
5 | import org.itheima.recycler.adapter.BaseLoadMoreRecyclerAdapter;
6 |
7 | /**
8 | * Created by lyl on 2016/10/7.
9 | */
10 |
11 | public abstract class PullToMoreListener implements SwipeRefreshLayout.OnRefreshListener {
12 | /**
13 | * 加载更多
14 | */
15 | public abstract void onRefreshLoadMore(BaseLoadMoreRecyclerAdapter.LoadMoreViewHolder holder);
16 |
17 | public void onRefresh() {
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/java/org/itheima/recycler/viewholder/BaseRecyclerViewHolder.java:
--------------------------------------------------------------------------------
1 | package org.itheima.recycler.viewholder;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import butterknife.ButterKnife;
10 |
11 |
12 | /**
13 | * Created by lyl on 2016/10/3.
14 | */
15 |
16 | public abstract class BaseRecyclerViewHolder extends RecyclerView.ViewHolder {
17 | protected Context mContext;
18 | protected int mPosition;
19 | protected T mData;
20 |
21 | public BaseRecyclerViewHolder(View itemView) {
22 | super(itemView);
23 | ButterKnife.bind(this, itemView);
24 | mContext = itemView.getContext().getApplicationContext();
25 | }
26 |
27 | public BaseRecyclerViewHolder(ViewGroup parentView, int itemResId) {
28 | this(LayoutInflater.from(parentView.getContext()).inflate(itemResId, parentView, false));
29 | }
30 |
31 | public final void onBindData(int position, T t) {
32 | this.mPosition = position;
33 | this.mData = t;
34 | onBindRealData();
35 | }
36 |
37 | protected abstract void onBindRealData();
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/java/org/itheima/recycler/widget/BaseSwipeRefreshHeaderRecyclerView.java:
--------------------------------------------------------------------------------
1 | package org.itheima.recycler.widget;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.support.annotation.AttrRes;
6 | import android.support.annotation.NonNull;
7 | import android.support.annotation.Nullable;
8 | import android.support.v4.widget.SwipeRefreshLayout;
9 | import android.util.AttributeSet;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 |
13 | import org.itheima.recycler.R;
14 |
15 | /**
16 | * Created by lyl on 2016/11/20.
17 | */
18 |
19 | public class BaseSwipeRefreshHeaderRecyclerView extends SwipeRefreshLayout {
20 | protected View mHeaderView;
21 | protected int mSpanCount;
22 | protected RecyclerViewHeader mRecyclerViewHeader;
23 | protected ItheimaRecyclerView mItheimaRecyclerView;
24 |
25 | public BaseSwipeRefreshHeaderRecyclerView(Context context) {
26 | this(context, null);
27 | }
28 |
29 | public BaseSwipeRefreshHeaderRecyclerView(Context context, AttributeSet attrs) {
30 | super(context, attrs);
31 | initAttr(context, attrs, 0);
32 | initView();
33 |
34 | }
35 |
36 | private void initAttr(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
37 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.itheima_recyclerView, defStyleAttr, 0);
38 | if (typedArray != null) {
39 | mSpanCount = typedArray.getInt(R.styleable.itheima_recyclerView_spanCount, 0);
40 | typedArray.recycle();
41 | }
42 |
43 | }
44 |
45 | private void initView() {
46 | mHeaderView = getChildAt(0);
47 | removeView(mHeaderView);
48 | addView(LayoutInflater.from(getContext()).inflate(R.layout.itheima_header_recyclerview_layout, this, false));
49 | mRecyclerViewHeader = (RecyclerViewHeader) findViewById(R.id.itheima_recycerview_header);
50 | mItheimaRecyclerView = (ItheimaRecyclerView) findViewById(R.id.itheima_recyclerview);
51 | mRecyclerViewHeader.addView(mHeaderView);
52 |
53 | setSpanCount(mSpanCount);
54 | mRecyclerViewHeader.attachTo(mItheimaRecyclerView);
55 | }
56 |
57 |
58 | public void setSpanCount(int spanCount) {
59 | mItheimaRecyclerView.setSpanCount(spanCount);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/java/org/itheima/recycler/widget/ItheimaHeaderRecyclerView.java:
--------------------------------------------------------------------------------
1 | package org.itheima.recycler.widget;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.support.annotation.AttrRes;
6 | import android.support.annotation.NonNull;
7 | import android.support.annotation.Nullable;
8 | import android.util.AttributeSet;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.widget.FrameLayout;
12 |
13 | import org.itheima.recycler.R;
14 | import org.itheima.recycler.adapter.BaseRecyclerAdapter;
15 |
16 | /**
17 | * Created by lyl on 2016/11/20.
18 | */
19 |
20 | public class ItheimaHeaderRecyclerView extends FrameLayout {
21 |
22 | private RecyclerViewHeader mRecyclerViewHeader;
23 | private ItheimaRecyclerView mItheimaRecyclerView;
24 | private int mSpanCount;
25 |
26 | private View mHeaderView;
27 |
28 | public ItheimaHeaderRecyclerView(@NonNull Context context) {
29 | this(context, null, 0);
30 | }
31 |
32 | public ItheimaHeaderRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
33 | this(context, attrs, 0);
34 | }
35 |
36 | public ItheimaHeaderRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
37 | super(context, attrs, defStyleAttr);
38 | initAttr(context, attrs, defStyleAttr);
39 | initView();
40 | }
41 |
42 | private void initAttr(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
43 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.itheima_recyclerView, defStyleAttr, 0);
44 | if (typedArray != null) {
45 | mSpanCount = typedArray.getInt(R.styleable.itheima_recyclerView_spanCount, 0);
46 | typedArray.recycle();
47 | }
48 |
49 | }
50 |
51 |
52 | private void initView() {
53 | post(new Runnable() {
54 | @Override
55 | public void run() {
56 | mHeaderView = getChildAt(0);
57 | removeView(mHeaderView);
58 |
59 | View contentView = LayoutInflater.from(getContext()).inflate(R.layout.itheima_header_recyclerview_layout, ItheimaHeaderRecyclerView.this, false);
60 | mRecyclerViewHeader = (RecyclerViewHeader) contentView.findViewById(R.id.itheima_recycerview_header);
61 | mItheimaRecyclerView = (ItheimaRecyclerView) contentView.findViewById(R.id.itheima_recyclerview);
62 | mRecyclerViewHeader.addView(mHeaderView);
63 | addView(contentView);
64 |
65 | setSpanCount(mSpanCount);
66 | mRecyclerViewHeader.attachTo(mItheimaRecyclerView);
67 | }
68 | });
69 |
70 | }
71 |
72 | public void setSpanCount(int spanCount) {
73 | mItheimaRecyclerView.setSpanCount(spanCount);
74 | }
75 |
76 | public void setAdapter(BaseRecyclerAdapter adapter) {
77 | mItheimaRecyclerView.setAdapter(adapter);
78 |
79 | }
80 |
81 | public ItheimaRecyclerView getRecycerView() {
82 | return mItheimaRecyclerView;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/java/org/itheima/recycler/widget/ItheimaRecyclerView.java:
--------------------------------------------------------------------------------
1 | package org.itheima.recycler.widget;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.support.annotation.Nullable;
6 | import android.support.v7.widget.GridLayoutManager;
7 | import android.support.v7.widget.LinearLayoutManager;
8 | import android.support.v7.widget.RecyclerView;
9 | import android.util.AttributeSet;
10 |
11 | import org.itheima.recycler.R;
12 |
13 | /**
14 | * Created by lyl on 2016/10/3.
15 | */
16 |
17 | public class ItheimaRecyclerView extends RecyclerView {
18 | /**
19 | * 0:LinearLayoutManager.VERTICAL(默认)
20 | * 1:LinearLayoutManager.HORIZONTAL
21 | * [2,9]:
22 | */
23 | private int mSpanCount;
24 |
25 | public ItheimaRecyclerView(Context context) {
26 | this(context, null);
27 | }
28 |
29 | public ItheimaRecyclerView(Context context, @Nullable AttributeSet attrs) {
30 | this(context, attrs, 0);
31 | }
32 |
33 | public ItheimaRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
34 | super(context, attrs, defStyle);
35 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.itheima_recyclerView, defStyle, 0);
36 | if (typedArray != null) {
37 | mSpanCount = typedArray.getInt(R.styleable.itheima_recyclerView_spanCount, 0);
38 | typedArray.recycle();
39 | }
40 | setSpanCount(mSpanCount);
41 | }
42 |
43 | public void setSpanCount(int spanCount) {
44 | mSpanCount = spanCount;
45 | setLayoutManagerType();
46 | }
47 |
48 | public int getSpanCount() {
49 | return mSpanCount;
50 | }
51 |
52 | private void setLayoutManagerType() {
53 | LayoutManager layoutManager = null;
54 | if (getSpanCount() == 0) {
55 | layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
56 | } else if (getSpanCount() == 1) {//1
57 | layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
58 | } else if (getSpanCount() <= 10) {//[2,10]
59 | layoutManager = new GridLayoutManager(getContext(), getSpanCount());
60 | } else if (getSpanCount() > 10) {// >10 横向GridLayout,第二位代表行
61 | layoutManager = new GridLayoutManager(getContext(), getSpanCount() % 10, GridLayoutManager.HORIZONTAL, false);
62 | }
63 | setLayoutManager(layoutManager);
64 |
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/java/org/itheima/recycler/widget/PullToLoadMoreRecyclerView.java:
--------------------------------------------------------------------------------
1 | package org.itheima.recycler.widget;
2 |
3 | import android.support.v4.widget.SwipeRefreshLayout;
4 |
5 | import com.itheima.retrofitutils.ItheimaHttp;
6 | import com.itheima.retrofitutils.Request;
7 | import com.itheima.retrofitutils.listener.HttpResponseListener;
8 |
9 | import org.itheima.recycler.R;
10 | import org.itheima.recycler.adapter.BaseLoadMoreRecyclerAdapter;
11 | import org.itheima.recycler.bean.BasePageBean;
12 | import org.itheima.recycler.listener.PullToMoreListener;
13 | import org.itheima.recycler.viewholder.BaseRecyclerViewHolder;
14 |
15 | import java.util.HashMap;
16 | import java.util.Map;
17 |
18 | import okhttp3.Headers;
19 | import okhttp3.ResponseBody;
20 | import retrofit2.Call;
21 |
22 | /**
23 | * Created by lyl on 2016/10/7.
24 | */
25 |
26 | public abstract class PullToLoadMoreRecyclerView extends PullToMoreListener {
27 |
28 | private SwipeRefreshLayout mSwipeRefreshLayout;
29 | private ItheimaRecyclerView mRecyclerView;
30 | private Class extends BaseRecyclerViewHolder> mViewHolderClazz;
31 | /**
32 | * 扩展字段
33 | */
34 | public Object mMextendObject;
35 |
36 | private LoadingDataListener mLoadingDataListener;
37 |
38 | public PullToLoadMoreRecyclerView(SwipeRefreshLayout swipeRefreshLayout, ItheimaRecyclerView recyclerView, Class extends BaseRecyclerViewHolder> viewHolderClazz) {
39 | mSwipeRefreshLayout = swipeRefreshLayout;
40 | mRecyclerView = recyclerView;
41 | mViewHolderClazz = viewHolderClazz;
42 | initView();
43 | initData();
44 | }
45 |
46 | private void initView() {
47 | if (mSwipeRefreshLayout != null) {
48 | mSwipeRefreshLayout.setColorSchemeResources(getSwipeColorSchemeResources());
49 | mSwipeRefreshLayout.setOnRefreshListener(this);
50 | }
51 | }
52 |
53 | public void setSpanCount(int spanCount) {
54 | mRecyclerView.setSpanCount(spanCount);
55 | }
56 |
57 |
58 | protected void initData() {
59 | mLoadMoreRecyclerViewAdapter = new BaseLoadMoreRecyclerAdapter(mRecyclerView, mViewHolderClazz, getItemResId(), null);
60 | mLoadMoreRecyclerViewAdapter.setPullAndMoreListener(this);
61 | }
62 |
63 |
64 | public int mCurPage = 1;
65 | public int mPageSize = 20;
66 |
67 | public int mTotalPage = 0;
68 |
69 | public Call mCall;
70 |
71 |
72 | public String mCurPageKey = "curPage";
73 | public String mPageSizeKey = "pageSize";
74 |
75 | public BaseLoadMoreRecyclerAdapter mLoadMoreRecyclerViewAdapter;
76 |
77 | public abstract int getItemResId();
78 |
79 | public abstract String getApi();
80 |
81 | public int[] getSwipeColorSchemeResources() {
82 | return new int[]{R.color.colorPrimary};
83 | }
84 |
85 | Map mParamMap = new HashMap<>();
86 | Map mHeaderMap = new HashMap<>();
87 |
88 | public Map putParam(String key, Object value) {
89 | mParamMap.put(key, value);
90 | return mParamMap;
91 | }
92 |
93 | public Map putHeader(String key, Object value) {
94 | mHeaderMap.put(key, value);
95 | return mHeaderMap;
96 | }
97 |
98 |
99 | @Override
100 | public void onRefresh() {
101 | if (mLoadingDataListener != null) {
102 | mLoadingDataListener.onRefresh();
103 | }
104 | requestData();
105 | }
106 |
107 | @Override
108 | public void onRefreshLoadMore(BaseLoadMoreRecyclerAdapter.LoadMoreViewHolder holder) {
109 | if (isMoreData(holder)) {
110 | holder.loading(null);
111 | requestData(true);
112 | } else {
113 | holder.loadingFinish(null);
114 | pullLoadFinish();
115 | }
116 | }
117 |
118 |
119 | public void requestData() {
120 | mCurPage = 1;
121 | requestData(false);
122 | }
123 |
124 | /**
125 | * 是否有更多数据(可以更具自己的分页条件重写)
126 | */
127 | public boolean isMoreData(BaseLoadMoreRecyclerAdapter.LoadMoreViewHolder holder) {
128 | return mCurPage <= mTotalPage;
129 | }
130 |
131 |
132 | private void requestData(final boolean isLoadMore) {
133 | if (mLoadingDataListener != null) {
134 | mLoadingDataListener.onStart();
135 | }
136 | mParamMap.put(mCurPageKey, mCurPage);
137 | mParamMap.put(mPageSizeKey, mPageSize);
138 | Request request = ItheimaHttp.newGetRequest(getApi());
139 | request.putParamsMap(mParamMap);
140 |
141 | if (mHeaderMap != null && mHeaderMap.size() > 0) {
142 | request.putHeaderMap(mHeaderMap);
143 | }
144 | mCall = ItheimaHttp.send(request, new HttpResponseListener() {
145 | @Override
146 | public void onResponse(HttpResponseBean responseBean, Headers headers) {
147 | mTotalPage = responseBean.getTotalPage();
148 | mCurPage++;
149 | mLoadMoreRecyclerViewAdapter.addDatas(isLoadMore, responseBean.getItemDatas());
150 | pullLoadFinish();
151 | /* if (mHttpResponseCall != null) {
152 | mHttpResponseCall.onResponse(responseBean);
153 | }*/
154 |
155 | if (mLoadingDataListener != null) {
156 | mLoadingDataListener.onSuccess(responseBean, headers);
157 | }
158 | }
159 |
160 | @Override
161 | public void onFailure(Call call, Throwable e) {
162 | super.onFailure(call, e);
163 | pullLoadFinish();
164 | /*if (mHttpResponseCall != null) {
165 | mHttpResponseCall.onFailure(call, e);
166 | }*/
167 | if (mLoadingDataListener != null) {
168 | mLoadingDataListener.onFailure();
169 | }
170 |
171 | }
172 |
173 |
174 | @Override
175 | public Class getClazz() {
176 | return PullToLoadMoreRecyclerView.this.getClass();
177 | }
178 | });
179 |
180 | }
181 |
182 | //private HttpResponseListener mHttpResponseCall;
183 |
184 | /*public void setHttpResponseListener(HttpResponseListener call) {
185 | mHttpResponseCall = call;
186 | }*/
187 |
188 | public void pullLoadFinish() {
189 | if (mSwipeRefreshLayout != null) {
190 | mSwipeRefreshLayout.setRefreshing(false);
191 | }
192 | }
193 |
194 | public void free() {
195 | mRecyclerView = null;
196 | if (mSwipeRefreshLayout != null) {
197 | mSwipeRefreshLayout.setRefreshing(false);
198 | mSwipeRefreshLayout = null;
199 |
200 | }
201 | if (mCall != null) {
202 | mCall.cancel();
203 | mCall = null;
204 | }
205 |
206 | if (mLoadMoreRecyclerViewAdapter != null) {
207 | mLoadMoreRecyclerViewAdapter.setPullAndMoreListener(null);
208 | mLoadMoreRecyclerViewAdapter = null;
209 | }
210 |
211 | //mHttpResponseCall = null;
212 | mLoadingDataListener = null;
213 | }
214 | /*|||||||||||||||||||||||||||||||||||||||||||||||||||||*/
215 |
216 | public void setCurPage(int curPage) {
217 | mCurPage = curPage;
218 | }
219 |
220 | public void setPageSize(int pageSize) {
221 | mPageSize = pageSize;
222 | }
223 |
224 | public void setTotalPage(int totalPage) {
225 | mTotalPage = totalPage;
226 | }
227 |
228 | public void setCurPageKey(String curPageKey) {
229 | mCurPageKey = curPageKey;
230 | }
231 |
232 | public void setPageSizeKey(String pageSizeKey) {
233 | mPageSizeKey = pageSizeKey;
234 | }
235 |
236 | /*///////////////////////////////////////////////////*/
237 | public void setLoadingDataListener(LoadingDataListener loadingDataListener) {
238 | mLoadingDataListener = loadingDataListener;
239 | }
240 |
241 | /**
242 | * 监听下啦刷新 & 上啦加载更多
243 | */
244 | public static abstract class LoadingDataListener {
245 | /**
246 | * 下啦刷新回调
247 | */
248 | public void onRefresh() {
249 |
250 | }
251 |
252 | /**
253 | * http请求开始
254 | */
255 | public void onStart() {
256 | }
257 |
258 | /**
259 | * http请求数据成功
260 | *
261 | * @param t
262 | */
263 | public void onSuccess(T t, Headers headers) {
264 | }
265 |
266 | public void onFailure() {
267 |
268 | }
269 | }
270 | }
271 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/java/org/itheima/recycler/widget/RecyclerViewHeader.java:
--------------------------------------------------------------------------------
1 | package org.itheima.recycler.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.Rect;
5 | import android.support.annotation.CallSuper;
6 | import android.support.annotation.IntDef;
7 | import android.support.annotation.NonNull;
8 | import android.support.annotation.Nullable;
9 | import android.support.v7.widget.GridLayoutManager;
10 | import android.support.v7.widget.LinearLayoutManager;
11 | import android.support.v7.widget.RecyclerView;
12 | import android.support.v7.widget.StaggeredGridLayoutManager;
13 | import android.util.AttributeSet;
14 | import android.view.MotionEvent;
15 | import android.view.View;
16 | import android.widget.RelativeLayout;
17 |
18 | import java.lang.annotation.Retention;
19 | import java.lang.annotation.RetentionPolicy;
20 |
21 | public class RecyclerViewHeader extends RelativeLayout {
22 |
23 | @Visibility
24 | private int intendedVisibility = VISIBLE;
25 | private int downTranslation;
26 | private boolean hidden = false;
27 | private boolean recyclerWantsTouch;
28 | private boolean isVertical;
29 | private boolean isAttachedToRecycler;
30 | private RecyclerViewDelegate recyclerView;
31 | private LayoutManagerDelegate layoutManager;
32 |
33 | public RecyclerViewHeader(Context context) {
34 | super(context);
35 | }
36 |
37 | public RecyclerViewHeader(Context context, AttributeSet attrs) {
38 | super(context, attrs);
39 | }
40 |
41 | public RecyclerViewHeader(Context context, AttributeSet attrs, int defStyle) {
42 | super(context, attrs, defStyle);
43 | }
44 |
45 | /**
46 | * Attaches RecyclerViewHeader
to RecyclerView
.
47 | * Be sure that setLayoutManager(...)
has been called for RecyclerView
before calling this method.
48 | *
49 | * @param recycler RecyclerView
to attach RecyclerViewHeader
to.
50 | */
51 | public final void attachTo(@NonNull final RecyclerView recycler) {
52 | validate(recycler);
53 | this.recyclerView = RecyclerViewDelegate.with(recycler);
54 | this.layoutManager = LayoutManagerDelegate.with(recycler.getLayoutManager());
55 | isVertical = layoutManager.isVertical();
56 | isAttachedToRecycler = true;
57 | recyclerView.setHeaderDecoration(new HeaderItemDecoration());
58 | recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
59 | @Override
60 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
61 | onScrollChanged();
62 | }
63 | });
64 | recyclerView.setOnChildAttachListener(new RecyclerView.OnChildAttachStateChangeListener() {
65 | @Override
66 | public void onChildViewAttachedToWindow(View view) {
67 | }
68 |
69 | @Override
70 | public void onChildViewDetachedFromWindow(View view) {
71 | recycler.post(new Runnable() {
72 | @Override
73 | public void run() {
74 | recyclerView.invalidateItemDecorations();
75 | onScrollChanged();
76 | }
77 | });
78 | }
79 | });
80 | }
81 |
82 | /**
83 | * Detaches RecyclerViewHeader
from RecyclerView
.
84 | */
85 | public final void detach() {
86 | if (isAttachedToRecycler) {
87 | isAttachedToRecycler = false;
88 | recyclerWantsTouch = false;
89 | recyclerView.reset();
90 | recyclerView = null;
91 | layoutManager = null;
92 | }
93 | }
94 |
95 | private void onScrollChanged() {
96 | hidden = recyclerView.hasItems() && !layoutManager.isFirstRowVisible();
97 | RecyclerViewHeader.super.setVisibility(hidden ? INVISIBLE : intendedVisibility);
98 | if (!hidden) {
99 | final int translation = calculateTranslation();
100 | if (isVertical) {
101 | setTranslationY(translation);
102 | } else {
103 | setTranslationX(translation);
104 | }
105 | }
106 | }
107 |
108 | private int calculateTranslation() {
109 | int offset = recyclerView.getScrollOffset(isVertical);
110 | int base = layoutManager.isReversed() ? recyclerView.getTranslationBase(isVertical) : 0;
111 | return base - offset;
112 | }
113 |
114 | @Override
115 | public final void setVisibility(@Visibility int visibility) {
116 | this.intendedVisibility = visibility;
117 | if (!hidden) {
118 | super.setVisibility(intendedVisibility);
119 | }
120 | }
121 |
122 | @Visibility
123 | @Override
124 | public final int getVisibility() {
125 | return intendedVisibility;
126 | }
127 |
128 | @Override
129 | protected final void onLayout(boolean changed, int l, int t, int r, int b) {
130 | super.onLayout(changed, l, t, r, b);
131 | if (changed && isAttachedToRecycler) {
132 | int verticalMargins = 0;
133 | int horizontalMargins = 0;
134 | if (getLayoutParams() instanceof MarginLayoutParams) {
135 | final MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();
136 | verticalMargins = layoutParams.topMargin + layoutParams.bottomMargin;
137 | horizontalMargins = layoutParams.leftMargin + layoutParams.rightMargin;
138 | }
139 | recyclerView.onHeaderSizeChanged(getHeight() + verticalMargins, getWidth() + horizontalMargins);
140 | onScrollChanged();
141 | }
142 | }
143 |
144 | @Override
145 | @CallSuper
146 | public boolean onInterceptTouchEvent(MotionEvent ev) {
147 | recyclerWantsTouch = isAttachedToRecycler && recyclerView.onInterceptTouchEvent(ev);
148 | if (recyclerWantsTouch && ev.getAction() == MotionEvent.ACTION_MOVE) {
149 | downTranslation = calculateTranslation();
150 | }
151 | return recyclerWantsTouch || super.onInterceptTouchEvent(ev);
152 | }
153 |
154 | @Override
155 | @CallSuper
156 | public boolean onTouchEvent(@NonNull MotionEvent event) {
157 | if (recyclerWantsTouch) { // this cannot be true if recycler is not attached
158 | int scrollDiff = downTranslation - calculateTranslation();
159 | int verticalDiff = isVertical ? scrollDiff : 0;
160 | int horizontalDiff = isVertical ? 0 : scrollDiff;
161 | MotionEvent recyclerEvent =
162 | MotionEvent.obtain(event.getDownTime(),
163 | event.getEventTime(),
164 | event.getAction(),
165 | event.getX() - horizontalDiff,
166 | event.getY() - verticalDiff,
167 | event.getMetaState());
168 | recyclerView.onTouchEvent(recyclerEvent);
169 | return false;
170 | }
171 | return super.onTouchEvent(event);
172 | }
173 |
174 | private void validate(RecyclerView recyclerView) {
175 | if (recyclerView.getLayoutManager() == null) {
176 | throw new IllegalStateException("Be sure to attach RecyclerViewHeader after setting your RecyclerView's LayoutManager.");
177 | }
178 | }
179 |
180 | private class HeaderItemDecoration extends RecyclerView.ItemDecoration {
181 | private int headerHeight;
182 | private int headerWidth;
183 | private int firstRowSpan;
184 |
185 | public HeaderItemDecoration() {
186 | firstRowSpan = layoutManager.getFirstRowSpan();
187 | }
188 |
189 | public void setWidth(int width) {
190 | headerWidth = width;
191 | }
192 |
193 | public void setHeight(int height) {
194 | headerHeight = height;
195 | }
196 |
197 | @Override
198 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
199 | super.getItemOffsets(outRect, view, parent, state);
200 | final boolean headerRelatedPosition = parent.getChildLayoutPosition(view) < firstRowSpan;
201 | int heightOffset = headerRelatedPosition && isVertical ? headerHeight : 0;
202 | int widthOffset = headerRelatedPosition && !isVertical ? headerWidth : 0;
203 | if (layoutManager.isReversed()) {
204 | outRect.bottom = heightOffset;
205 | outRect.right = widthOffset;
206 | } else {
207 | outRect.top = heightOffset;
208 | outRect.left = widthOffset;
209 | }
210 | }
211 | }
212 |
213 | private static class RecyclerViewDelegate {
214 |
215 | @NonNull
216 | private final RecyclerView recyclerView;
217 | private HeaderItemDecoration decoration;
218 | private RecyclerView.OnScrollListener onScrollListener;
219 | private RecyclerView.OnChildAttachStateChangeListener onChildAttachListener;
220 |
221 | private RecyclerViewDelegate(final @NonNull RecyclerView recyclerView) {
222 | this.recyclerView = recyclerView;
223 | }
224 |
225 | public static RecyclerViewDelegate with(@NonNull RecyclerView recyclerView) {
226 | return new RecyclerViewDelegate(recyclerView);
227 | }
228 |
229 | public final void onHeaderSizeChanged(int height, int width) {
230 | if (decoration != null) {
231 | decoration.setHeight(height);
232 | decoration.setWidth(width);
233 | recyclerView.post(new Runnable() {
234 | @Override
235 | public void run() {
236 | invalidateItemDecorations();
237 | }
238 | });
239 | }
240 | }
241 |
242 | private void invalidateItemDecorations() {
243 | if (!recyclerView.isComputingLayout()) {
244 | recyclerView.invalidateItemDecorations();
245 | }
246 | }
247 |
248 | public final int getScrollOffset(boolean isVertical) {
249 | return isVertical ? recyclerView.computeVerticalScrollOffset() : recyclerView.computeHorizontalScrollOffset();
250 | }
251 |
252 | public final int getTranslationBase(boolean isVertical) {
253 | return isVertical ?
254 | recyclerView.computeVerticalScrollRange() - recyclerView.getHeight() :
255 | recyclerView.computeHorizontalScrollRange() - recyclerView.getWidth();
256 | }
257 |
258 | public final boolean hasItems() {
259 | return recyclerView.getAdapter() != null && recyclerView.getAdapter().getItemCount() != 0;
260 | }
261 |
262 | public final void setHeaderDecoration(HeaderItemDecoration decoration) {
263 | clearHeaderDecoration();
264 | this.decoration = decoration;
265 | recyclerView.addItemDecoration(this.decoration, 0);
266 | }
267 |
268 | public final void clearHeaderDecoration() {
269 | if (decoration != null) {
270 | recyclerView.removeItemDecoration(decoration);
271 | decoration = null;
272 | }
273 | }
274 |
275 | public final void setOnScrollListener(RecyclerView.OnScrollListener onScrollListener) {
276 | clearOnScrollListener();
277 | this.onScrollListener = onScrollListener;
278 | recyclerView.addOnScrollListener(this.onScrollListener);
279 | }
280 |
281 | public final void clearOnScrollListener() {
282 | if (onScrollListener != null) {
283 | recyclerView.removeOnScrollListener(onScrollListener);
284 | onScrollListener = null;
285 | }
286 | }
287 |
288 | public final void setOnChildAttachListener(RecyclerView.OnChildAttachStateChangeListener onChildAttachListener) {
289 | clearOnChildAttachListener();
290 | this.onChildAttachListener = onChildAttachListener;
291 | recyclerView.addOnChildAttachStateChangeListener(this.onChildAttachListener);
292 | }
293 |
294 | public final void clearOnChildAttachListener() {
295 | if (onChildAttachListener != null) {
296 | recyclerView.removeOnChildAttachStateChangeListener(onChildAttachListener);
297 | onChildAttachListener = null;
298 | }
299 | }
300 |
301 | public final void reset() {
302 | clearHeaderDecoration();
303 | clearOnScrollListener();
304 | clearOnChildAttachListener();
305 | }
306 |
307 | public boolean onInterceptTouchEvent(MotionEvent ev) {
308 | return recyclerView.onInterceptTouchEvent(ev);
309 | }
310 |
311 | public boolean onTouchEvent(MotionEvent ev) {
312 | return recyclerView.onTouchEvent(ev);
313 | }
314 |
315 | }
316 |
317 | private static class LayoutManagerDelegate {
318 | @Nullable
319 | private final LinearLayoutManager linear;
320 | @Nullable
321 | private final GridLayoutManager grid;
322 | @Nullable
323 | private final StaggeredGridLayoutManager staggeredGrid;
324 |
325 | private LayoutManagerDelegate(@NonNull RecyclerView.LayoutManager manager) {
326 | final Class extends RecyclerView.LayoutManager> managerClass = manager.getClass();
327 | if (managerClass == LinearLayoutManager.class) { //not using instanceof on purpose
328 | linear = (LinearLayoutManager) manager;
329 | grid = null;
330 | staggeredGrid = null;
331 | } else if (managerClass == GridLayoutManager.class) {
332 | linear = null;
333 | grid = (GridLayoutManager) manager;
334 | staggeredGrid = null;
335 | // } else if (manager instanceof StaggeredGridLayoutManager) { //TODO: 05.04.2016 implement staggered
336 | // linear = null;
337 | // grid = null;
338 | // staggeredGrid = (StaggeredGridLayoutManager) manager;
339 | } else {
340 | throw new IllegalArgumentException("Currently RecyclerViewHeader supports only LinearLayoutManager and GridLayoutManager.");
341 | }
342 | }
343 |
344 | public static LayoutManagerDelegate with(@NonNull RecyclerView.LayoutManager layoutManager) {
345 | return new LayoutManagerDelegate(layoutManager);
346 | }
347 |
348 | public final int getFirstRowSpan() {
349 | if (linear != null) {
350 | return 1;
351 | } else if (grid != null) {
352 | return grid.getSpanCount();
353 | // } else if (staggeredGrid != null) {
354 | // return staggeredGrid.getSpanCount(); //TODO: 05.04.2016 implement staggered
355 | }
356 | return 0; //shouldn't get here
357 | }
358 |
359 | public final boolean isFirstRowVisible() {
360 | if (linear != null) {
361 | return linear.findFirstVisibleItemPosition() == 0;
362 | } else if (grid != null) {
363 | return grid.findFirstVisibleItemPosition() == 0;
364 | // } else if (staggeredGrid != null) {
365 | // return staggeredGrid.findFirstCompletelyVisibleItemPositions() //TODO: 05.04.2016 implement staggered
366 | }
367 | return false; //shouldn't get here
368 | }
369 |
370 | public final boolean isReversed() {
371 | if (linear != null) {
372 | return linear.getReverseLayout();
373 | } else if (grid != null) {
374 | return grid.getReverseLayout();
375 | // } else if (staggeredGrid != null) {
376 | // return ; //TODO: 05.04.2016 implement staggered
377 | }
378 | return false; //shouldn't get here
379 | }
380 |
381 | public final boolean isVertical() {
382 | if (linear != null) {
383 | return linear.getOrientation() == LinearLayoutManager.VERTICAL;
384 | } else if (grid != null) {
385 | return grid.getOrientation() == LinearLayoutManager.VERTICAL;
386 | // } else if (staggeredGrid != null) {
387 | // return ; //TODO: 05.04.2016 implement staggered
388 | }
389 | return false; //shouldn't get here
390 | }
391 | }
392 |
393 | @IntDef({VISIBLE, INVISIBLE, GONE})
394 | @Retention(RetentionPolicy.SOURCE)
395 | private @interface Visibility {
396 | }
397 |
398 | }
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/java/org/itheima/recycler/widget/SwipeRefreshHeaderRecyclerView.java:
--------------------------------------------------------------------------------
1 | package org.itheima.recycler.widget;
2 |
3 | import android.content.Context;
4 | import android.support.v4.widget.SwipeRefreshLayout;
5 | import android.util.AttributeSet;
6 |
7 | import com.google.gson.annotations.SerializedName;
8 | import com.itheima.retrofitutils.ItheimaHttp;
9 | import com.itheima.retrofitutils.Request;
10 | import com.itheima.retrofitutils.RequestMethod;
11 | import com.itheima.retrofitutils.listener.HttpResponseListener;
12 |
13 | import org.itheima.recycler.L;
14 | import org.itheima.recycler.R;
15 | import org.itheima.recycler.adapter.BaseRecyclerAdapter;
16 | import org.itheima.recycler.bean.BasePageBean;
17 | import org.itheima.recycler.bean.SwipeRefreshBean;
18 |
19 | import java.lang.reflect.Field;
20 | import java.util.HashMap;
21 | import java.util.Map;
22 |
23 | import okhttp3.Headers;
24 | import okhttp3.ResponseBody;
25 | import retrofit2.Call;
26 |
27 | /**
28 | * Created by lyl on 2016/11/20.
29 | */
30 |
31 | public class SwipeRefreshHeaderRecyclerView extends BaseSwipeRefreshHeaderRecyclerView implements SwipeRefreshLayout.OnRefreshListener {
32 |
33 | private SwipeRefreshBean mSwipeRefreshBean;
34 |
35 | public int mCurPage = 1;
36 | public int mPageSize = 20;
37 | public int mTotalPage = 0;
38 | public String mCurPageKey = "currentPage";
39 | public String mPageSizeKey = "pageSize";
40 | public String mTotalPageKey = "totalPage";
41 |
42 | private RequestMethod mRequestMethod;
43 |
44 | public Call mCall;
45 |
46 | private BaseRecyclerAdapter mBaseRecyclerAdapter;
47 |
48 | private SwipeLoadingDataListener mSwipeLoadingDataListener;
49 |
50 |
51 | public SwipeRefreshHeaderRecyclerView(Context context) {
52 | this(context, null);
53 | }
54 |
55 | public SwipeRefreshHeaderRecyclerView(Context context, AttributeSet attrs) {
56 | super(context, attrs);
57 | setColorSchemeResources(R.color.colorPrimary);
58 | setOnRefreshListener(this);
59 | }
60 |
61 | @Override
62 | public void onRefresh() {
63 | if (mSwipeLoadingDataListener != null) {
64 | mSwipeLoadingDataListener.onRefresh();
65 | }
66 | mCurPage = 1;
67 | mParamMap.put(mCurPageKey, mCurPage);
68 | requestData(false, mRequestMethod, mParamMap);
69 | }
70 |
71 | private Map mParamMap = new HashMap();
72 |
73 | public void requestData(RequestMethod method, Map paramMap) {
74 | requestData(false, method, paramMap);
75 |
76 | }
77 |
78 | public void requestData(final boolean isLoadMore, RequestMethod method, Map paramMap) {
79 | if (mSwipeLoadingDataListener != null) {
80 | mSwipeLoadingDataListener.onStart();
81 | }
82 | mRequestMethod = method;
83 | if (paramMap != null) {
84 | mParamMap.putAll(paramMap);
85 | }
86 | Request request = null;
87 | if (RequestMethod.GET.equals(method)) {
88 | request = ItheimaHttp.newGetRequest(mSwipeRefreshBean.apiUrl);
89 | } else {
90 | request = ItheimaHttp.newPostRequest(mSwipeRefreshBean.apiUrl);
91 | }
92 | request.putParamsMap(mParamMap);
93 | mCall = ItheimaHttp.send(request, new HttpResponseListener() {
94 | @Override
95 | public void onResponse(BasePageBean responseBean, Headers headers) {
96 | if (mSwipeLoadingDataListener != null) {
97 | mSwipeLoadingDataListener.onSuccess(responseBean, headers);
98 | }
99 | mTotalPage = responseBean.totalPage;
100 | mCurPage++;
101 | mBaseRecyclerAdapter.addDatas(isLoadMore, responseBean.getItemDatas());
102 | }
103 |
104 | @Override
105 | public void onFailure(Call call, Throwable e) {
106 | super.onFailure(call, e);
107 |
108 | if (mSwipeLoadingDataListener != null) {
109 | mSwipeLoadingDataListener.onFailure();
110 | }
111 |
112 | }
113 |
114 |
115 | @Override
116 | public Class getClazz() {
117 | return mSwipeRefreshBean.httpResponseBeanClazz;
118 | }
119 | });
120 |
121 |
122 | }
123 |
124 |
125 | /* public void prepareData(SwipeRefreshBean swipeRefreshBean) {
126 | mSwipeRefreshBean = swipeRefreshBean;
127 | try {
128 | //反射获取有关于分页数据的值
129 | Field pageSizeField = mSwipeRefreshBean.httpResponseBeanClazz.getField("pageSize");
130 | Field currentPageField = mSwipeRefreshBean.httpResponseBeanClazz.getField("currentPage");
131 | Field totalPageField = mSwipeRefreshBean.httpResponseBeanClazz.getField("totalPage");
132 |
133 | mPageSize = pageSizeField.getInt(20);
134 | mCurPage = currentPageField.getInt(1);
135 | //mTotalPage = totalPageField.getInt(0);
136 |
137 | SerializedName pageSizeAnnotation = pageSizeField.getAnnotation(SerializedName.class);
138 | SerializedName currentPageAnnotation = currentPageField.getAnnotation(SerializedName.class);
139 | SerializedName totalPageAnnotation = totalPageField.getAnnotation(SerializedName.class);
140 | if (pageSizeAnnotation != null) {
141 | mPageSizeKey = pageSizeAnnotation.value();
142 | }
143 | if (currentPageAnnotation != null) {
144 | mCurPageKey = currentPageAnnotation.value();
145 | }
146 | if (totalPageAnnotation != null) {
147 | mTotalPageKey = currentPageAnnotation.value();
148 | }
149 |
150 | } catch (Exception e) {
151 | L.e(e);
152 | }
153 |
154 | }*/
155 |
156 |
157 | public void setAdapter(BaseRecyclerAdapter adapter) {
158 | mBaseRecyclerAdapter = adapter;
159 | mItheimaRecyclerView.setAdapter(adapter);
160 | }
161 |
162 | public void setSwipeLoadingDataListener(SwipeLoadingDataListener swipeLoadingDataListener) {
163 | mSwipeLoadingDataListener = swipeLoadingDataListener;
164 | }
165 |
166 | /**
167 | * 监听下啦刷新 & 上啦加载更多
168 | *
169 | * @param
170 | */
171 | public static abstract class SwipeLoadingDataListener {
172 | /**
173 | * 下啦刷新回调
174 | */
175 | public void onRefresh() {
176 |
177 | }
178 |
179 | /**
180 | * http请求开始
181 | */
182 | public void onStart() {
183 | }
184 |
185 | /**
186 | * http请求数据成功
187 | *
188 | * @param t
189 | */
190 | public void onSuccess(T t, Headers headers) {
191 | }
192 |
193 | public void onFailure() {
194 |
195 | }
196 | }
197 |
198 | }
199 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/res/layout/itheima_header_recyclerview_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
17 |
18 |
19 |
24 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/res/layout/itheima_item_loadmore_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/res/values/color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #fff4511e
4 |
5 |
--------------------------------------------------------------------------------
/BaseRecyclerAndAdapter/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | #RecyclerView & RecyclerView.Adapter封装
3 |
4 | 开源项目:[https://github.com/open-android/BaseRecyclerAndAdapter](https://github.com/open-android/BaseRecyclerAndAdapter "地址")
5 |
6 | * 爱生活,爱学习,更爱做代码的搬运工,分类查找更方便请下载黑马助手app
7 |
8 |
9 | 
10 |
11 |
12 | ## 使用步骤
13 | ### 1. 在project的build.gradle添加如下代码(如下图)
14 | ```groovy
15 | allprojects {
16 | repositories {
17 | ...
18 | maven { url "https://jitpack.io" }
19 | }
20 | }
21 | ```
22 | 
23 |
24 | ### 2. 在Module的build.gradle添加依赖
25 | ```groovy
26 | compile 'com.github.open-android:BaseRecyclerAndAdapter:0.5.13'
27 | compile 'com.jakewharton:butterknife:8.4.0'
28 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
29 | ```
30 |
31 | ### 3. 添加权限
32 | ```groovy
33 |
34 |
35 |
36 |
37 | ```
38 | ### ItheimaRecyclerView使用方式
39 |
40 |
41 | * 网格RecyclerView(app:spanCount="2",spanCount取值范围[1,10])
42 |
43 | ```xml
44 |
49 | ```
50 | * 垂直滚动RecyclerView
51 | ```xml
52 |
56 | ```
57 | * 横向滚动RecyclerView(11:一行,12:二行.......,spanCount取值范围[11,19])
58 | ```xml
59 |
64 | ```
65 |
66 | ### ItheimaRecyclerView添加头
67 |
68 | 
69 |
70 | * xml代码
71 | ```xml
72 |
75 |
76 |
80 |
81 |
86 |
87 |
91 |
92 |
93 | ```
94 |
95 | * java代码
96 |
97 | ```java
98 | RecyclerViewHeader header = (RecyclerViewHeader) findViewById(R.id.header);
99 | RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
100 | header.attachTo(recyclerView);
101 | ```
102 |
103 | ### 给RecyclerView的item添加点击事件和长按事件
104 |
105 | ```java
106 | ItemClickSupport itemClickSupport = new ItemClickSupport(mRecyclerView);
107 | //点击事件
108 | itemClickSupport.setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
109 | @Override
110 | public void onItemClicked(RecyclerView recyclerView, int position, View v) {
111 | Toast.makeText(recyclerView.getContext(), "我被点击了", Toast.LENGTH_SHORT).show();
112 | }
113 | });
114 | //长按事件
115 | itemClickSupport.setOnItemLongClickListener(new ItemClickSupport.OnItemLongClickListener() {
116 | @Override
117 | public boolean onItemLongClicked(RecyclerView recyclerView, int position, View v) {
118 | Toast.makeText(recyclerView.getContext(), "我被长按了", Toast.LENGTH_SHORT).show();
119 | return false;
120 | }
121 | });
122 | ```
123 |
124 | ### BaseRecyclerAdapter使用方式
125 |
126 | ```java
127 | adapter = new BaseRecyclerAdapter(recyclerView
128 | , MyRecyclerViewHolder.class
129 | , R.layout.item_reyclerview
130 | , datas);
131 |
132 | //@param recyclerView
133 | //@param viewHolderClazz
134 | //@param itemResId recyclerView条目的资源id
135 | //@param datas recyclerView展示的数据集合(可以传null)
136 | ```
137 |
138 | ### ViewHolder模板(ViewHolder如果是内部类必须加上static和public关键字)
139 |
140 | ```java
141 | public static class MyRecyclerViewHolder extends BaseRecyclerViewHolder {
142 | //换成你布局文件中的id
143 | @BindView(R.id.tv_title)
144 | TextView tvTitle;
145 |
146 | public MyRecyclerViewHolder(ViewGroup parentView, int itemResId) {
147 | super(parentView, itemResId);
148 | }
149 |
150 | /**
151 | * 绑定数据的方法,在mData获取数据(mData声明在基类中)
152 | */
153 | @Override
154 | public void onBindRealData() {
155 | tvTitle.setText(mData.title);
156 | }
157 |
158 |
159 | /**
160 | * 给按钮添加点击事件(button改成你要添加点击事件的id)
161 | * @param v
162 | */
163 | @OnClick(R.id.button)
164 | public void click(View v) {
165 | }
166 | }
167 | ```
168 |
169 | ### 下啦刷新 & 加载更多组合控件(下啦刷新和加载更多内部实现,你只需要在对应的ViewHolder做数据绑定即可)
170 | * http请求初始化
171 | ```java
172 | ItheimaHttp.init(context, baseUrl);//使用前必须调用(如果调用过则不需要重复调用)
173 | ```
174 | * xml布局
175 | ```xml
176 |
180 |
181 |
185 |
186 | ```
187 | * java代码实现布局
188 | ```java
189 | pullToLoadMoreRecyclerView = new PullToLoadMoreRecyclerView(mSwipeRefreshLayout, mRecyclerView, MyRecyclerViewHolder.class) {
190 | @Override
191 | public int getItemResId() {
192 | //recylerview item资源id
193 | return R.layout.item_recylerview;
194 | }
195 |
196 | @Override
197 | public String getApi() {
198 | //接口
199 | return "order/list";
200 | }
201 | //是否加载更多的数据,根据业务逻辑自行判断,true表示有更多的数据,false表示没有更多的数据,如果不需要监听可以不重写该方法
202 | @Override
203 | public boolean isMoreData(BaseLoadMoreRecyclerAdapter.LoadMoreViewHolder holder) {
204 | System.out.println("isMoreData" + holder);
205 |
206 | return true;
207 | }
208 | };
209 | ```
210 |
211 | * 设置监听
212 | ```java
213 | pullToLoadMoreRecyclerView.setLoadingDataListener(new PullToLoadMoreRecyclerView.LoadingDataListener() {
214 |
215 | @Override
216 | public void onRefresh() {
217 | //监听下啦刷新,如果不需要监听可以不重新该方法
218 | L.i("setLoadingDataListener onRefresh");
219 | }
220 |
221 | @Override
222 | public void onStart() {
223 | //监听http请求开始,如果不需要监听可以不重新该方法
224 | L.i("setLoadingDataListener onStart");
225 | }
226 |
227 | @Override
228 | public void onSuccess(Bean o ,,Headers headers) {
229 | //监听http请求成功,如果不需要监听可以不重新该方法
230 | L.i("setLoadingDataListener onSuccess: " + o);
231 | }
232 |
233 | @Override
234 | public void onFailure() {
235 | //监听http请求失败,如果不需要监听可以不重新该方法
236 | L.i("setLoadingDataListener onFailure");
237 | }
238 | });
239 |
240 |
241 | //添加头
242 | pullToLoadMoreRecyclerView.putHeader(key,value);
243 | //添加请求参数
244 | pullToLoadMoreRecyclerView.putParam(key, value);
245 | //开始请求
246 | pullToLoadMoreRecyclerView.requestData();
247 |
248 |
249 | //控制加状态,可以在监听中处理
250 | loadMoreViewHolder.loading("加载中...");//默认文字:"加载中..."
251 | loadMoreViewHolder.loadingFinish("没有更多数据");
252 | ```
253 |
254 | ### 高级用法
255 | ```java
256 | //如果使用数字控制页数可以使用如下api
257 | //设置参数的key
258 | setCurPageKey("curPage");//当前页key
259 | setPageSizeKey("pageSize");//每一页数量的key
260 | //设置参数的值
261 | setPageSize(1);//设置每一页数量
262 | setTotalPage(20);//设置一共有多少页
263 | //如果使用其他方式分页
264 | 可以设置setLoadingDataListener在onSuccess(Bean o)回调中处理分页
265 | onSuccess回调在每一次加载数据成功后回调
266 | ```
267 |
268 |
269 |
270 | ### RecyclerView多条目展示
271 | ```java
272 | class MyTypeAdapter extends BaseRecyclerAdapter {
273 | private final int ITEM_TYPE_1 = 0;
274 | private final int ITEM_TYPE_2 = 1;
275 |
276 | public MyTypeAdapter(RecyclerView recyclerView, List datas) {
277 | super(recyclerView, null, 0, datas);
278 | }
279 |
280 | @Override
281 | public BaseRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
282 | //选择类型
283 | if (viewType == ITEM_TYPE_2) {
284 | return new MyTypeHolder2(parent, R.layout.item_type2);
285 | }
286 | return new MyTypeHolder1(parent, R.layout.item_type1);
287 | }
288 |
289 | @Override
290 | public int getItemViewType(int position) {
291 | //根据position返回类型
292 | return position % 2 == 0 ? ITEM_TYPE_2 : ITEM_TYPE_1;
293 | }
294 | }
295 | ```
296 |
297 | ### 动态向Adapter中添加数据
298 |
299 | ```java
300 | //@param isLoadMore 数据是否累加
301 | //@param datas List数据
302 |
303 | adapter.addDatas(true,datas);
304 | ```
305 | ### 清空Adapter中所以数据(不推荐使用,使用adapter.addDatas(true,datas))可以实现相同的功能
306 |
307 | ```java
308 | adapter.clearAllData();
309 | ```
310 | 详细的使用方法在DEMO里面都演示啦,如果你觉得这个库还不错,请赏我一颗star吧~~~
311 |
312 | 欢迎关注微信公众号
313 |
314 | 
315 |
316 |
317 |
318 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.2.2'
9 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | maven { url "https://jitpack.io" }
19 | }
20 | }
21 |
22 | task clean(type: Delete) {
23 | delete rootProject.buildDir
24 | }
25 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## Project-wide Gradle settings.
2 | #
3 | # For more details on how to configure your build environment visit
4 | # http://www.gradle.org/docs/current/userguide/build_environment.html
5 | #
6 | # Specifies the JVM arguments used for the daemon process.
7 | # The setting is particularly useful for tweaking memory settings.
8 | # Default value: -Xmx1024m -XX:MaxPermSize=256m
9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | #
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 | #Sat Dec 24 09:18:22 CST 2016
16 | systemProp.http.proxyHost=127.0.0.1
17 | org.gradle.jvmargs=-Xmx1536m
18 | systemProp.http.proxyPort=1080
19 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/BaseRecyclerAndAdapter/e44fdcc204de3f36f9829c38cc88149ac3c57aa6/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/img/jitpack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/BaseRecyclerAndAdapter/e44fdcc204de3f36f9829c38cc88149ac3c57aa6/img/jitpack.png
--------------------------------------------------------------------------------
/img/loadMoreAdapter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/BaseRecyclerAndAdapter/e44fdcc204de3f36f9829c38cc88149ac3c57aa6/img/loadMoreAdapter.png
--------------------------------------------------------------------------------
/img/recyclerViewHeader.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/open-android/BaseRecyclerAndAdapter/e44fdcc204de3f36f9829c38cc88149ac3c57aa6/img/recyclerViewHeader.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':BaseRecyclerAndAdapter'
--------------------------------------------------------------------------------