├── .gitignore
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── demo.apk
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── zlc
│ │ └── season
│ │ └── demo
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── zlc
│ │ │ └── season
│ │ │ └── demo
│ │ │ ├── Header.java
│ │ │ ├── RecyclerItemType.java
│ │ │ ├── drag
│ │ │ ├── DragActivity.java
│ │ │ ├── DragAdapter.java
│ │ │ ├── DragBean.java
│ │ │ ├── DragPresenter.java
│ │ │ ├── DragView.java
│ │ │ ├── DragViewHolder.java
│ │ │ └── ItemTouchHelperProvider.java
│ │ │ ├── expand
│ │ │ ├── ChildBean.java
│ │ │ ├── ChildViewHolder.java
│ │ │ ├── ExpandActivity.java
│ │ │ ├── ExpandAdapter.java
│ │ │ ├── ExpandPresenter.java
│ │ │ ├── ExpandView.java
│ │ │ ├── MockResponse.java
│ │ │ ├── ParentBean.java
│ │ │ └── ParentViewHolder.java
│ │ │ ├── grid
│ │ │ ├── GridActivity.java
│ │ │ ├── GridAdapter.java
│ │ │ ├── GridBean.java
│ │ │ ├── GridPresenter.java
│ │ │ ├── GridView.java
│ │ │ └── GridViewHolder.java
│ │ │ ├── main
│ │ │ ├── MainActivity.java
│ │ │ ├── MainAdapter.java
│ │ │ ├── MainPresenter.java
│ │ │ ├── MainView.java
│ │ │ ├── MenuBean.java
│ │ │ └── MenuViewHolder.java
│ │ │ ├── multipleitem
│ │ │ ├── MultiItemActivity.java
│ │ │ ├── MultiItemAdapter.java
│ │ │ ├── MultiItemPresenter.java
│ │ │ ├── MultiItemView.java
│ │ │ ├── TypeOneBean.java
│ │ │ ├── TypeOneViewHolder.java
│ │ │ ├── TypeTwoBean.java
│ │ │ └── TypeTwoViewHolder.java
│ │ │ ├── singleitem
│ │ │ ├── ManualLoadMoreActivity.java
│ │ │ ├── NormalBean.java
│ │ │ ├── NormalViewHolder.java
│ │ │ ├── SingleItemActivity.java
│ │ │ ├── SingleItemAdapter.java
│ │ │ ├── SingleItemPresenter.java
│ │ │ └── SingleItemView.java
│ │ │ └── staggered
│ │ │ ├── StaggerAdapter.java
│ │ │ ├── StaggerBean.java
│ │ │ ├── StaggerPresenter.java
│ │ │ ├── StaggerView.java
│ │ │ ├── StaggerViewHolder.java
│ │ │ └── StaggeredActivity.java
│ └── res
│ │ ├── drawable-v21
│ │ ├── ic_menu_camera.xml
│ │ ├── ic_menu_gallery.xml
│ │ ├── ic_menu_manage.xml
│ │ ├── ic_menu_send.xml
│ │ ├── ic_menu_share.xml
│ │ └── ic_menu_slideshow.xml
│ │ ├── drawable-xhdpi
│ │ ├── ic_keyboard_arrow_down.png
│ │ ├── ic_keyboard_arrow_up.png
│ │ └── ic_reorder.png
│ │ ├── drawable
│ │ └── side_nav_bar.xml
│ │ ├── layout
│ │ ├── activity_drag.xml
│ │ ├── activity_expand.xml
│ │ ├── activity_grid.xml
│ │ ├── activity_main.xml
│ │ ├── activity_manual_load.xml
│ │ ├── activity_multi_item.xml
│ │ ├── activity_single_item.xml
│ │ ├── activity_staggered.xml
│ │ ├── child_item.xml
│ │ ├── content_drag.xml
│ │ ├── content_expand.xml
│ │ ├── content_grid.xml
│ │ ├── content_main.xml
│ │ ├── content_multi_item.xml
│ │ ├── content_staggered.xml
│ │ ├── drag_item.xml
│ │ ├── grid_item.xml
│ │ ├── header_item.xml
│ │ ├── manual_load_layout.xml
│ │ ├── menu_item.xml
│ │ ├── normal_item.xml
│ │ ├── parent_item.xml
│ │ ├── stagger_item.xml
│ │ ├── type_one_item.xml
│ │ └── type_two_item.xml
│ │ ├── menu
│ │ ├── drag_menu.xml
│ │ └── menu.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ ├── a.jpg
│ │ ├── b.jpg
│ │ ├── c.jpg
│ │ ├── d.jpg
│ │ ├── e.jpg
│ │ ├── f.jpg
│ │ ├── g.jpg
│ │ ├── h.jpg
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-v21
│ │ └── styles.xml
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── zlc
│ └── season
│ └── demo
│ └── ExampleUnitTest.java
├── build.gradle
├── gif
├── GIF.gif
├── drag.gif
├── expand.gif
├── grid.gif
├── manual.gif
├── multiitem.gif
└── stagger.gif
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── practicalrecyclerview
├── .gitignore
├── bintray.gradle
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── zlc
│ │ └── season
│ │ └── practicalrecyclerview
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── zlc
│ │ │ └── season
│ │ │ └── practicalrecyclerview
│ │ │ ├── AbstractAdapter.java
│ │ │ ├── AbstractViewHolder.java
│ │ │ ├── Bridge.java
│ │ │ ├── Configure.java
│ │ │ ├── ConfigureAdapter.java
│ │ │ ├── DataSetObservable.java
│ │ │ ├── ItemType.java
│ │ │ ├── PracticalRecyclerView.java
│ │ │ ├── SectionItem.java
│ │ │ ├── SectionItemImpl.java
│ │ │ ├── SimpleItemTouchHelperCallback.java
│ │ │ └── decoration
│ │ │ ├── DividerItemDecoration.java
│ │ │ └── ShadowItemDecoration.java
│ └── res
│ │ ├── layout
│ │ ├── default_empty_layout.xml
│ │ ├── default_error_layout.xml
│ │ ├── default_load_more_failed_layout.xml
│ │ ├── default_load_more_layout.xml
│ │ ├── default_loading_layout.xml
│ │ ├── default_no_more_layout.xml
│ │ └── recycler_layout.xml
│ │ └── values
│ │ ├── attr.xml
│ │ └── strings.xml
│ └── test
│ └── java
│ └── zlc
│ └── season
│ └── practicalrecyclerview
│ ├── ExampleUnitTest.java
│ └── SegmentTest.java
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | .DS_Store
5 | /build
6 | /captures
7 | .idea/
8 | /gradle.properties
9 |
10 |
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PracticalRecyclerView
2 |
3 | Encapsulation RecyclerView, to create for the development of a very practical tool, add some commonly used in the development of function, such as drop-down refresh, paging, automatic loading, loading error, etc.More new functions will gradually add...
4 |
5 | 标签(空格分隔): Android RecyclerView
6 |
7 | ---
8 |
9 | ## 对RecyclerView的一个封装,添加一些实用的功能
10 |
11 | ### 主要功能:
12 |
13 | - 下拉刷新,使用默认的下拉刷新控件
14 | - 页面加载数据过程中显示LoadingView
15 | - 页面加载数据出错时显示ErrorView
16 | - 页面数据大小为0时显示EmptyView
17 | - 自动加载,当页面到底部或者当前页面显示不全时,自动加载其余数据,并显示LoadMoreView
18 | - 加载更多时出错自动停止加载更多,并显示LoadMoreFailedView
19 | - 没有更多数据加载时,显示NoMoreView
20 | - 支持Header View和Footer View
21 | - 除下拉刷新以外,其余View均可自定义
22 | - 支持多种Item类型
23 | - 支持GridLayout和瀑布流
24 |
25 | ### 2016-10-11 更新:
26 |
27 | - 新增动态显示或关闭NoMoreView,LoadMoreView,LoadMoreFailedView功能
28 | - 新增打开或关闭自动加载功能
29 | - 新增手动触发加载demo
30 |
31 | ### 2016-10-17 更新:
32 |
33 | - 增加获取RecyclerView接口
34 |
35 | ```java
36 | public RecyclerView get() {
37 | return mRecyclerView;
38 | }
39 | ```
40 | - 增加拖拽功能与demo
41 |
42 | ### 2016-10-18 更新:
43 |
44 | - 向下支持到API 11(android 3.0)
45 | - AbstractAdapter增加更多操作数据接口, 如:
46 |
47 | ```java
48 | public void clearData() {}
49 |
50 | public void clearHeader() {}
51 |
52 | public void clearFooter() {}
53 |
54 | public void insert(){}
55 |
56 | public void insertBack(){}
57 |
58 | //等等
59 |
60 | ```
61 | - 增加ExpandItemList demo
62 |
63 | ### 2016-11-7 更新:
64 |
65 | - 新增添加单个数据接口 void add(T item);
66 |
67 | ### 2017-1-22 更新
68 |
69 | - 修复需要滑动两次才能显示loadmore的bug.
70 |
71 |
72 | ### 效果图
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | ### 使用方式:
92 |
93 | 1.添加Gradle依赖
94 |
95 | [](https://bintray.com/ssseasonnn/android/PracticalRecyclerView/_latestVersion)
96 |
97 | ```groovy
98 | dependencies{
99 | compile 'zlc.season:practicalrecyclerview:1.1.5'
100 | }
101 | ```
102 | 2.在布局文件中添加PracticalRecyclerView
103 |
104 |
105 | ```xml
106 |
107 |
117 | ```
118 |
119 | 3.添加代码
120 |
121 | 首先定义一个POJO类, 并实现ItemType接口:
122 |
123 | ```java
124 | class NormalBean implements ItemType {
125 | String mImg;
126 | String mTitle;
127 | String mContent;
128 |
129 | NormalBean(String img, String title, String content) {
130 | mImg = img;
131 | mContent = content;
132 | mTitle = title;
133 | }
134 |
135 | @Override
136 | public int itemType() {
137 | return 0;
138 | }
139 | }
140 | ```
141 |
142 | > 这里返回的item type 表示是item的类型, 如果列表只有一种类型的item, 那么返回0就可以了, 如果有多种item, 则对应类型的item返回对应类型的item type. 这里简单的返回0 .
143 |
144 | 接着定义ViewHolder, 继承自AbstractViewHolder, 并提供泛型参数:
145 |
146 | ```java
147 | class NormalViewHolder extends AbstractViewHolder {
148 | @BindView(R.id.head)
149 | ImageView mHead;
150 | @BindView(R.id.title)
151 | TextView mTitle;
152 | @BindView(R.id.content)
153 | TextView mContent;
154 |
155 | private Context mContext;
156 |
157 | NormalViewHolder(ViewGroup parent) {
158 | super(parent, R.layout.normal_item); //与对应的item layout进行绑定.
159 | mContext = parent.getContext(); //如果viewholder需要context,在这里获取.
160 | ButterKnife.bind(this, itemView); //这里使用了butterknife进行控件绑定,也可以手写 // itemView.findViewById()来获取对应的控件.
161 | }
162 |
163 | @Override
164 | public void setData(NormalBean data) {
165 | Picasso.with(mContext).load(Uri.parse(data.mImg)).into(mHead);
166 | mTitle.setText(data.mTitle);
167 | mContent.setText(data.mContent);
168 | }
169 | }
170 | ```
171 |
172 | > 在Viewholder中进行View的创建和绑定, 如果需要绑定按钮的单击事件或者其他的一些事件, 在此处进行再好不过了.
173 |
174 | 接下来创建Adatper, 继承自AbstractAdapter, 并提供泛型参数:
175 |
176 | ```java
177 | class SingleItemAdapter extends AbstractAdapter {
178 |
179 | @Override
180 | protected NormalViewHolder onNewCreateViewHolder(ViewGroup parent, int viewType) {
181 | return new NormalViewHolder(parent);
182 | }
183 |
184 | @Override
185 | protected void onNewBindViewHolder(NormalViewHolder holder, int position) {
186 | holder.setData(get(position));
187 | }
188 | }
189 | ```
190 |
191 | > adapter 类中非常简洁, 只需要在onNewCreateViewHolder()中创建ViewHolder, 在onNewBindViewHolder()中调用viewholder的setData()即可, 这样adapter和viewholder的逻辑就分离开来,互不干扰.
192 |
193 | 最后,在Activity或者Fragment中进行最后的配置:
194 |
195 | ```java
196 | PracticalRecyclerView mRecycler;
197 | private SingleItemAdapter mAdapter = new SingleItemAdapter();
198 | ...
199 | mRecycler.setLayoutManager(new LinearLayoutManager(this));
200 | mRecycler.setAdapterWithLoading(mAdapter);
201 | mRecycler.setRefreshListener(new PracticalRecyclerView.OnRefreshListener() {
202 | @Override
203 | public void onRefresh() {
204 | mPresenter.loadData(true);
205 | }
206 | });
207 | mRecycler.setLoadMoreListener(new PracticalRecyclerView.OnLoadMoreListener() {
208 | @Override
209 | public void onLoadMore() {
210 | mPresenter.loadData(false);
211 | }
212 | });
213 | ...
214 | //更多详细代码请下载demo查看
215 | ```
216 |
217 | 4.添加Header 和 Footer
218 |
219 | 要添加Header和Footer, 可以选择实现SectionItem接口, 或者继承SectionItemImpl, 如下所示:
220 |
221 | ```java
222 | class Header implements SectionItem {
223 | @BindView(R.id.banner_guide_content)
224 | BGABanner mBanner;
225 |
226 | @Override
227 | public View createView(ViewGroup parent) {
228 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.header_item, parent, false);
229 | ButterKnife.bind(this, view);
230 | return view;
231 | }
232 |
233 | @Override
234 | public void onBind() {
235 | mBanner.setAdapter(new BGABanner.Adapter() {
236 | @Override
237 | public void fillBannerItem(BGABanner banner, View view, Object model, int position) {
238 | ((ImageView) view).setImageResource((int) model);
239 | }
240 | });
241 | mBanner.setData(Arrays.asList(R.mipmap.a, R.mipmap.b, R.mipmap.c, R.mipmap.d, R.mipmap.e, R.mipmap.f,
242 | R.mipmap.g, R.mipmap.h), null);
243 | }
244 | }
245 | ```
246 |
247 | > 这里使用了一个开源轮播库BGABanner当作Header, 该库的链接在此: [BGAbanner](https://github.com/bingoogolapple/BGABanner-Android)
248 |
249 | 接着调用Adapter的addHeader() 或者addFooter()方法将该Header或Footer添加到adapter中:
250 |
251 | ```java
252 | mAdapter.addHeader(new Header());
253 | ```
254 |
255 | 5.Configure 接口和ConfigureAdapter类
256 |
257 | 当默认的属性不能满足需求时, 可以自定义layout 并设置为PracticalRecyclerView的属性:
258 |
259 | ```xml
260 | ...
261 | app:load_more_failed_layout="@layout/custom_load_more_failed_layout" //当加载更多失败时显示的View
262 | ...
263 | ```
264 |
265 | 若需要对该View进行设置, 就需要用到Configure接口, Configure接口定义了以下方法,分别对属性中设置的View进行设置:
266 |
267 | ```java
268 | public interface Configure {
269 | void configureEmptyView(View emptyView); //对Empty View 进行设置
270 |
271 | void configureErrorView(View errorView); //对Error View 进行设置
272 |
273 | void configureLoadingView(View loadingView); // 对LoadingView 进行设置
274 |
275 | void configureLoadMoreView(View loadMoreView); // 对LoadMore View进行设置
276 |
277 | void configureNoMoreView(View noMoreView); //对NoMore View进行设置
278 |
279 | void configureLoadMoreErrorView(View loadMoreErrorView); // 对LoadMoreError View进行设置
280 | }
281 | ```
282 |
283 | ConfigureAdapter是对Configure接口的一个包装类, 可以选择实现其中的某一些方法,从而设置对应的View:
284 |
285 | ```java
286 | mRecycler.configureView(new ConfigureAdapter() {
287 | @Override
288 | public void configureLoadMoreFailedView(View loadMoreFailedView) {
289 | super.configureLoadMoreFailedView(loadMoreFailedView);
290 | loadMoreFailedView.setOnClickListener(new View.OnClickListener() {
291 | @Override
292 | public void onClick(View v) {
293 | Toast.makeText(SingleItemActivity.this, "点击LoadMoreFailedView时应该进行的操作", Toast.LENGTH_SHORT).show();
294 | }
295 | });
296 | }
297 |
298 | @Override
299 | public void configureErrorView(View errorView) {
300 | super.configureErrorView(errorView);
301 | errorView.dosomething();
302 | }
303 | });
304 | ```
305 |
306 | 6.更多功能将会继续开发和完善
307 |
308 | 若您对此项目有一些自己的想法 , 欢迎来提Pull Request.
309 |
310 | ### 关于我
311 |
312 | 若您对该项目有疑问,请联系我:
313 |
314 | QQ:270362455
315 |
316 | Gmail: ssseasonnn@gmail.com
317 |
318 |
319 |
320 | ### License
321 |
322 | > ```
323 | > Copyright 2016 Season.Zlc
324 | >
325 | > Licensed under the Apache License, Version 2.0 (the "License");
326 | > you may not use this file except in compliance with the License.
327 | > You may obtain a copy of the License at
328 | >
329 | > http://www.apache.org/licenses/LICENSE-2.0
330 | >
331 | > Unless required by applicable law or agreed to in writing, software
332 | > distributed under the License is distributed on an "AS IS" BASIS,
333 | > WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
334 | > See the License for the specific language governing permissions and
335 | > limitations under the License.
336 | > ```
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'android-apt'
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.2"
6 |
7 | defaultConfig {
8 | applicationId "zlc.season.demo"
9 | minSdkVersion 15
10 | targetSdkVersion 25
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | testCompile 'junit:junit:4.12'
25 | compile 'com.android.support:appcompat-v7:25.1.0'
26 |
27 | compile 'com.android.support:design:25.1.0'
28 | compile 'com.android.support:support-v13:25.1.0'
29 | compile 'com.android.support:cardview-v7:25.1.0'
30 |
31 | compile 'io.reactivex:rxjava:1.2.0'
32 | compile 'io.reactivex:rxandroid:1.2.1'
33 |
34 | compile 'com.squareup.picasso:picasso:2.5.2'
35 |
36 | compile 'com.jakewharton:butterknife:8.4.0'
37 | apt 'com.jakewharton:butterknife-compiler:8.4.0'
38 |
39 | compile 'com.nineoldandroids:library:2.4.0'
40 | compile 'cn.bingoogolapple:bga-banner:2.0.9'
41 |
42 | compile 'com.google.code.gson:gson:2.7'
43 |
44 | compile project(path: ':practicalrecyclerview')
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/demo.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/demo.apk
--------------------------------------------------------------------------------
/app/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:\Application\Android-Sdk/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 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/zlc/season/demo/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
29 |
30 |
34 |
35 |
39 |
40 |
43 |
47 |
48 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/Header.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo;
2 |
3 | import android.view.LayoutInflater;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 | import android.widget.ImageView;
7 |
8 | import java.util.Arrays;
9 |
10 | import butterknife.BindView;
11 | import butterknife.ButterKnife;
12 | import cn.bingoogolapple.bgabanner.BGABanner;
13 | import zlc.season.practicalrecyclerview.SectionItem;
14 |
15 | /**
16 | * Author: Season(ssseasonnn@gmail.com)
17 | * Date: 2016/10/10
18 | * Time: 11:47
19 | * FIXME
20 | */
21 | public class Header implements SectionItem {
22 | @BindView(R.id.banner_guide_content)
23 | BGABanner mBanner;
24 |
25 | @Override
26 | public View createView(ViewGroup parent) {
27 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.header_item, parent, false);
28 | ButterKnife.bind(this, view);
29 | return view;
30 | }
31 |
32 | @Override
33 | public void onBind() {
34 | mBanner.setAdapter(new BGABanner.Adapter() {
35 | @Override
36 | public void fillBannerItem(BGABanner banner, View view, Object model, int position) {
37 | ((ImageView) view).setImageResource((int) model);
38 | }
39 | });
40 | mBanner.setData(Arrays.asList(R.mipmap.a, R.mipmap.b, R.mipmap.c, R.mipmap.d, R.mipmap.e, R.mipmap.f,
41 | R.mipmap.g, R.mipmap.h), null);
42 | }
43 | }
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/RecyclerItemType.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo;
2 |
3 | /**
4 | * Author: Season(ssseasonnn@gmail.com)
5 | * Date: 2016/9/22
6 | * Time: 10:01
7 | * FIXME
8 | */
9 | public enum RecyclerItemType {
10 | NORMAL(0), TYPE1(1), TYPE2(2), TYPE3(3), PARENT(4), CHILD(5);
11 |
12 | // 定义私有变量
13 | private int nCode;
14 |
15 | RecyclerItemType(int _nCode) {
16 | this.nCode = _nCode;
17 | }
18 |
19 | public int getValue() {
20 | return this.nCode;
21 | }
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/drag/DragActivity.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.drag;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.support.v7.widget.GridLayoutManager;
6 | import android.support.v7.widget.LinearLayoutManager;
7 | import android.support.v7.widget.Toolbar;
8 | import android.view.Menu;
9 | import android.view.MenuItem;
10 | import android.widget.RelativeLayout;
11 |
12 | import java.util.List;
13 |
14 | import butterknife.BindView;
15 | import butterknife.ButterKnife;
16 | import zlc.season.demo.Header;
17 | import zlc.season.demo.R;
18 | import zlc.season.practicalrecyclerview.PracticalRecyclerView;
19 | import zlc.season.practicalrecyclerview.SimpleItemTouchHelperCallback;
20 |
21 | public class DragActivity extends AppCompatActivity {
22 |
23 | @BindView(R.id.recycler)
24 | PracticalRecyclerView mRecycler;
25 | @BindView(R.id.toolbar)
26 | Toolbar mToolbar;
27 | @BindView(R.id.content_item_drag)
28 | RelativeLayout mContentItemDrag;
29 |
30 | private boolean flag = false;
31 | private boolean gridChecked = false;
32 |
33 | private DragAdapter mAdapter;
34 | private DragPresenter mPresenter;
35 |
36 |
37 | @Override
38 | public boolean onCreateOptionsMenu(Menu menu) {
39 | // Inflate the menu; this adds items to the action bar if it is present.
40 | getMenuInflater().inflate(R.menu.drag_menu, menu);
41 | return true;
42 | }
43 |
44 | @Override
45 | public boolean onPrepareOptionsMenu(Menu menu) {
46 | MenuItem grid = menu.findItem(R.id.action_grid);
47 | grid.setChecked(gridChecked);
48 | return true;
49 | }
50 |
51 | @Override
52 | public boolean onOptionsItemSelected(MenuItem item) {
53 | // Handle action bar item clicks here. The action bar will
54 | // automatically handle clicks on the Home/Up button, so long
55 | // as you specify a parent activity in AndroidManifest.xml.
56 | int id = item.getItemId();
57 |
58 | switch (id) {
59 | case R.id.action_edit:
60 | flag = !flag;
61 | if (flag) {
62 | item.setTitle("保存");
63 | } else {
64 | item.setTitle("编辑");
65 | }
66 |
67 | //点击编辑显示拖动图标
68 | List copy = mAdapter.getData();
69 | for (DragBean each : copy) {
70 | each.status = !each.status;
71 | }
72 | mAdapter.notifyDataSetChanged();
73 |
74 | return true;
75 |
76 | case R.id.action_grid:
77 | gridChecked = !item.isChecked();
78 | item.setChecked(gridChecked);
79 |
80 | if (gridChecked) {
81 | mRecycler.setLayoutManager(new GridLayoutManager(this, 3));
82 | mRecycler.setAdapter(mAdapter);
83 | } else {
84 | mRecycler.setLayoutManager(new LinearLayoutManager(this));
85 | mRecycler.setAdapter(mAdapter);
86 | }
87 | return true;
88 | }
89 |
90 | return super.onOptionsItemSelected(item);
91 | }
92 |
93 | @Override
94 | protected void onCreate(Bundle savedInstanceState) {
95 | super.onCreate(savedInstanceState);
96 | setContentView(R.layout.activity_drag);
97 | ButterKnife.bind(this);
98 | setSupportActionBar(mToolbar);
99 |
100 | mAdapter = new DragAdapter();
101 | mRecycler.setLayoutManager(new LinearLayoutManager(this));
102 | mRecycler.setAdapterWithLoading(mAdapter);
103 |
104 | mPresenter = new DragPresenter(this);
105 | mPresenter.setDataLoadCallBack(new DragView() {
106 | @Override
107 | public void onDataLoadSuccess(List list) {
108 | mAdapter.addHeader(new Header());
109 | mAdapter.addAll(list);
110 | }
111 |
112 | @Override
113 | public void onDataLoadFailed() {
114 | mAdapter.showError();
115 | }
116 | });
117 |
118 | //初始化拖拽, 设置不启用默认的长按拖拽, 设置不启用默认的滑动删除
119 | //具体的拖拽实现在 ViewHolder 中
120 | ItemTouchHelperProvider.init(new SimpleItemTouchHelperCallback(false, false));
121 | mRecycler.attachItemTouchHelper(ItemTouchHelperProvider.getInstance());
122 | }
123 |
124 | @Override
125 | protected void onDestroy() {
126 | super.onDestroy();
127 | mPresenter.unsubscribeAll();
128 | }
129 |
130 | @Override
131 | protected void onResume() {
132 | super.onResume();
133 | mPresenter.loadData();
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/drag/DragAdapter.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.drag;
2 |
3 | import android.view.ViewGroup;
4 |
5 | import zlc.season.practicalrecyclerview.AbstractAdapter;
6 |
7 | /**
8 | * Author: Season(ssseasonnn@gmail.com)
9 | * Date: 2016/10/12
10 | * Time: 11:45
11 | * FIXME
12 | */
13 | class DragAdapter extends AbstractAdapter {
14 | @Override
15 | protected DragViewHolder onNewCreateViewHolder(ViewGroup parent, int viewType) {
16 | return new DragViewHolder(parent);
17 | }
18 |
19 | @Override
20 | protected void onNewBindViewHolder(DragViewHolder holder, int position) {
21 | holder.setData(get(position));
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/drag/DragBean.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.drag;
2 |
3 | import zlc.season.practicalrecyclerview.ItemType;
4 |
5 | /**
6 | * Author: Season(ssseasonnn@gmail.com)
7 | * Date: 2016/10/12
8 | * Time: 11:42
9 | * FIXME
10 | */
11 | class DragBean implements ItemType {
12 | String text;
13 | boolean status = false;
14 |
15 | DragBean(String text) {
16 | this.text = text;
17 | }
18 |
19 | @Override
20 | public int itemType() {
21 | return 0;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/drag/DragPresenter.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.drag;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 | import java.util.concurrent.TimeUnit;
9 |
10 | import rx.Observable;
11 | import rx.Observer;
12 | import rx.Subscriber;
13 | import rx.Subscription;
14 | import rx.android.schedulers.AndroidSchedulers;
15 | import rx.schedulers.Schedulers;
16 | import rx.subscriptions.CompositeSubscription;
17 |
18 | /**
19 | * Author: Season(ssseasonnn@gmail.com)
20 | * Date: 2016/10/12
21 | * Time: 11:46
22 | * FIXME
23 | */
24 | class DragPresenter {
25 |
26 | private CompositeSubscription mSubscriptions;
27 | private DragView mView;
28 | private Context mContext;
29 |
30 | DragPresenter(Context context) {
31 | mContext = context;
32 | mSubscriptions = new CompositeSubscription();
33 | }
34 |
35 | void setDataLoadCallBack(DragView view) {
36 | mView = view;
37 | }
38 |
39 | void unsubscribeAll() {
40 | mSubscriptions.clear();
41 | }
42 |
43 | void loadData() {
44 | Subscription subscription = createObservable()
45 | .subscribeOn(Schedulers.io())
46 | .delay(2, TimeUnit.SECONDS)
47 | .observeOn(AndroidSchedulers.mainThread())
48 | .subscribe(new Observer>() {
49 | @Override
50 | public void onCompleted() {
51 |
52 | }
53 |
54 | @Override
55 | public void onError(Throwable e) {
56 | Log.w("SingleItemPresenter", e);
57 | mView.onDataLoadFailed();
58 | }
59 |
60 | @Override
61 | public void onNext(List list) {
62 | mView.onDataLoadSuccess(list);
63 | }
64 | });
65 | mSubscriptions.add(subscription);
66 | }
67 |
68 | private Observable> createObservable() {
69 | return Observable.create(new Observable.OnSubscribe>() {
70 | @Override
71 | public void call(Subscriber super List> subscriber) {
72 | List mData = new ArrayList<>();
73 | for (int i = 0; i < 5; i++) {
74 | DragBean bean = new DragBean(i + "");
75 | mData.add(bean);
76 | }
77 | subscriber.onNext(mData);
78 | subscriber.onCompleted();
79 | }
80 | });
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/drag/DragView.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.drag;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Author: Season(ssseasonnn@gmail.com)
7 | * Date: 2016/10/12
8 | * Time: 11:45
9 | * FIXME
10 | */
11 | interface DragView {
12 | void onDataLoadSuccess(List list);
13 |
14 | void onDataLoadFailed();
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/drag/DragViewHolder.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.drag;
2 |
3 | import android.content.Context;
4 | import android.view.MotionEvent;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.ImageView;
8 | import android.widget.TextView;
9 | import android.widget.Toast;
10 |
11 | import butterknife.BindView;
12 | import butterknife.ButterKnife;
13 | import butterknife.OnClick;
14 | import zlc.season.demo.R;
15 | import zlc.season.practicalrecyclerview.AbstractViewHolder;
16 |
17 | /**
18 | * Author: Season(ssseasonnn@gmail.com)
19 | * Date: 2016/10/12
20 | * Time: 11:43
21 | * FIXME
22 | */
23 | class DragViewHolder extends AbstractViewHolder {
24 | @BindView(R.id.text)
25 | TextView mText;
26 | @BindView(R.id.reorder)
27 | ImageView mReorder;
28 | private Context mContext;
29 |
30 | DragViewHolder(ViewGroup parent) {
31 | super(parent, R.layout.drag_item);
32 | ButterKnife.bind(this, itemView);
33 | mContext = parent.getContext();
34 |
35 | //触摸拖拽
36 | mReorder.setOnTouchListener(new View.OnTouchListener() {
37 | @Override
38 | public boolean onTouch(View v, MotionEvent event) {
39 | ItemTouchHelperProvider.getInstance().startDrag(DragViewHolder.this);
40 | return true;
41 | }
42 | });
43 |
44 | //长按拖拽
45 | // mText.setOnLongClickListener(new View.OnLongClickListener() {
46 | // @Override
47 | // public boolean onLongClick(View v) {
48 | // ItemTouchHelperProvider.getInstance().startDrag(DragViewHolder.this);
49 | // return true;
50 | // }
51 | // });
52 | }
53 |
54 | @Override
55 | public void setData(DragBean data) {
56 | mText.setText(data.text);
57 | if (data.status) {
58 | mReorder.setVisibility(View.VISIBLE);
59 | } else {
60 | mReorder.setVisibility(View.GONE);
61 | }
62 | }
63 |
64 | @OnClick(R.id.text)
65 | public void onClick() {
66 | Toast.makeText(mContext, mText.getText().toString(), Toast.LENGTH_SHORT).show();
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/drag/ItemTouchHelperProvider.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.drag;
2 |
3 | import android.support.v7.widget.helper.ItemTouchHelper;
4 |
5 | /**
6 | * Author: Season(ssseasonnn@gmail.com)
7 | * Date: 2016/10/17
8 | * Time: 10:08
9 | * FIXME
10 | */
11 | class ItemTouchHelperProvider {
12 | private static ItemTouchHelper ourInstance;
13 |
14 | private ItemTouchHelperProvider() {
15 | }
16 |
17 | static ItemTouchHelper getInstance() {
18 | if (ourInstance == null) {
19 | throw new IllegalStateException("you should call init first");
20 | }
21 | return ourInstance;
22 | }
23 |
24 | static void init(ItemTouchHelper.Callback callback) {
25 | ourInstance = new ItemTouchHelper(callback);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/expand/ChildBean.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.expand;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | import zlc.season.demo.RecyclerItemType;
6 | import zlc.season.practicalrecyclerview.ItemType;
7 |
8 | /**
9 | * Author: Season(ssseasonnn@gmail.com)
10 | * Date: 2016/10/17
11 | * Time: 15:29
12 | * FIXME
13 | */
14 | class ChildBean implements ItemType {
15 | @SerializedName("text")
16 | int text;
17 |
18 | @Override
19 | public int itemType() {
20 | return RecyclerItemType.CHILD.getValue();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/expand/ChildViewHolder.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.expand;
2 |
3 | import android.content.Context;
4 | import android.view.ViewGroup;
5 | import android.widget.TextView;
6 | import android.widget.Toast;
7 |
8 | import butterknife.BindView;
9 | import butterknife.ButterKnife;
10 | import butterknife.OnClick;
11 | import zlc.season.demo.R;
12 | import zlc.season.practicalrecyclerview.AbstractViewHolder;
13 |
14 | /**
15 | * Author: Season(ssseasonnn@gmail.com)
16 | * Date: 2016/10/17
17 | * Time: 15:31
18 | * FIXME
19 | */
20 | class ChildViewHolder extends AbstractViewHolder {
21 | @BindView(R.id.text)
22 | TextView mText;
23 |
24 | private Context mContext;
25 |
26 | ChildViewHolder(ViewGroup parent) {
27 | super(parent, R.layout.child_item);
28 | ButterKnife.bind(this, itemView);
29 | mContext = parent.getContext();
30 | }
31 |
32 | @Override
33 | public void setData(ChildBean data) {
34 | mText.setText(String.valueOf(data.text));
35 | }
36 |
37 | @OnClick(R.id.text)
38 | public void onClick() {
39 | Toast.makeText(mContext, "i am child view", Toast.LENGTH_SHORT).show();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/expand/ExpandActivity.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.expand;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.support.v7.widget.LinearLayoutManager;
6 | import android.support.v7.widget.Toolbar;
7 |
8 | import java.util.List;
9 |
10 | import butterknife.BindView;
11 | import butterknife.ButterKnife;
12 | import zlc.season.demo.R;
13 | import zlc.season.practicalrecyclerview.PracticalRecyclerView;
14 |
15 | public class ExpandActivity extends AppCompatActivity {
16 |
17 | @BindView(R.id.toolbar)
18 | Toolbar mToolbar;
19 | @BindView(R.id.recycler)
20 | PracticalRecyclerView mRecycler;
21 |
22 | private ExpandAdapter mAdapter;
23 | private ExpandPresenter mPresenter;
24 |
25 | @Override
26 | protected void onCreate(Bundle savedInstanceState) {
27 | super.onCreate(savedInstanceState);
28 | setContentView(R.layout.activity_expand);
29 | ButterKnife.bind(this);
30 | setSupportActionBar(mToolbar);
31 | mAdapter = new ExpandAdapter();
32 | mRecycler.setLayoutManager(new LinearLayoutManager(this));
33 | mRecycler.setAdapterWithLoading(mAdapter);
34 |
35 | mRecycler.setRefreshListener(new PracticalRecyclerView.OnRefreshListener() {
36 | @Override
37 | public void onRefresh() {
38 | mPresenter.loadData();
39 | }
40 | });
41 |
42 | mPresenter = new ExpandPresenter(this);
43 | mPresenter.setDataLoadCallBack(new ExpandView() {
44 | @Override
45 | public void onDataLoadSuccess(List list) {
46 | mAdapter.clear();
47 | // mAdapter.addHeader(new Header());
48 | // mAdapter.addFooter(new Header());
49 | mAdapter.addAll(list);
50 | }
51 |
52 | @Override
53 | public void onDataLoadFailed() {
54 | }
55 | });
56 | }
57 |
58 | @Override
59 | protected void onDestroy() {
60 | super.onDestroy();
61 | mPresenter.unsubscribeAll();
62 | }
63 |
64 | @Override
65 | protected void onResume() {
66 | super.onResume();
67 | mPresenter.loadData();
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/expand/ExpandAdapter.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.expand;
2 |
3 | import android.view.ViewGroup;
4 |
5 | import zlc.season.demo.RecyclerItemType;
6 | import zlc.season.practicalrecyclerview.AbstractAdapter;
7 | import zlc.season.practicalrecyclerview.AbstractViewHolder;
8 | import zlc.season.practicalrecyclerview.ItemType;
9 |
10 | /**
11 | * Author: Season(ssseasonnn@gmail.com)
12 | * Date: 2016/10/17
13 | * Time: 15:31
14 | * FIXME
15 | */
16 | class ExpandAdapter extends AbstractAdapter {
17 | @Override
18 | protected AbstractViewHolder onNewCreateViewHolder(ViewGroup parent, int viewType) {
19 | if (viewType == RecyclerItemType.PARENT.getValue()) {
20 | return new ParentViewHolder(this, parent);
21 | } else if (viewType == RecyclerItemType.CHILD.getValue()) {
22 | return new ChildViewHolder(parent);
23 | }
24 | return null;
25 | }
26 |
27 | @Override
28 | protected void onNewBindViewHolder(AbstractViewHolder holder, int position) {
29 | if (holder instanceof ParentViewHolder) {
30 | ((ParentViewHolder) holder).setData((ParentBean) get(position));
31 | } else if (holder instanceof ChildViewHolder) {
32 | ((ChildViewHolder) holder).setData((ChildBean) get(position));
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/expand/ExpandPresenter.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.expand;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 | import android.util.Log;
6 |
7 | import com.google.gson.Gson;
8 |
9 | import java.util.List;
10 | import java.util.concurrent.TimeUnit;
11 |
12 | import rx.Observable;
13 | import rx.Observer;
14 | import rx.Subscriber;
15 | import rx.Subscription;
16 | import rx.android.schedulers.AndroidSchedulers;
17 | import rx.schedulers.Schedulers;
18 | import rx.subscriptions.CompositeSubscription;
19 | import zlc.season.demo.R;
20 |
21 | /**
22 | * Author: Season(ssseasonnn@gmail.com)
23 | * Date: 2016/10/10
24 | * Time: 11:42
25 | * FIXME
26 | */
27 | class ExpandPresenter {
28 | private CompositeSubscription mSubscriptions;
29 | private ExpandView mView;
30 | private Context mContext;
31 |
32 | ExpandPresenter(Context context) {
33 | mContext = context;
34 | mSubscriptions = new CompositeSubscription();
35 | }
36 |
37 | void setDataLoadCallBack(ExpandView gridView) {
38 | mView = gridView;
39 | }
40 |
41 | void unsubscribeAll() {
42 | mSubscriptions.clear();
43 | }
44 |
45 | void loadData() {
46 | Subscription subscription = createObservable()
47 | .subscribeOn(Schedulers.io())
48 | .delay(2, TimeUnit.SECONDS)
49 | .observeOn(AndroidSchedulers.mainThread())
50 | .subscribe(new Observer() {
51 | @Override
52 | public void onCompleted() {
53 |
54 | }
55 |
56 | @Override
57 | public void onError(Throwable e) {
58 | Log.w("SingleItemPresenter", e);
59 | mView.onDataLoadFailed();
60 | }
61 |
62 | @Override
63 | public void onNext(MockResponse response) {
64 | List parent = response.mData;
65 | mView.onDataLoadSuccess(parent);
66 | }
67 | });
68 | mSubscriptions.add(subscription);
69 | }
70 |
71 | private Observable createObservable() {
72 | return Observable.create(new Observable.OnSubscribe() {
73 | @Override
74 | public void call(Subscriber super MockResponse> subscriber) {
75 | Resources res = mContext.getResources();
76 | final String mockResponse = res.getString(R.string.mock_response);
77 | MockResponse response = new Gson().fromJson(mockResponse, MockResponse.class);
78 | subscriber.onNext(response);
79 | subscriber.onCompleted();
80 | }
81 | });
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/expand/ExpandView.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.expand;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Author: Season(ssseasonnn@gmail.com)
7 | * Date: 2016/10/10
8 | * Time: 11:42
9 | * FIXME
10 | */
11 | interface ExpandView {
12 | void onDataLoadSuccess(List list);
13 |
14 | void onDataLoadFailed();
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/expand/MockResponse.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.expand;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * Author: Season(ssseasonnn@gmail.com)
9 | * Date: 2016/10/17
10 | * Time: 16:02
11 | * FIXME
12 | */
13 | class MockResponse {
14 |
15 | /**
16 | * text : 0
17 | * child : [{"text":0},{"text":1},{"text":2},{"text":3}]
18 | */
19 |
20 | @SerializedName("data")
21 | public List mData;
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/expand/ParentBean.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.expand;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | import java.util.List;
6 |
7 | import zlc.season.demo.RecyclerItemType;
8 | import zlc.season.practicalrecyclerview.ItemType;
9 |
10 | /**
11 | * Author: Season(ssseasonnn@gmail.com)
12 | * Date: 2016/10/17
13 | * Time: 15:28
14 | * FIXME
15 | */
16 | class ParentBean implements ItemType {
17 |
18 | @SerializedName("text")
19 | int text;
20 |
21 | @SerializedName("child")
22 | List mChild;
23 |
24 | /**
25 | * 是否展开
26 | */
27 | boolean isExpand;
28 |
29 | @Override
30 | public int itemType() {
31 | return RecyclerItemType.PARENT.getValue();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/expand/ParentViewHolder.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.expand;
2 |
3 | import android.content.Context;
4 | import android.view.ViewGroup;
5 | import android.widget.ImageView;
6 | import android.widget.TextView;
7 |
8 | import com.squareup.picasso.Picasso;
9 |
10 | import java.util.List;
11 |
12 | import butterknife.BindView;
13 | import butterknife.ButterKnife;
14 | import butterknife.OnClick;
15 | import zlc.season.demo.R;
16 | import zlc.season.practicalrecyclerview.AbstractAdapter;
17 | import zlc.season.practicalrecyclerview.AbstractViewHolder;
18 |
19 | /**
20 | * Author: Season(ssseasonnn@gmail.com)
21 | * Date: 2016/10/17
22 | * Time: 15:30
23 | * FIXME
24 | */
25 | class ParentViewHolder extends AbstractViewHolder {
26 |
27 | @BindView(R.id.text)
28 | TextView mText;
29 | @BindView(R.id.image)
30 | ImageView mImageView;
31 |
32 | private ParentBean parent;
33 | private List child;
34 |
35 | private Context mContext;
36 | private ExpandAdapter mAdapter;
37 |
38 | ParentViewHolder(AbstractAdapter adapter, ViewGroup parent) {
39 | super(parent, R.layout.parent_item);
40 | ButterKnife.bind(this, itemView);
41 | mContext = parent.getContext();
42 | mAdapter = (ExpandAdapter) adapter;
43 | }
44 |
45 | @Override
46 | public void setData(ParentBean data) {
47 | mText.setText(String.valueOf(data.text));
48 | child = data.mChild;
49 | parent = data;
50 | }
51 |
52 | @OnClick(R.id.text)
53 | public void onClick() {
54 | if (parent.isExpand) {
55 | mAdapter.removeBack(getAdapterPosition(), child.size());
56 | parent.isExpand = false;
57 | Picasso.with(mContext).load(R.drawable.ic_keyboard_arrow_down).into(mImageView);
58 | } else {
59 | mAdapter.insertAllBack(getAdapterPosition(), child);
60 | parent.isExpand = true;
61 | Picasso.with(mContext).load(R.drawable.ic_keyboard_arrow_up).into(mImageView);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/grid/GridActivity.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.grid;
2 |
3 | import android.os.Bundle;
4 | import android.support.design.widget.FloatingActionButton;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.support.v7.widget.GridLayoutManager;
7 | import android.support.v7.widget.Toolbar;
8 | import android.widget.RelativeLayout;
9 |
10 | import java.util.List;
11 |
12 | import butterknife.BindView;
13 | import butterknife.ButterKnife;
14 | import zlc.season.demo.Header;
15 | import zlc.season.demo.R;
16 | import zlc.season.practicalrecyclerview.PracticalRecyclerView;
17 |
18 | public class GridActivity extends AppCompatActivity {
19 |
20 | @BindView(R.id.toolbar)
21 | Toolbar mToolbar;
22 | @BindView(R.id.recycler)
23 | PracticalRecyclerView mRecycler;
24 | @BindView(R.id.content_grid)
25 | RelativeLayout mContentGrid;
26 | @BindView(R.id.fab)
27 | FloatingActionButton mFab;
28 |
29 | private GridAdapter mAdapter;
30 |
31 | private GridPresenter mPresenter;
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 | setContentView(R.layout.activity_grid);
37 | ButterKnife.bind(this);
38 | setSupportActionBar(mToolbar);
39 |
40 | mAdapter = new GridAdapter();
41 | mRecycler.setLayoutManager(new GridLayoutManager(this, 3));
42 | mRecycler.setAdapterWithLoading(mAdapter);
43 |
44 | mRecycler.setRefreshListener(new PracticalRecyclerView.OnRefreshListener() {
45 | @Override
46 | public void onRefresh() {
47 | mPresenter.loadData(true);
48 | }
49 | });
50 |
51 | mRecycler.setLoadMoreListener(new PracticalRecyclerView.OnLoadMoreListener() {
52 | @Override
53 | public void onLoadMore() {
54 | mPresenter.loadData(false);
55 | }
56 | });
57 |
58 | mPresenter = new GridPresenter(this);
59 | mPresenter.setDataLoadCallBack(new GridView() {
60 | @Override
61 | public void onDataLoadSuccess(List list, boolean isRefresh) {
62 | if (isRefresh) {
63 | mAdapter.clear();
64 | mAdapter.addHeader(new Header());
65 | // mAdapter.addFooter(new Header());
66 | mAdapter.addAll(list);
67 | } else {
68 | mAdapter.addAll(list);
69 | }
70 | }
71 |
72 | @Override
73 | public void onDataLoadFailed(boolean isRefresh) {
74 | if (isRefresh) {
75 | mAdapter.showError();
76 | } else {
77 | mAdapter.loadMoreFailed();
78 | }
79 | }
80 | });
81 | }
82 |
83 | @Override
84 | protected void onDestroy() {
85 | super.onDestroy();
86 | mPresenter.unsubscribeAll();
87 | }
88 |
89 | @Override
90 | protected void onResume() {
91 | super.onResume();
92 | mPresenter.loadData(true);
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/grid/GridAdapter.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.grid;
2 |
3 | import android.view.ViewGroup;
4 |
5 | import zlc.season.practicalrecyclerview.AbstractAdapter;
6 |
7 | /**
8 | * Author: Season(ssseasonnn@gmail.com)
9 | * Date: 2016/10/10
10 | * Time: 10:25
11 | * FIXME
12 | */
13 | public class GridAdapter extends AbstractAdapter {
14 | @Override
15 | protected GridViewHolder onNewCreateViewHolder(ViewGroup parent, int viewType) {
16 | return new GridViewHolder(parent);
17 | }
18 |
19 | @Override
20 | protected void onNewBindViewHolder(GridViewHolder holder, int position) {
21 | holder.setData(get(position));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/grid/GridBean.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.grid;
2 |
3 | import zlc.season.practicalrecyclerview.ItemType;
4 |
5 | /**
6 | * Author: Season(ssseasonnn@gmail.com)
7 | * Date: 2016/10/10
8 | * Time: 10:15
9 | * FIXME
10 | */
11 | public class GridBean implements ItemType {
12 | String text;
13 |
14 | public GridBean(String text) {
15 | this.text = text;
16 | }
17 |
18 | @Override
19 | public int itemType() {
20 | return 0;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/grid/GridPresenter.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.grid;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 | import java.util.concurrent.TimeUnit;
9 |
10 | import rx.Observable;
11 | import rx.Observer;
12 | import rx.Subscriber;
13 | import rx.Subscription;
14 | import rx.android.schedulers.AndroidSchedulers;
15 | import rx.schedulers.Schedulers;
16 | import rx.subscriptions.CompositeSubscription;
17 |
18 | /**
19 | * Author: Season(ssseasonnn@gmail.com)
20 | * Date: 2016/10/10
21 | * Time: 11:42
22 | * FIXME
23 | */
24 | class GridPresenter {
25 | private static int count = -1;
26 | private CompositeSubscription mSubscriptions;
27 | private GridView mView;
28 | private Context mContext;
29 |
30 | GridPresenter(Context context) {
31 | mContext = context;
32 | mSubscriptions = new CompositeSubscription();
33 | }
34 |
35 | void setDataLoadCallBack(GridView gridView) {
36 | mView = gridView;
37 | }
38 |
39 | void unsubscribeAll() {
40 | mSubscriptions.clear();
41 | }
42 |
43 | void loadData(final boolean isRefresh) {
44 | Subscription subscription = createObservable()
45 | .subscribeOn(Schedulers.io())
46 | .delay(2, TimeUnit.SECONDS)
47 | .observeOn(AndroidSchedulers.mainThread())
48 | .subscribe(new Observer>() {
49 | @Override
50 | public void onCompleted() {
51 |
52 | }
53 |
54 | @Override
55 | public void onError(Throwable e) {
56 | Log.w("SingleItemPresenter", e);
57 | mView.onDataLoadFailed(isRefresh);
58 | }
59 |
60 | @Override
61 | public void onNext(List gridBeen) {
62 | mView.onDataLoadSuccess(gridBeen, isRefresh);
63 | }
64 | });
65 | mSubscriptions.add(subscription);
66 | }
67 |
68 | private Observable> createObservable() {
69 | count++;
70 | count %= 6;
71 | return Observable.create(new Observable.OnSubscribe>() {
72 | @Override
73 | public void call(Subscriber super List> subscriber) {
74 | if (count == 3) {
75 | subscriber.onError(new Throwable("on error"));
76 | return;
77 | }
78 | if (count == 5) {
79 | subscriber.onNext(new ArrayList());
80 | return;
81 | }
82 | List mData = new ArrayList<>();
83 | for (int i = count * 5; i < count * 5 + 2; i++) {
84 | GridBean bean = new GridBean(i + "");
85 | mData.add(bean);
86 | }
87 | subscriber.onNext(mData);
88 | subscriber.onCompleted();
89 |
90 | }
91 | });
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/grid/GridView.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.grid;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Author: Season(ssseasonnn@gmail.com)
7 | * Date: 2016/10/10
8 | * Time: 11:42
9 | * FIXME
10 | */
11 | public interface GridView {
12 | void onDataLoadSuccess(List list, boolean isRefresh);
13 |
14 | void onDataLoadFailed(boolean isRefresh);
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/grid/GridViewHolder.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.grid;
2 |
3 | import android.content.Context;
4 | import android.view.ViewGroup;
5 | import android.widget.TextView;
6 | import android.widget.Toast;
7 |
8 | import butterknife.BindView;
9 | import butterknife.ButterKnife;
10 | import butterknife.OnClick;
11 | import zlc.season.demo.R;
12 | import zlc.season.practicalrecyclerview.AbstractViewHolder;
13 |
14 | /**
15 | * Author: Season(ssseasonnn@gmail.com)
16 | * Date: 2016/10/10
17 | * Time: 10:15
18 | * FIXME
19 | */
20 | public class GridViewHolder extends AbstractViewHolder {
21 | @BindView(R.id.text)
22 | TextView mText;
23 | private Context mContext;
24 |
25 | public GridViewHolder(ViewGroup parent) {
26 | super(parent, R.layout.grid_item);
27 | ButterKnife.bind(this, itemView);
28 | mContext = parent.getContext();
29 | }
30 |
31 | @Override
32 | public void setData(GridBean data) {
33 | mText.setText(data.text);
34 | }
35 |
36 | @OnClick(R.id.text)
37 | public void onClick() {
38 | Toast.makeText(mContext, mText.getText().toString(), Toast.LENGTH_SHORT).show();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/main/MainActivity.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.main;
2 |
3 | import android.os.Bundle;
4 | import android.support.design.widget.FloatingActionButton;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.support.v7.widget.LinearLayoutManager;
7 | import android.support.v7.widget.Toolbar;
8 |
9 | import java.util.List;
10 |
11 | import butterknife.BindView;
12 | import butterknife.ButterKnife;
13 | import zlc.season.demo.R;
14 | import zlc.season.practicalrecyclerview.PracticalRecyclerView;
15 |
16 | public class MainActivity extends AppCompatActivity {
17 |
18 | @BindView(R.id.toolbar)
19 | Toolbar mToolbar;
20 | @BindView(R.id.fab)
21 | FloatingActionButton mFab;
22 | @BindView(R.id.recycler)
23 | PracticalRecyclerView mRecycler;
24 |
25 | private MainAdapter mAdapter;
26 | private MainPresenter mPresenter;
27 |
28 | @Override
29 | protected void onCreate(Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.activity_main);
32 | ButterKnife.bind(this);
33 | setSupportActionBar(mToolbar);
34 |
35 | mAdapter = new MainAdapter();
36 | mPresenter = new MainPresenter(this);
37 |
38 | mRecycler.setLayoutManager(new LinearLayoutManager(this));
39 | mRecycler.setAdapterWithLoading(mAdapter);
40 |
41 | mPresenter.setDataLoadCallBack(new MainView() {
42 | @Override
43 | public void onLoadSuccess(List menu) {
44 | mAdapter.clear();
45 | mAdapter.addAll(menu);
46 | }
47 |
48 | @Override
49 | public void onLoadFailed() {
50 | mAdapter.showError();
51 | }
52 | });
53 | }
54 |
55 | @Override
56 | protected void onDestroy() {
57 | super.onDestroy();
58 | mPresenter.unsubscribeAll();
59 | }
60 |
61 | @Override
62 | protected void onResume() {
63 | super.onResume();
64 | mPresenter.loadData();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/main/MainAdapter.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.main;
2 |
3 | import android.view.ViewGroup;
4 |
5 | import zlc.season.practicalrecyclerview.AbstractAdapter;
6 |
7 | /**
8 | * Author: Season(ssseasonnn@gmail.com)
9 | * Date: 2016/10/8
10 | * Time: 14:19
11 | * FIXME
12 | */
13 | class MainAdapter extends AbstractAdapter {
14 | @Override
15 | protected MenuViewHolder onNewCreateViewHolder(ViewGroup parent, int viewType) {
16 | return new MenuViewHolder(parent);
17 | }
18 |
19 | @Override
20 | protected void onNewBindViewHolder(MenuViewHolder holder, int position) {
21 | holder.setData(get(position));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/main/MainPresenter.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.main;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 | import java.util.concurrent.TimeUnit;
9 |
10 | import rx.Observable;
11 | import rx.Observer;
12 | import rx.Subscriber;
13 | import rx.Subscription;
14 | import rx.android.schedulers.AndroidSchedulers;
15 | import rx.schedulers.Schedulers;
16 | import rx.subscriptions.CompositeSubscription;
17 | import zlc.season.demo.R;
18 |
19 | /**
20 | * Author: Season(ssseasonnn@gmail.com)
21 | * Date: 2016/10/8
22 | * Time: 14:34
23 | * FIXME
24 | */
25 | class MainPresenter {
26 |
27 | private CompositeSubscription mSubscriptions;
28 | private Context mContext;
29 | private MainView mMainView;
30 |
31 | MainPresenter(Context context) {
32 | mContext = context;
33 | mSubscriptions = new CompositeSubscription();
34 | }
35 |
36 | void setDataLoadCallBack(MainView mainView) {
37 | mMainView = mainView;
38 | }
39 |
40 | void unsubscribeAll() {
41 | mSubscriptions.clear();
42 | }
43 |
44 | void loadData() {
45 | Subscription subscription = createObservable()
46 | .subscribeOn(Schedulers.io())
47 | .delay(2, TimeUnit.SECONDS)
48 | .observeOn(AndroidSchedulers.mainThread())
49 | .subscribe(new Observer>() {
50 | @Override
51 | public void onCompleted() {
52 |
53 | }
54 |
55 | @Override
56 | public void onError(Throwable e) {
57 | mMainView.onLoadFailed();
58 | }
59 |
60 | @Override
61 | public void onNext(List menu) {
62 | mMainView.onLoadSuccess(menu);
63 | }
64 | });
65 | mSubscriptions.add(subscription);
66 | }
67 |
68 | private Observable> createObservable() {
69 | Resources res = mContext.getResources();
70 | final String[] resource = res.getStringArray(R.array.mennu);
71 | return Observable.create(new Observable.OnSubscribe>() {
72 | @Override
73 | public void call(Subscriber super List> subscriber) {
74 | List mData = new ArrayList<>();
75 | for (int i = 0; i < resource.length; i++) {
76 | String aResource = resource[i];
77 | MenuBean bean = new MenuBean();
78 | bean.menu = aResource;
79 | bean.type = i;
80 | mData.add(bean);
81 | }
82 | subscriber.onNext(mData);
83 | subscriber.onCompleted();
84 | }
85 | });
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/main/MainView.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.main;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Author: Season(ssseasonnn@gmail.com)
7 | * Date: 2016/10/8
8 | * Time: 15:12
9 | * FIXME
10 | */
11 | interface MainView {
12 | void onLoadSuccess(List menu);
13 |
14 | void onLoadFailed();
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/main/MenuBean.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.main;
2 |
3 | import zlc.season.practicalrecyclerview.ItemType;
4 |
5 | /**
6 | * Author: Season(ssseasonnn@gmail.com)
7 | * Date: 2016/10/8
8 | * Time: 14:21
9 | * FIXME
10 | */
11 | class MenuBean implements ItemType {
12 | public String menu;
13 | public int type;
14 |
15 | @Override
16 | public int itemType() {
17 | return 0;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/main/MenuViewHolder.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.main;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.LinearLayout;
8 | import android.widget.TextView;
9 |
10 | import butterknife.BindView;
11 | import butterknife.ButterKnife;
12 | import butterknife.OnClick;
13 | import zlc.season.demo.R;
14 | import zlc.season.demo.drag.DragActivity;
15 | import zlc.season.demo.expand.ExpandActivity;
16 | import zlc.season.demo.grid.GridActivity;
17 | import zlc.season.demo.multipleitem.MultiItemActivity;
18 | import zlc.season.demo.singleitem.ManualLoadMoreActivity;
19 | import zlc.season.demo.singleitem.SingleItemActivity;
20 | import zlc.season.demo.staggered.StaggeredActivity;
21 | import zlc.season.practicalrecyclerview.AbstractViewHolder;
22 |
23 | /**
24 | * Author: Season(ssseasonnn@gmail.com)
25 | * Date: 2016/10/8
26 | * Time: 14:22
27 | * FIXME
28 | */
29 | class MenuViewHolder extends AbstractViewHolder {
30 | @BindView(R.id.menu)
31 | TextView mMenu;
32 | @BindView(R.id.container)
33 | LinearLayout mLayout;
34 |
35 | private Context mContext;
36 | private MenuBean mBean;
37 |
38 | MenuViewHolder(ViewGroup parent) {
39 | super(parent, R.layout.menu_item);
40 | ButterKnife.bind(this, itemView);
41 | mContext = parent.getContext();
42 | }
43 |
44 | @OnClick(R.id.container)
45 | public void onClick(View view) {
46 | int type = mBean.type;
47 | switch (type) {
48 | case 0:
49 | mContext.startActivity(new Intent(mContext, SingleItemActivity.class));
50 | break;
51 | case 1:
52 | mContext.startActivity(new Intent(mContext, MultiItemActivity.class));
53 | break;
54 | case 2:
55 | mContext.startActivity(new Intent(mContext, GridActivity.class));
56 | break;
57 | case 3:
58 | mContext.startActivity(new Intent(mContext, StaggeredActivity.class));
59 | break;
60 | case 4:
61 | mContext.startActivity(new Intent(mContext, ManualLoadMoreActivity.class));
62 | break;
63 | case 5:
64 | mContext.startActivity(new Intent(mContext, DragActivity.class));
65 | break;
66 | case 6:
67 | mContext.startActivity(new Intent(mContext, ExpandActivity.class));
68 | break;
69 | }
70 |
71 | }
72 |
73 | @Override
74 | public void setData(MenuBean data) {
75 | mBean = data;
76 | mMenu.setText(data.menu);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/multipleitem/MultiItemActivity.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.multipleitem;
2 |
3 | import android.os.Bundle;
4 | import android.support.design.widget.FloatingActionButton;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.support.v7.widget.LinearLayoutManager;
7 | import android.support.v7.widget.Toolbar;
8 | import android.widget.RelativeLayout;
9 | import android.widget.Toast;
10 |
11 | import java.util.List;
12 |
13 | import butterknife.BindView;
14 | import butterknife.ButterKnife;
15 | import butterknife.OnClick;
16 | import zlc.season.demo.Header;
17 | import zlc.season.demo.R;
18 | import zlc.season.practicalrecyclerview.ItemType;
19 | import zlc.season.practicalrecyclerview.PracticalRecyclerView;
20 |
21 | public class MultiItemActivity extends AppCompatActivity {
22 |
23 | @BindView(R.id.toolbar)
24 | Toolbar mToolbar;
25 | @BindView(R.id.recycler)
26 | PracticalRecyclerView mRecycler;
27 | @BindView(R.id.content_multi_item)
28 | RelativeLayout mContentMultiItem;
29 | @BindView(R.id.fab)
30 | FloatingActionButton mFab;
31 |
32 | private MultiItemAdapter mAdapter;
33 | private MultiItemPresenter mPresenter;
34 |
35 | private boolean flag = true;
36 |
37 | @OnClick(R.id.fab)
38 | public void onClick() {
39 | flag = !flag;
40 | Toast.makeText(this, "flag:" + flag, Toast.LENGTH_SHORT).show();
41 | // mRecycler.setNoMoreViewEnabled(flag);
42 | mRecycler.setLoadMoreViewEnabled(flag);
43 | // mRecycler.setLoadMoreFailedViewEnabled(flag);
44 | }
45 |
46 | @Override
47 | protected void onCreate(Bundle savedInstanceState) {
48 | super.onCreate(savedInstanceState);
49 | setContentView(R.layout.activity_multi_item);
50 | ButterKnife.bind(this);
51 | setSupportActionBar(mToolbar);
52 |
53 | mAdapter = new MultiItemAdapter();
54 | mRecycler.setLayoutManager(new LinearLayoutManager(this));
55 | mRecycler.setAdapterWithLoading(mAdapter);
56 |
57 | mRecycler.setRefreshListener(new PracticalRecyclerView.OnRefreshListener() {
58 | @Override
59 | public void onRefresh() {
60 | mPresenter.loadData(true);
61 | }
62 | });
63 |
64 | mRecycler.setLoadMoreListener(new PracticalRecyclerView.OnLoadMoreListener() {
65 | @Override
66 | public void onLoadMore() {
67 | mPresenter.loadData(false);
68 | }
69 | });
70 |
71 | mPresenter = new MultiItemPresenter(this);
72 | mPresenter.setDataLoadCallBack(new MultiItemView() {
73 | @Override
74 | public void onDataLoadSuccess(List list, boolean isRefresh) {
75 | if (isRefresh) {
76 | mAdapter.clear();
77 | mAdapter.addHeader(new Header());
78 | // mAdapter.addFooter(new Header());
79 | mAdapter.addAll(list);
80 | } else {
81 | mAdapter.addAll(list);
82 | }
83 | }
84 |
85 | @Override
86 | public void onDataLoadFailed(boolean isRefresh) {
87 | if (isRefresh) {
88 | mAdapter.showError();
89 | } else {
90 | mAdapter.loadMoreFailed();
91 | }
92 | }
93 | });
94 | }
95 |
96 | @Override
97 | protected void onDestroy() {
98 | super.onDestroy();
99 | mPresenter.unsubscribeAll();
100 | }
101 |
102 | @Override
103 | protected void onResume() {
104 | super.onResume();
105 | mPresenter.loadData(true);
106 | }
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/multipleitem/MultiItemAdapter.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.multipleitem;
2 |
3 | import android.view.ViewGroup;
4 |
5 | import zlc.season.demo.RecyclerItemType;
6 | import zlc.season.practicalrecyclerview.AbstractAdapter;
7 | import zlc.season.practicalrecyclerview.AbstractViewHolder;
8 | import zlc.season.practicalrecyclerview.ItemType;
9 |
10 | /**
11 | * Author: Season(ssseasonnn@gmail.com)
12 | * Date: 2016/9/21
13 | * Time: 15:08
14 | * FIXME
15 | */
16 | public class MultiItemAdapter extends AbstractAdapter {
17 |
18 | @Override
19 | protected AbstractViewHolder onNewCreateViewHolder(ViewGroup parent, int viewType) {
20 | if (viewType == RecyclerItemType.TYPE1.getValue()) {
21 | return new TypeOneViewHolder(parent);
22 | } else if (viewType == RecyclerItemType.TYPE2.getValue()) {
23 | return new TypeTwoViewHolder(parent);
24 | }
25 | return null;
26 | }
27 |
28 | @Override
29 | protected void onNewBindViewHolder(AbstractViewHolder holder, int position) {
30 | if (holder instanceof TypeOneViewHolder) {
31 | ((TypeOneViewHolder) holder).setData((TypeOneBean) get(position));
32 | } else if (holder instanceof TypeTwoViewHolder) {
33 | ((TypeTwoViewHolder) holder).setData((TypeTwoBean) get(position));
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/multipleitem/MultiItemPresenter.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.multipleitem;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 | import java.util.concurrent.TimeUnit;
9 |
10 | import rx.Observable;
11 | import rx.Observer;
12 | import rx.Subscriber;
13 | import rx.Subscription;
14 | import rx.android.schedulers.AndroidSchedulers;
15 | import rx.schedulers.Schedulers;
16 | import rx.subscriptions.CompositeSubscription;
17 | import zlc.season.practicalrecyclerview.ItemType;
18 |
19 | /**
20 | * Author: Season(ssseasonnn@gmail.com)
21 | * Date: 2016/10/10
22 | * Time: 12:07
23 | * FIXME
24 | */
25 | public class MultiItemPresenter {
26 | private static int count = -1;
27 | private CompositeSubscription mSubscriptions;
28 | private MultiItemView mView;
29 | private Context mContext;
30 |
31 | MultiItemPresenter(Context context) {
32 | mContext = context;
33 | mSubscriptions = new CompositeSubscription();
34 | }
35 |
36 | void setDataLoadCallBack(MultiItemView itemView) {
37 | mView = itemView;
38 | }
39 |
40 | void unsubscribeAll() {
41 | mSubscriptions.clear();
42 | }
43 |
44 | void loadData(final boolean isRefresh) {
45 | Subscription subscription = createObservable()
46 | .subscribeOn(Schedulers.io())
47 | .delay(2, TimeUnit.SECONDS)
48 | .observeOn(AndroidSchedulers.mainThread())
49 | .subscribe(new Observer>() {
50 | @Override
51 | public void onCompleted() {
52 |
53 | }
54 |
55 | @Override
56 | public void onError(Throwable e) {
57 | Log.w("SingleItemPresenter", e);
58 | mView.onDataLoadFailed(isRefresh);
59 | }
60 |
61 | @Override
62 | public void onNext(List list) {
63 | mView.onDataLoadSuccess(list, isRefresh);
64 | }
65 | });
66 | mSubscriptions.add(subscription);
67 | }
68 |
69 | private Observable> createObservable() {
70 | count++;
71 | count %= 6;
72 | return Observable.create(new Observable.OnSubscribe>() {
73 | @Override
74 | public void call(Subscriber super List> subscriber) {
75 | if (count == 3) {
76 | subscriber.onError(new Throwable("on error"));
77 | return;
78 | }
79 | if (count == 5) {
80 | subscriber.onNext(new ArrayList());
81 | return;
82 | }
83 | List mData = new ArrayList<>();
84 | for (int i = count * 5; i < count * 5 + 2; i++) {
85 | if (i % 2 == 0) {
86 | ItemType bean = new TypeOneBean("type one");
87 | mData.add(bean);
88 | } else {
89 | ItemType bean = new TypeTwoBean("type two");
90 | mData.add(bean);
91 | }
92 | }
93 | subscriber.onNext(mData);
94 | subscriber.onCompleted();
95 | }
96 | });
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/multipleitem/MultiItemView.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.multipleitem;
2 |
3 | import java.util.List;
4 |
5 | import zlc.season.practicalrecyclerview.ItemType;
6 |
7 | /**
8 | * Author: Season(ssseasonnn@gmail.com)
9 | * Date: 2016/10/10
10 | * Time: 12:08
11 | * FIXME
12 | */
13 | public interface MultiItemView {
14 | void onDataLoadSuccess(List list, boolean isRefresh);
15 |
16 | void onDataLoadFailed(boolean isRefresh);
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/multipleitem/TypeOneBean.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.multipleitem;
2 |
3 | import zlc.season.demo.RecyclerItemType;
4 | import zlc.season.practicalrecyclerview.ItemType;
5 |
6 | /**
7 | * Author: Season(ssseasonnn@gmail.com)
8 | * Date: 2016/9/21
9 | * Time: 15:11
10 | * FIXME
11 | */
12 | class TypeOneBean implements ItemType {
13 |
14 | public String text;
15 |
16 | public TypeOneBean(String text) {
17 | this.text = text;
18 | }
19 |
20 | @Override
21 | public int itemType() {
22 | return RecyclerItemType.TYPE1.getValue();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/multipleitem/TypeOneViewHolder.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.multipleitem;
2 |
3 | import android.content.Context;
4 | import android.view.ViewGroup;
5 | import android.widget.TextView;
6 | import android.widget.Toast;
7 |
8 | import butterknife.BindView;
9 | import butterknife.ButterKnife;
10 | import butterknife.OnClick;
11 | import zlc.season.demo.R;
12 | import zlc.season.practicalrecyclerview.AbstractViewHolder;
13 |
14 | /**
15 | * Author: Season(ssseasonnn@gmail.com)
16 | * Date: 2016/9/22
17 | * Time: 09:59
18 | * FIXME
19 | */
20 | class TypeOneViewHolder extends AbstractViewHolder {
21 |
22 | @BindView(R.id.text)
23 | TextView mText;
24 |
25 | private Context mContext;
26 |
27 | TypeOneViewHolder(ViewGroup parent) {
28 | super(parent, R.layout.type_one_item);
29 | ButterKnife.bind(this, itemView);
30 | mContext = parent.getContext();
31 | }
32 |
33 | @Override
34 | public void setData(TypeOneBean data) {
35 | mText.setText(data.text);
36 | }
37 |
38 | @OnClick(R.id.text)
39 | public void onClick() {
40 | Toast.makeText(mContext, mText.getText().toString(), Toast.LENGTH_SHORT).show();
41 | }
42 | }
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/multipleitem/TypeTwoBean.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.multipleitem;
2 |
3 | import zlc.season.demo.RecyclerItemType;
4 | import zlc.season.practicalrecyclerview.ItemType;
5 |
6 | /**
7 | * Author: Season(ssseasonnn@gmail.com)
8 | * Date: 2016/10/10
9 | * Time: 11:56
10 | * FIXME
11 | */
12 | public class TypeTwoBean implements ItemType {
13 | String text;
14 |
15 | public TypeTwoBean(String text) {
16 | this.text = text;
17 | }
18 |
19 | @Override
20 | public int itemType() {
21 | return RecyclerItemType.TYPE2.getValue();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/multipleitem/TypeTwoViewHolder.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.multipleitem;
2 |
3 | import android.content.Context;
4 | import android.view.ViewGroup;
5 | import android.widget.TextView;
6 | import android.widget.Toast;
7 |
8 | import butterknife.BindView;
9 | import butterknife.ButterKnife;
10 | import butterknife.OnClick;
11 | import zlc.season.demo.R;
12 | import zlc.season.practicalrecyclerview.AbstractViewHolder;
13 |
14 | /**
15 | * Author: Season(ssseasonnn@gmail.com)
16 | * Date: 2016/10/10
17 | * Time: 12:01
18 | * FIXME
19 | */
20 | public class TypeTwoViewHolder extends AbstractViewHolder {
21 |
22 | @BindView(R.id.text)
23 | TextView mText;
24 | private Context mContext;
25 |
26 | public TypeTwoViewHolder(ViewGroup parent) {
27 | super(parent, R.layout.type_two_item);
28 | ButterKnife.bind(this, itemView);
29 | mContext = parent.getContext();
30 | }
31 |
32 | @Override
33 | public void setData(TypeTwoBean data) {
34 | mText.setText(data.text);
35 | }
36 |
37 | @OnClick(R.id.text)
38 | public void onClick() {
39 | Toast.makeText(mContext, mText.getText(), Toast.LENGTH_SHORT).show();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/singleitem/ManualLoadMoreActivity.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.singleitem;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.support.v7.widget.LinearLayoutManager;
6 | import android.view.View;
7 | import android.widget.Button;
8 | import android.widget.LinearLayout;
9 |
10 | import java.util.List;
11 |
12 | import butterknife.BindView;
13 | import butterknife.ButterKnife;
14 | import zlc.season.demo.Header;
15 | import zlc.season.demo.R;
16 | import zlc.season.practicalrecyclerview.ConfigureAdapter;
17 | import zlc.season.practicalrecyclerview.PracticalRecyclerView;
18 |
19 | /**
20 | * Author: Season(ssseasonnn@gmail.com)
21 | * Date: 2016/10/11
22 | * Time: 15:24
23 | * FIXME
24 | */
25 | public class ManualLoadMoreActivity extends AppCompatActivity {
26 |
27 | @BindView(R.id.recycler)
28 | PracticalRecyclerView mRecycler;
29 |
30 | private SingleItemAdapter mAdapter;
31 | private SingleItemPresenter mPresenter;
32 |
33 | private Button mNextPage;
34 | private LinearLayout mProgress;
35 |
36 | @Override
37 | protected void onCreate(Bundle savedInstanceState) {
38 | super.onCreate(savedInstanceState);
39 | setContentView(R.layout.activity_manual_load);
40 | ButterKnife.bind(this);
41 |
42 | configurePresenter();
43 | configureRecyclerView();
44 | }
45 |
46 | @Override
47 | protected void onDestroy() {
48 | super.onDestroy();
49 | mPresenter.unsubscribeAll();
50 | }
51 |
52 | @Override
53 | protected void onResume() {
54 | super.onResume();
55 | mPresenter.loadData(true);
56 | }
57 |
58 | private void configurePresenter() {
59 | mAdapter = new SingleItemAdapter();
60 | mPresenter = new SingleItemPresenter(this);
61 | mPresenter.setDataLoadCallBack(new SingleItemView() {
62 | @Override
63 | public void onDataLoadSuccess(List list, boolean isRefresh) {
64 | if (isRefresh) {
65 | mAdapter.clear();
66 | mAdapter.addHeader(new Header());
67 | // mAdapter.addFooter(new Header());
68 | mAdapter.addAll(list);
69 | } else {
70 | mAdapter.addAll(list);
71 | }
72 | setVisibility(View.VISIBLE, View.GONE);
73 | }
74 |
75 | @Override
76 | public void onDataLoadFailed(boolean isRefresh) {
77 | if (isRefresh) {
78 | mAdapter.showError();
79 | } else {
80 | mAdapter.loadMoreFailed();
81 | }
82 | setVisibility(View.VISIBLE, View.GONE);
83 | }
84 | });
85 | }
86 |
87 | private void configureRecyclerView() {
88 | //关闭自动加载更多, 改为手动触发
89 | mRecycler.setAutoLoadEnable(false);
90 | mRecycler.setLayoutManager(new LinearLayoutManager(this));
91 | mRecycler.setAdapterWithLoading(mAdapter);
92 |
93 | mRecycler.setRefreshListener(new PracticalRecyclerView.OnRefreshListener() {
94 | @Override
95 | public void onRefresh() {
96 | mPresenter.loadData(true);
97 | }
98 | });
99 | mRecycler.setLoadMoreListener(new PracticalRecyclerView.OnLoadMoreListener() {
100 | @Override
101 | public void onLoadMore() {
102 | mPresenter.loadData(false);
103 | }
104 | });
105 |
106 | mRecycler.configureView(new ConfigureAdapter() {
107 | @Override
108 | public void configureLoadMoreView(View loadMoreView) {
109 | super.configureLoadMoreView(loadMoreView);
110 | mNextPage = (Button) loadMoreView.findViewById(R.id.next_page);
111 | mProgress = (LinearLayout) loadMoreView.findViewById(R.id.loading);
112 | mNextPage.setOnClickListener(new View.OnClickListener() {
113 | @Override
114 | public void onClick(View v) {
115 | setVisibility(View.GONE, View.VISIBLE);
116 | //手动触发加载更多
117 | mAdapter.manualLoadMore();
118 | }
119 | });
120 | }
121 | });
122 | }
123 |
124 | private void setVisibility(int visible1, int visible2) {
125 | mNextPage.setVisibility(visible1);
126 | mProgress.setVisibility(visible2);
127 | }
128 | }
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/singleitem/NormalBean.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.singleitem;
2 |
3 | import zlc.season.practicalrecyclerview.ItemType;
4 |
5 | /**
6 | * Author: Season(ssseasonnn@gmail.com)
7 | * Date: 2016/9/21
8 | * Time: 15:33
9 | * FIXME
10 | */
11 | class NormalBean implements ItemType {
12 | String mImg;
13 | String mTitle;
14 | String mContent;
15 |
16 | NormalBean(String img, String title, String content) {
17 | mImg = img;
18 | mContent = content;
19 | mTitle = title;
20 | }
21 |
22 | @Override
23 | public int itemType() {
24 | return 0;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/singleitem/NormalViewHolder.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.singleitem;
2 |
3 | import android.content.Context;
4 | import android.net.Uri;
5 | import android.view.ViewGroup;
6 | import android.widget.ImageView;
7 | import android.widget.TextView;
8 |
9 | import com.squareup.picasso.Picasso;
10 |
11 | import butterknife.BindView;
12 | import butterknife.ButterKnife;
13 | import zlc.season.demo.R;
14 | import zlc.season.practicalrecyclerview.AbstractViewHolder;
15 |
16 | /**
17 | * Author: Season(ssseasonnn@gmail.com)
18 | * Date: 2016/9/22
19 | * Time: 09:58
20 | * FIXME
21 | */
22 |
23 | class NormalViewHolder extends AbstractViewHolder {
24 | @BindView(R.id.head)
25 | ImageView mHead;
26 | @BindView(R.id.title)
27 | TextView mTitle;
28 | @BindView(R.id.content)
29 | TextView mContent;
30 |
31 | private Context mContext;
32 |
33 | NormalViewHolder(ViewGroup parent) {
34 | super(parent, R.layout.normal_item);
35 | mContext = parent.getContext();
36 | ButterKnife.bind(this, itemView);
37 | }
38 |
39 | @Override
40 | public void setData(NormalBean data) {
41 | Picasso.with(mContext).load(Uri.parse(data.mImg)).into(mHead);
42 | mTitle.setText(data.mTitle);
43 | mContent.setText(data.mContent);
44 | }
45 | }
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/singleitem/SingleItemActivity.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.singleitem;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.support.v7.widget.LinearLayoutManager;
6 | import android.view.Menu;
7 | import android.view.MenuItem;
8 |
9 | import java.util.List;
10 |
11 | import butterknife.BindView;
12 | import butterknife.ButterKnife;
13 | import zlc.season.demo.Header;
14 | import zlc.season.demo.R;
15 | import zlc.season.practicalrecyclerview.PracticalRecyclerView;
16 |
17 | public class SingleItemActivity extends AppCompatActivity {
18 |
19 | @BindView(R.id.recycler)
20 | PracticalRecyclerView mRecycler;
21 |
22 | private boolean isNoMoreEnabled = false;
23 | private boolean isLoadMoreEnabled = false;
24 | private boolean isLoadMoreFailedEnabled = false;
25 |
26 | private boolean isAutoLoadEnabled = true;
27 |
28 | private SingleItemAdapter mAdapter;
29 | private SingleItemPresenter mPresenter;
30 |
31 | @Override
32 | public boolean onCreateOptionsMenu(Menu menu) {
33 | // Inflate the menu; this adds items to the action bar if it is present.
34 | getMenuInflater().inflate(R.menu.menu, menu);
35 | return true;
36 | }
37 |
38 | @Override
39 | public boolean onPrepareOptionsMenu(Menu menu) {
40 | MenuItem noMore = menu.findItem(R.id.action_no_more_enabled);
41 | MenuItem loadMore = menu.findItem(R.id.action_load_more_enabled);
42 | MenuItem loadMoreFailed = menu.findItem(R.id.action_load_more_failed_enabled);
43 | MenuItem autoLoad = menu.findItem(R.id.action_auto_load_enabled);
44 | noMore.setChecked(isNoMoreEnabled);
45 | loadMore.setChecked(isLoadMoreEnabled);
46 | loadMoreFailed.setChecked(isLoadMoreFailedEnabled);
47 | autoLoad.setChecked(isAutoLoadEnabled);
48 | return true;
49 | }
50 |
51 | @Override
52 | public boolean onOptionsItemSelected(MenuItem item) {
53 | // Handle action bar item clicks here. The action bar will
54 | // automatically handle clicks on the Home/Up button, so long
55 | // as you specify a parent activity in AndroidManifest.xml.
56 | int id = item.getItemId();
57 |
58 | switch (id) {
59 | case R.id.action_no_more_enabled:
60 | isNoMoreEnabled = !item.isChecked();
61 | item.setChecked(isNoMoreEnabled);
62 | mRecycler.setNoMoreViewEnabled(!isNoMoreEnabled);
63 | return true;
64 | case R.id.action_load_more_enabled:
65 | isLoadMoreEnabled = !item.isChecked();
66 | item.setChecked(isLoadMoreEnabled);
67 | mRecycler.setLoadMoreViewEnabled(!isLoadMoreEnabled);
68 | return true;
69 | case R.id.action_load_more_failed_enabled:
70 | isLoadMoreFailedEnabled = !item.isChecked();
71 | item.setChecked(isLoadMoreFailedEnabled);
72 | mRecycler.setLoadMoreFailedViewEnabled(!isLoadMoreFailedEnabled);
73 | return true;
74 | case R.id.action_auto_load_enabled:
75 | isAutoLoadEnabled = !item.isChecked();
76 | item.setChecked(isAutoLoadEnabled);
77 | mRecycler.setAutoLoadEnable(isAutoLoadEnabled);
78 | return true;
79 | }
80 |
81 | return super.onOptionsItemSelected(item);
82 | }
83 |
84 | @Override
85 | protected void onCreate(Bundle savedInstanceState) {
86 | super.onCreate(savedInstanceState);
87 | setContentView(R.layout.activity_single_item);
88 | ButterKnife.bind(this);
89 |
90 | configurePresenter();
91 | configureRecyclerView();
92 | }
93 |
94 | @Override
95 | protected void onDestroy() {
96 | super.onDestroy();
97 | mPresenter.unsubscribeAll();
98 | }
99 |
100 | @Override
101 | protected void onResume() {
102 | super.onResume();
103 | mPresenter.loadData(true);
104 | }
105 |
106 | private void configurePresenter() {
107 | mAdapter = new SingleItemAdapter();
108 | mPresenter = new SingleItemPresenter(this);
109 | mPresenter.setDataLoadCallBack(new SingleItemView() {
110 | @Override
111 | public void onDataLoadSuccess(List list, boolean isRefresh) {
112 | if (isRefresh) {
113 | mAdapter.clear();
114 | mAdapter.addHeader(new Header());
115 | // mAdapter.addFooter(new Header());
116 | mAdapter.addAll(list);
117 | } else {
118 | mAdapter.addAll(list);
119 | }
120 | }
121 |
122 | @Override
123 | public void onDataLoadFailed(boolean isRefresh) {
124 | if (isRefresh) {
125 | mAdapter.showError();
126 | } else {
127 | mAdapter.loadMoreFailed();
128 | }
129 | }
130 | });
131 | }
132 |
133 | private void configureRecyclerView() {
134 | mRecycler.setLayoutManager(new LinearLayoutManager(this));
135 | mRecycler.setAdapterWithLoading(mAdapter);
136 |
137 | mRecycler.setRefreshListener(new PracticalRecyclerView.OnRefreshListener() {
138 | @Override
139 | public void onRefresh() {
140 | mPresenter.loadData(true);
141 | }
142 | });
143 | mRecycler.setLoadMoreListener(new PracticalRecyclerView.OnLoadMoreListener() {
144 | @Override
145 | public void onLoadMore() {
146 | mPresenter.loadData(false);
147 | }
148 | });
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/singleitem/SingleItemAdapter.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.singleitem;
2 |
3 | import android.view.ViewGroup;
4 |
5 | import zlc.season.practicalrecyclerview.AbstractAdapter;
6 |
7 | /**
8 | * Author: Season(ssseasonnn@gmail.com)
9 | * Date: 2016/9/22
10 | * Time: 09:47
11 | * FIXME
12 | */
13 | class SingleItemAdapter extends AbstractAdapter {
14 |
15 | @Override
16 | protected NormalViewHolder onNewCreateViewHolder(ViewGroup parent, int viewType) {
17 | return new NormalViewHolder(parent);
18 | }
19 |
20 | @Override
21 | protected void onNewBindViewHolder(NormalViewHolder holder, int position) {
22 | holder.setData(get(position));
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/singleitem/SingleItemPresenter.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.singleitem;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 | import android.util.Log;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 | import java.util.concurrent.TimeUnit;
10 |
11 | import rx.Observable;
12 | import rx.Observer;
13 | import rx.Subscriber;
14 | import rx.Subscription;
15 | import rx.android.schedulers.AndroidSchedulers;
16 | import rx.schedulers.Schedulers;
17 | import rx.subscriptions.CompositeSubscription;
18 | import zlc.season.demo.R;
19 |
20 | /**
21 | * Author: Season(ssseasonnn@gmail.com)
22 | * Date: 2016/9/23
23 | * Time: 15:16
24 | * FIXME
25 | */
26 | class SingleItemPresenter {
27 | private static int count = -1;
28 | private CompositeSubscription mSubscriptions;
29 | private SingleItemView mSingleItemView;
30 | private Context mContext;
31 |
32 | SingleItemPresenter(Context context) {
33 | mContext = context;
34 | mSubscriptions = new CompositeSubscription();
35 | }
36 |
37 | void setDataLoadCallBack(SingleItemView singleItemView) {
38 | mSingleItemView = singleItemView;
39 | }
40 |
41 | void unsubscribeAll() {
42 | mSubscriptions.clear();
43 | }
44 |
45 | void loadData(final boolean isRefresh) {
46 | Subscription subscription = createObservable()
47 | .subscribeOn(Schedulers.io())
48 | .delay(2, TimeUnit.SECONDS)
49 | .observeOn(AndroidSchedulers.mainThread())
50 | .subscribe(new Observer>() {
51 | @Override
52 | public void onCompleted() {
53 |
54 | }
55 |
56 | @Override
57 | public void onError(Throwable e) {
58 | Log.w("SingleItemPresenter", e);
59 | mSingleItemView.onDataLoadFailed(isRefresh);
60 | }
61 |
62 | @Override
63 | public void onNext(List normalBeen) {
64 | mSingleItemView.onDataLoadSuccess(normalBeen, isRefresh);
65 | }
66 | });
67 | mSubscriptions.add(subscription);
68 | }
69 |
70 | private Observable> createObservable() {
71 | count++;
72 | count %= 6;
73 | Resources res = mContext.getResources();
74 | final String[] images = res.getStringArray(R.array.image);
75 | final String[] titles = res.getStringArray(R.array.title);
76 | final String[] contents = res.getStringArray(R.array.content);
77 | return Observable.create(new Observable.OnSubscribe>() {
78 | @Override
79 | public void call(Subscriber super List> subscriber) {
80 | if (count == 3) {
81 | subscriber.onError(new Throwable("on error"));
82 | return;
83 | }
84 | if (count == 5) {
85 | subscriber.onNext(new ArrayList());
86 | return;
87 | }
88 | List mData = new ArrayList<>();
89 | for (int i = count * 5; i < count * 5 + 2; i++) {
90 | NormalBean bean = new NormalBean(images[i], titles[i], contents[i]);
91 | mData.add(bean);
92 | }
93 | subscriber.onNext(mData);
94 | subscriber.onCompleted();
95 |
96 | }
97 | });
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/singleitem/SingleItemView.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.singleitem;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Author: Season(ssseasonnn@gmail.com)
7 | * Date: 2016/9/23
8 | * Time: 15:17
9 | * FIXME
10 | */
11 | interface SingleItemView {
12 | void onDataLoadSuccess(List list, boolean isRefresh);
13 |
14 | void onDataLoadFailed(boolean isRefresh);
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/staggered/StaggerAdapter.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.staggered;
2 |
3 | import android.view.ViewGroup;
4 |
5 | import zlc.season.practicalrecyclerview.AbstractAdapter;
6 |
7 | /**
8 | * Author: Season(ssseasonnn@gmail.com)
9 | * Date: 2016/10/10
10 | * Time: 13:47
11 | * FIXME
12 | */
13 | public class StaggerAdapter extends AbstractAdapter {
14 | @Override
15 | protected StaggerViewHolder onNewCreateViewHolder(ViewGroup parent, int viewType) {
16 | return new StaggerViewHolder(parent);
17 | }
18 |
19 | @Override
20 | protected void onNewBindViewHolder(StaggerViewHolder holder, int position) {
21 | holder.setData(get(position));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/staggered/StaggerBean.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.staggered;
2 |
3 | import zlc.season.practicalrecyclerview.ItemType;
4 |
5 | /**
6 | * Author: Season(ssseasonnn@gmail.com)
7 | * Date: 2016/10/10
8 | * Time: 13:38
9 | * FIXME
10 | */
11 | public class StaggerBean implements ItemType {
12 | String text;
13 |
14 | public StaggerBean(String text) {
15 | this.text = text;
16 | }
17 |
18 | @Override
19 | public int itemType() {
20 | return 0;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/staggered/StaggerPresenter.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.staggered;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 | import java.util.concurrent.TimeUnit;
9 |
10 | import rx.Observable;
11 | import rx.Observer;
12 | import rx.Subscriber;
13 | import rx.Subscription;
14 | import rx.android.schedulers.AndroidSchedulers;
15 | import rx.schedulers.Schedulers;
16 | import rx.subscriptions.CompositeSubscription;
17 |
18 | /**
19 | * Author: Season(ssseasonnn@gmail.com)
20 | * Date: 2016/10/10
21 | * Time: 11:42
22 | * FIXME
23 | */
24 | class StaggerPresenter {
25 | private static int count = -1;
26 | private CompositeSubscription mSubscriptions;
27 | private StaggerView mView;
28 | private Context mContext;
29 |
30 | StaggerPresenter(Context context) {
31 | mContext = context;
32 | mSubscriptions = new CompositeSubscription();
33 | }
34 |
35 | void setDataLoadCallBack(StaggerView staggerView) {
36 | mView = staggerView;
37 | }
38 |
39 | void unsubscribeAll() {
40 | mSubscriptions.clear();
41 | }
42 |
43 | void loadData(final boolean isRefresh) {
44 | Subscription subscription = createObservable()
45 | .subscribeOn(Schedulers.io())
46 | .delay(2, TimeUnit.SECONDS)
47 | .observeOn(AndroidSchedulers.mainThread())
48 | .subscribe(new Observer>() {
49 | @Override
50 | public void onCompleted() {
51 |
52 | }
53 |
54 | @Override
55 | public void onError(Throwable e) {
56 | Log.w("SingleItemPresenter", e);
57 | mView.onDataLoadFailed(isRefresh);
58 | }
59 |
60 | @Override
61 | public void onNext(List list) {
62 | mView.onDataLoadSuccess(list, isRefresh);
63 | }
64 | });
65 | mSubscriptions.add(subscription);
66 | }
67 |
68 | private Observable> createObservable() {
69 | count++;
70 | count %= 6;
71 | return Observable.create(new Observable.OnSubscribe>() {
72 | @Override
73 | public void call(Subscriber super List> subscriber) {
74 | if (count == 3) {
75 | subscriber.onError(new Throwable("on error"));
76 | return;
77 | }
78 | if (count == 5) {
79 | subscriber.onNext(new ArrayList());
80 | return;
81 | }
82 | List mData = new ArrayList<>();
83 | for (int i = count * 5; i < count * 5 + 2; i++) {
84 | StaggerBean bean = new StaggerBean(i + "");
85 | mData.add(bean);
86 | }
87 | subscriber.onNext(mData);
88 | subscriber.onCompleted();
89 |
90 | }
91 | });
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/staggered/StaggerView.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.staggered;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Author: Season(ssseasonnn@gmail.com)
7 | * Date: 2016/10/10
8 | * Time: 11:42
9 | * FIXME
10 | */
11 | public interface StaggerView {
12 | void onDataLoadSuccess(List list, boolean isRefresh);
13 |
14 | void onDataLoadFailed(boolean isRefresh);
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/staggered/StaggerViewHolder.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.staggered;
2 |
3 | import android.view.ViewGroup;
4 | import android.widget.TextView;
5 |
6 | import butterknife.BindView;
7 | import butterknife.ButterKnife;
8 | import butterknife.OnClick;
9 | import zlc.season.demo.R;
10 | import zlc.season.practicalrecyclerview.AbstractViewHolder;
11 |
12 | /**
13 | * Author: Season(ssseasonnn@gmail.com)
14 | * Date: 2016/10/10
15 | * Time: 13:38
16 | * FIXME
17 | */
18 | public class StaggerViewHolder extends AbstractViewHolder {
19 | @BindView(R.id.text)
20 | TextView mText;
21 |
22 | public StaggerViewHolder(ViewGroup parent) {
23 | super(parent, R.layout.stagger_item);
24 | ButterKnife.bind(this, itemView);
25 | }
26 |
27 | @Override
28 | public void setData(StaggerBean data) {
29 | mText.setText(data.text);
30 |
31 | int height = (int) (100 + Math.random() * 300);
32 | ViewGroup.LayoutParams lp = itemView.getLayoutParams();
33 | lp.height = height;
34 |
35 | itemView.setLayoutParams(lp);
36 | }
37 |
38 | @OnClick(R.id.text)
39 | public void onClick() {
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/zlc/season/demo/staggered/StaggeredActivity.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo.staggered;
2 |
3 | import android.os.Bundle;
4 | import android.support.design.widget.FloatingActionButton;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.support.v7.widget.StaggeredGridLayoutManager;
7 | import android.support.v7.widget.Toolbar;
8 | import android.widget.RelativeLayout;
9 |
10 | import java.util.List;
11 |
12 | import butterknife.BindView;
13 | import butterknife.ButterKnife;
14 | import butterknife.OnClick;
15 | import zlc.season.demo.Header;
16 | import zlc.season.demo.R;
17 | import zlc.season.practicalrecyclerview.PracticalRecyclerView;
18 |
19 | public class StaggeredActivity extends AppCompatActivity {
20 |
21 | @BindView(R.id.toolbar)
22 | Toolbar mToolbar;
23 | @BindView(R.id.recycler)
24 | PracticalRecyclerView mRecycler;
25 | @BindView(R.id.content_staggered)
26 | RelativeLayout mContentStaggered;
27 | @BindView(R.id.fab)
28 | FloatingActionButton mFab;
29 |
30 | private StaggerAdapter mAdapter;
31 | private StaggerPresenter mPresenter;
32 |
33 | @OnClick(R.id.fab)
34 | public void onClick() {
35 | }
36 |
37 | @Override
38 | protected void onCreate(Bundle savedInstanceState) {
39 | super.onCreate(savedInstanceState);
40 | setContentView(R.layout.activity_staggered);
41 | ButterKnife.bind(this);
42 | setSupportActionBar(mToolbar);
43 |
44 | mAdapter = new StaggerAdapter();
45 | mRecycler.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
46 | mRecycler.setAdapterWithLoading(mAdapter);
47 |
48 | mRecycler.setRefreshListener(new PracticalRecyclerView.OnRefreshListener() {
49 | @Override
50 | public void onRefresh() {
51 | mPresenter.loadData(true);
52 | }
53 | });
54 |
55 | mRecycler.setLoadMoreListener(new PracticalRecyclerView.OnLoadMoreListener() {
56 | @Override
57 | public void onLoadMore() {
58 | mPresenter.loadData(false);
59 | }
60 | });
61 |
62 | mPresenter = new StaggerPresenter(this);
63 | mPresenter.setDataLoadCallBack(new StaggerView() {
64 | @Override
65 | public void onDataLoadSuccess(List list, boolean isRefresh) {
66 | if (isRefresh) {
67 | mAdapter.clear();
68 | mAdapter.addHeader(new Header());
69 | // mAdapter.addFooter(new Header());
70 | mAdapter.addAll(list);
71 | } else {
72 | mAdapter.addAll(list);
73 | }
74 | }
75 |
76 | @Override
77 | public void onDataLoadFailed(boolean isRefresh) {
78 | if (isRefresh) {
79 | mAdapter.showError();
80 | } else {
81 | mAdapter.loadMoreFailed();
82 | }
83 | }
84 | });
85 | }
86 |
87 | @Override
88 | protected void onDestroy() {
89 | super.onDestroy();
90 | mPresenter.unsubscribeAll();
91 | }
92 |
93 | @Override
94 | protected void onResume() {
95 | super.onResume();
96 | mPresenter.loadData(true);
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_camera.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_gallery.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_manage.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_send.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_share.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_slideshow.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_keyboard_arrow_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/drawable-xhdpi/ic_keyboard_arrow_down.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_keyboard_arrow_up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/drawable-xhdpi/ic_keyboard_arrow_up.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_reorder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/drawable-xhdpi/ic_reorder.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/side_nav_bar.xml:
--------------------------------------------------------------------------------
1 |
3 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_drag.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_expand.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
27 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_grid.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
27 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
27 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_manual_load.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_multi_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
27 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_single_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_staggered.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
27 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/child_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_drag.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_expand.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_grid.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_multi_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_staggered.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/drag_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
23 |
24 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/grid_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/header_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/manual_load_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
22 |
23 |
28 |
29 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/menu_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/normal_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
17 |
22 |
23 |
32 |
33 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/parent_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
23 |
24 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/stagger_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/type_one_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/type_two_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/drag_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/a.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/mipmap-xhdpi/a.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/mipmap-xhdpi/b.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/c.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/mipmap-xhdpi/c.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/d.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/mipmap-xhdpi/d.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/e.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/mipmap-xhdpi/e.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/f.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/mipmap-xhdpi/f.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/g.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/mipmap-xhdpi/g.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/h.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/mipmap-xhdpi/h.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 |
7 | 16dp
8 | 160dp
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Demo
3 | MainActivity
4 |
5 |
6 | - SingleItem列表
7 | - MultiItem列表
8 | - Grid
9 | - 瀑布流
10 | - 手动触发加载更多
11 | - 拖拽
12 | - ExpandItemList
13 |
14 |
15 |
16 | {
17 | "data":[
18 | {
19 | "text": 0,
20 | "child": [
21 | {"text": 0},
22 | {"text": 1}
23 | ]
24 | },
25 | {
26 | "text": 1,
27 | "child": [
28 | {"text": 0},
29 | {"text": 1}
30 |
31 |
32 | ]
33 | }
34 | ]
35 | }
36 |
37 |
38 |
39 | {"data": [
40 | {
41 | "text": 0,
42 | "child": [
43 | {"text": 0},
44 | {"text": 1},
45 | {"text": 2},
46 | {"text": 3}
47 | ]
48 | },
49 | {
50 | "text": 1,
51 | "child": [
52 | {"text": 0},
53 | {"text": 1},
54 | {"text": 2},
55 | {"text": 3}
56 | ]
57 | },
58 | {
59 | "text": 2,
60 | "child": [
61 | {"text": 0},
62 | {"text": 1},
63 | {"text": 2},
64 | {"text": 3}
65 | ]
66 | },
67 | {
68 | "text": 3,
69 | "child": [
70 | {"text": 0},
71 | {"text": 1},
72 | {"text": 2},
73 | {"text": 3}
74 | ]
75 | },
76 | {
77 | "text": 4,
78 | "child": [
79 | {"text": 0},
80 | {"text": 1},
81 | {"text": 2},
82 | {"text": 3}
83 | ]
84 | }
85 | ]}
86 |
87 |
88 |
89 | - http://pic4.zhimg.com/d672dba4d597876c6ad33427780f6a37_m.jpg
90 | - http://pic4.zhimg.com/e803f3e7a832b035f9bd2dff87033133_m.jpg
91 | - http://pic4.zhimg.com/e803f3e7a832b035f9bd2dff87033133_m.jpg
92 | - http://pic4.zhimg.com/f07808da5625fef3607f8b75b770349f_m.jpg
93 | - http://pic4.zhimg.com/f07808da5625fef3607f8b75b770349f_m.jpg
94 | - http://pic3.zhimg.com/b85ddd8aa_m.jpg
95 | - http://pic4.zhimg.com/d672dba4d597876c6ad33427780f6a37_m.jpg
96 | - http://pic4.zhimg.com/95b86ea8b502d9aef1b13f621bba2ef3_m.jpg
97 | - http://pic1.zhimg.com/7b050959c_m.jpg
98 | - http://pic4.zhimg.com/f07808da5625fef3607f8b75b770349f_m.jpg
99 | - http://pic4.zhimg.com/16bfc7e37_m.jpg
100 | - http://pic4.zhimg.com/f07808da5625fef3607f8b75b770349f_m.jpg
101 | - http://pic4.zhimg.com/f07808da5625fef3607f8b75b770349f_m.jpg
102 | - http://pic4.zhimg.com/e803f3e7a832b035f9bd2dff87033133_m.jpg
103 | - http://pic4.zhimg.com/f07808da5625fef3607f8b75b770349f_m.jpg
104 | - http://pic4.zhimg.com/f07808da5625fef3607f8b75b770349f_m.jpg
105 | - http://pic1.zhimg.com/7b050959c_m.jpg
106 | - http://pic4.zhimg.com/e803f3e7a832b035f9bd2dff87033133_m.jpg
107 | - http://pic4.zhimg.com/d672dba4d597876c6ad33427780f6a37_m.jpg
108 | - http://pic4.zhimg.com/e803f3e7a832b035f9bd2dff87033133_m.jpg
109 | - http://pic4.zhimg.com/f07808da5625fef3607f8b75b770349f_m.jpg
110 | - http://pic3.zhimg.com/b85ddd8aa_m.jpg
111 | - http://pic1.zhimg.com/9db7191dc_m.jpg
112 | - http://pic4.zhimg.com/f07808da5625fef3607f8b75b770349f_m.jpg
113 | - http://pic1.zhimg.com/bb001daf610146168242bff98cf514ec_m.png
114 |
115 |
116 | - 如何设计出好看又实用的家居收纳系统呢?
117 | - 车险哥告诉你,出事故不要轻易揽全责
118 | - 哪些人不宜尝试买二手车?
119 | - 作为普通用户,淘宝购物时,有哪些你经常用但一般人不知道的方法?
120 | - 评《Mathematics for Computer Science》
121 | - 众多活动策划案,ppt模版,行业报告免费分享
122 | - 分享几个有意思,稀奇古怪的网站,不要错过~
123 | - 如何看待疑似炒房团抢空成都城南高新区部分楼盘?
124 | - 有哪些能给人带来极大幸福感的家用电器?
125 | - 如何看待美国共和党总统候选人Donald Trump发表声明反对美国政府放弃DNS管理权?
126 | - 如何用低成本打造全能卫生间
127 | - 如何干掉一家网络公司、干掉互联网人,APT攻击!
128 | - 来看看有没有你想要的干货
129 | - 当你有了车,实质上你有了什么?
130 | - 怎么看“阿里巴巴超越百度成中国最大互联网广告平台”?
131 | - 电商大逃亡,实体店即将崛起!
132 | - 如何看待疑似炒房团抢空成都城南高新区部分楼盘?
133 | - 当你有了车,实质上你有了什么?
134 | - 怎么评价宜家(IKEA)?
135 | - 何优雅地借车(或拒绝借车)?
136 | - 如何评价「一夜之间百度云被塞满黄片」?
137 | - 什么是迁移学习 (Transfer Learning)?这个领域历史发展前景如何?
138 | - 你读过的最好的 C++ 开源代码是什么?
139 | - 如何看待美国共和党总统候选人Donald Trump发表声明反对美国政府放弃DNS管理权?
140 | - 《交换空间》有哪些很成功的案例?
141 |
142 |
143 | - 观察者说去看德国日本普通住宅的样子,从房子的硬装上来说都非常之简单,大多是大白墙和原木地板,空间处理得非常中性化,像一张白纸一样,所谓主人的个性化大概都把任务交给了家具和陈设。但是有一点值得注意的事,在硬装中,储物系统的设计会非常重视,一…
144 | - 从一个案例说起,看完后估计车主朋友会后背发凉,车险哥先来介绍一个案例吧: 【案例】 甲驾驶机动车通过十字路口时,与闯红灯的汽车人乙相撞造成乙头部受伤。 【处理经过】 发生交通事故后,乙当时与甲争吵。甲报警。交警赶到后,询问甲都购买了什么保险。…
145 | - 周含露_iCheNuonuo【写在前面】这篇文章可能不受部分人欢迎,却可能帮你避免一笔不明智的开支。 2016年是我涉足二手车的第十个年头了。十年里,从给自己、给同事找车,到给素未谋面的网友淘车,已有数千人跟诺诺在二手车这个话题上有过交集,他们形形色色,…
146 |
147 | - 我也来说一说,作为天猫、京东、淘宝多年的运营。我也来分享一些。 请勿转载。 如果你年网购1万元,我可以说最少让你省2000.可以说百分之90的宝贝都可以返。多少而已。你再也不用去等双11了!! 现在的淘宝水很深的!你们能看到的卖的好的店家,很大一部分…
148 | - MIT open courseware 6.042J/18.062J在目前的本科教学中,一门门课程就像一个个孤岛,学生们淹死在从一个孤岛游向另一个孤岛的途中。每个老师守在各自的孤岛上。能把一个孤岛打理好的老师,已属难得,对于孤岛中将要淹死的学生,实在是无力顾及。对于计算机…
149 | - 今日从网盘拿出几百份行业报告,活动策划,ppt模版,创业BP,营销推广方案等给大家,本人酷爱收集各类信息,有一些小圈子流传的干货和付费才可得到的东西,以及整理了各大网站,论坛,公众号等的信息资源,行业报告,策划书,ppt去很多网站就可以下载得到了,这…
150 | - 早上收到呼友私信说公众号搜不到了,登录一看原来公众号因为之前推荐过一篇国内如何使用谷歌的文章被屏蔽一个月,昨天几百个呼友在后台的留言也没来的及回复,所以现在新开公众号 干货推荐 ID(ganhuo010),学习,分享,交流,欢迎来到我新家留言骚扰,但……
151 |
152 | - 地震都毁不掉的,可能要被这批人毁掉了。 我真的恨他们! 我在成都有房子,不止一套,房价涨了我表面上是既得利益者。 但我超级恨他们 我恨他们当着我的面一点一点毁掉这个城市最珍贵的品质。 成都为什么那么吸引人 普通小白领,7000元月薪,2000元供房。20…
153 |
154 | - 这是一篇价值逼近100W的回答,希望你能看好自己的钱包。 吃好很重要 1.IH电饭煲 多数国人的主食都是米饭,米饭吃的好一点对生活质量的提升自然极大的,IH电饭煲的优点有: 强大的火力:快速升温,米粒迅速吸热,不会散架。优秀热传导力:帮助米粒充分吸水,…
155 | - 这么重要的东西,奥巴马居然要交出去。 ICANN 是干嘛的? 互联网名称与数字地址分配机构是一家非营利组织,负责在全球范围内对互联网唯一标识符系统及其安全稳定的运营进行协调。 如果你还是不明白,那我举个简单的例子,你注册了个网站 http://weixin.xxx…
156 | - 现代装修既要实用功能,又要个性风格,所以预算常常很难控制。卫浴空间使用率较高,如果处处“能省则省”,就会发生返工、维修,得不偿失。与此同时家具和装饰成本等也存在进退空间,花与不花的问题还需要因地制宜的划重点。 墙面区 防水必不可少 不能省: …
157 | - 起因:无极领域博客所在的主机商被攻击了,一个成立6年,在业内名气很大的网络提供商就这么被干了,旗下所有客户包括他们自己的官网全部被干死了。搞他们的十之八九是同行,这几乎是网络圈子公开的秘密,看你不顺眼就打你,打的质疑人生。没错,本文讲一些…
158 | - 开篇先来两个动态图网站soogif(这是国内的)你们在公众看到的动态图很多都源于这里。如果是公众号编辑人员应该会有些帮助,SOOGIF提供搞笑、表情、美女、明星、热门事件GIF动图全搜索,QQ、微信斗图神器,魔性、鬼畜、性感、福利、金馆长、暴漫、二次元野…
159 | - 大学期间,禁不住诱惑,让爸妈给买了辆车,不是什么好车,具体牌子型号先不说吧。 车是从买车的城市自己开回学校,车是在女友的城市买的,之前自己开车从未跑过这么远的路,回来的路上有山,我最喜欢山水,可能是因为我家乡没有山的缘故吧。一路上简直是享…
160 | - 很多人不懂阿里巴巴的盈利模式。 同样做电商,亚马逊、京东成立十几二十年,一直到今年之前还在亏损,还没赚钱。而阿里巴巴早已赚得盆满钵满。这是为何? 两者区别在于盈利模式的不同。再具体的说,阿里巴巴是坐着收广告费,而亚马逊、京东没收广告费。 阿…
161 | - 作者:水木然 来源:水木然(smr8700)、商智库(shangretail) 链接:电商大逃亡,实体店即将崛起! 商业转载请联系作者获得授权,非商业转载请注明出处。 电商的成本越来越高。电商已经突飞猛进地发展了很多年,现在的电商成本之高已不低于实体店:人工11…
162 | - 我爱这个城市,我怕她完了 半夜睡不着觉,不邀自答吧。 我和我老婆都是土生土长的成都人,两边家里除开自主的房子,可供投资用的还有好几套。所以客观上这波房价如果真的把成都房价拉到一个历史新高,对我们来说至少在物质上不是什么坏事。但是作为一个骨子…
163 | - 安全感。 昨晚撑到下班,在办公室里披了两件毛衣还是冻得瑟瑟发抖,我知道我发烧了。(后来到家里量了一下体温确实高烧39度。) 下楼出了电梯,才发现外面居然在下大雨,寒风阵阵,从包里拿出雨伞走到车库,按了车钥匙他闪了两下灯,他就这样默默的等着我。…
164 | - 一个欧洲穷人(包括没有太多钱的年轻人)因为买不起经过精心雕琢的高级家具而退而求其次的品牌选择,中国留学生在国外出租屋内使用得起,国内小众并且可以装逼的知名品牌。 就这样一个玩意儿,被中国屌丝气息浓厚,视装逼成功为命的部分钱不多,又爱装的人…
165 | - 没结婚之前开摩托车 这车其实挺好的,带我跑了很多地方,除了下雨和去太远的地方不太方便 结婚了之后,我们这边的习俗是第一年过年要带老婆把所有的亲戚走一遍,太远,而且广东过年一般都下雨,路也不好,就借我叔(亲叔叔)的车,用了几天 这辆赛拉图才开…
166 | - 我是8月22被塞满的,瞬间反应是:我艹发财了!鸡冻的试看几部,哎呦不错哦!马上去某宝买了个不限速版本的云,火速安装,以8M/S的速度下载了一天两夜,我知道不抓紧很快他们就会“消失”,这恐怕是我经历过的最具有谍战特工窃密类似代入体验的人生经历了
167 | - Transfer learning 顾名思义就是就是把已学训练好的模型参数迁移到新的模型来帮助新模型训练数据集。就跟其他知友回答的那样,考虑到大部分数据或任务是存在相关性的,所以通过transfer learning我们可以将已经学到的parameter 分享给新模型从而加快并优化…
168 |
169 | - Facebook的开源基础库Folly(GitHub - facebook/folly: An open-source C++ library developed and used at Facebook.) 还是非常值得看的。这是Facebook内部广泛使用的可重复C++库组件大集合。也是最近几年C++领域难得的高质量库。 一方面,Folly直接采用C…
170 | - 先声明我是一贯反对川普的,特别是知乎川小将,但这件事上必须支持他了。 众所周知互联网发明于美国国防部,因此初期由美国政府管理天经地义。之后美国政府将位于美国根服务器和域名管理权移交给ICANN之后实际上没有在干涉过ICANN的实际运营,人类的信息产…
171 | - 成功的案例当然有啦 2016年初,参与央视《交换空间》节目,与原象设计师匹配的红队选手是一对夫妇。 而本次的设计风格,是炫原象设计机构炫彩波普风。 简单点来说,波普风非常年轻,而且强调色彩运用和图形,十分绚丽。 装修前的房子,比较普通。设计师十…
172 |
173 | GridActivity
174 | 点击查看
175 | MultiItemActivity
176 | StaggeredActivity
177 | ManualLoadMoreActivity
178 |
179 | 关闭NoMoreView
180 | 关闭LoadMoreView
181 | 关闭LoadMoreFailedView
182 | 开启自动加载
183 | 点击加载下一页
184 | ItemDragActivity
185 | aa
186 | 编辑
187 | 表格
188 | ExpandActivity
189 |
190 |
191 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/test/java/zlc/season/demo/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package zlc.season.demo;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.assertEquals;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/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.3'
9 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
10 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
11 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.6'
12 | // NOTE: Do not place your application dependencies here; they belong
13 | // in the individual module build.gradle files
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | jcenter()
20 | }
21 | }
22 |
23 | allprojects {
24 | tasks.withType(Javadoc) {
25 | options.addStringOption('Xdoclint:none', '-quiet')
26 | options.addStringOption('encoding', 'UTF-8')
27 | }
28 | }
29 |
30 | task clean(type: Delete) {
31 | delete rootProject.buildDir
32 | }
33 |
--------------------------------------------------------------------------------
/gif/GIF.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/gif/GIF.gif
--------------------------------------------------------------------------------
/gif/drag.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/gif/drag.gif
--------------------------------------------------------------------------------
/gif/expand.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/gif/expand.gif
--------------------------------------------------------------------------------
/gif/grid.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/gif/grid.gif
--------------------------------------------------------------------------------
/gif/manual.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/gif/manual.gif
--------------------------------------------------------------------------------
/gif/multiitem.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/gif/multiitem.gif
--------------------------------------------------------------------------------
/gif/stagger.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/gif/stagger.gif
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ssseasonnn/PracticalRecyclerView/12f9769cee18c2527018b6f37ae1ea6520335094/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Sep 21 11:20:48 CST 2016
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 |
--------------------------------------------------------------------------------
/practicalrecyclerview/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/practicalrecyclerview/bintray.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.github.dcendents.android-maven'
2 | apply plugin: 'com.jfrog.bintray'
3 |
4 | // This is the library version used when deploying the artifact
5 | version = "1.1.5"
6 |
7 | def siteUrl = 'https://github.com/ssseasonnn/PracticalRecyclerView' // 项目的主页
8 | def gitUrl = 'https://github.com/ssseasonnn/PracticalRecyclerView.git' // Git仓库的url
9 | group = "zlc.season" // Maven Group ID for the artifact,一般填你唯一的包名
10 |
11 | install {
12 | repositories.mavenInstaller {
13 | // This generates POM.xml with proper parameters
14 | pom {
15 | project {
16 | packaging 'aar'
17 | // Add your description here
18 | name 'practical recyclerview'
19 | url siteUrl
20 | // Set your license
21 | licenses {
22 | license {
23 | name 'The Apache Software License, Version 2.0'
24 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
25 | }
26 | }
27 | developers {
28 | developer {
29 | id 'Season.zlc' //填写的一些基本信息
30 | name 'Season.zlc'
31 | email 'ssseasonnn@gmail.com'
32 | }
33 | }
34 | scm {
35 | connection gitUrl
36 | developerConnection gitUrl
37 | url siteUrl
38 | }
39 | }
40 | }
41 | }
42 | }
43 | task sourcesJar(type: Jar) {
44 | from android.sourceSets.main.java.srcDirs
45 | classifier = 'sources'
46 | }
47 | task javadoc(type: Javadoc) {
48 | source = android.sourceSets.main.java.srcDirs
49 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
50 | }
51 | task javadocJar(type: Jar, dependsOn: javadoc) {
52 | classifier = 'javadoc'
53 | from javadoc.destinationDir
54 | }
55 | artifacts {
56 | archives javadocJar
57 | archives sourcesJar
58 | }
59 | Properties properties = new Properties()
60 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
61 | bintray {
62 | user = properties.getProperty("bintray.user")
63 | key = properties.getProperty("bintray.apikey")
64 | configurations = ['archives']
65 | pkg {
66 | repo = "android"
67 | name = "PracticalRecyclerView" //发布到JCenter上的项目名字
68 | websiteUrl = siteUrl
69 | vcsUrl = gitUrl
70 | licenses = ["Apache-2.0"]
71 | publish = true
72 | }
73 | }
74 | javadoc { //jav doc采用utf-8编码否则会报“GBK的不可映射字符”错误
75 | options{
76 | encoding "UTF-8"
77 | charSet 'UTF-8'
78 | }
79 | }
--------------------------------------------------------------------------------
/practicalrecyclerview/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.2"
6 |
7 | defaultConfig {
8 | minSdkVersion 11
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(include: ['*.jar'], dir: 'libs')
23 | testCompile 'junit:junit:4.12'
24 | compile 'com.android.support:appcompat-v7:25.1.0'
25 | compile 'com.android.support:recyclerview-v7:25.1.0'
26 | }
27 |
28 | apply from: "bintray.gradle"
--------------------------------------------------------------------------------
/practicalrecyclerview/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:\Application\Android-Sdk/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 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/androidTest/java/zlc/season/practicalrecyclerview/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package zlc.season.practicalrecyclerview;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/java/zlc/season/practicalrecyclerview/AbstractViewHolder.java:
--------------------------------------------------------------------------------
1 | package zlc.season.practicalrecyclerview;
2 |
3 | import android.support.annotation.LayoutRes;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | /**
10 | * Author: Season(ssseasonnn@gmail.com)
11 | * Date: 2016/9/21
12 | * Time: 14:35
13 | * FIXME
14 | */
15 | public abstract class AbstractViewHolder extends RecyclerView.ViewHolder {
16 |
17 | public AbstractViewHolder(View itemView) {
18 | super(itemView);
19 | }
20 |
21 | public AbstractViewHolder(ViewGroup parent, @LayoutRes int res) {
22 | super(LayoutInflater.from(parent.getContext()).inflate(res, parent, false));
23 | }
24 |
25 | public abstract void setData(T data);
26 | }
27 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/java/zlc/season/practicalrecyclerview/Bridge.java:
--------------------------------------------------------------------------------
1 | package zlc.season.practicalrecyclerview;
2 |
3 | /**
4 | * Author: Season(ssseasonnn@gmail.com)
5 | * Date: 2016/9/28
6 | * Time: 14:35
7 | * FIXME
8 | */
9 | interface Bridge {
10 | void doSomething(PracticalRecyclerView host);
11 |
12 | class Loading implements Bridge {
13 |
14 | @Override
15 | public void doSomething(PracticalRecyclerView host) {
16 | host.displayLoadingAndResetStatus();
17 | }
18 | }
19 |
20 | class Empty implements Bridge {
21 |
22 | @Override
23 | public void doSomething(PracticalRecyclerView host) {
24 | host.displayEmptyAndResetStatus();
25 | }
26 | }
27 |
28 | class Content implements Bridge {
29 |
30 | @Override
31 | public void doSomething(PracticalRecyclerView host) {
32 | host.displayContentAndResetStatus();
33 | }
34 | }
35 |
36 | class Error implements Bridge {
37 |
38 | @Override
39 | public void doSomething(PracticalRecyclerView host) {
40 | host.displayErrorAndResetStatus();
41 | }
42 | }
43 |
44 | class NoMore implements Bridge {
45 |
46 | @Override
47 | public void doSomething(PracticalRecyclerView host) {
48 | host.showNoMoreIfEnabled();
49 | }
50 | }
51 |
52 | class LoadMoreFailed implements Bridge {
53 |
54 | @Override
55 | public void doSomething(PracticalRecyclerView host) {
56 | host.showLoadMoreFailedIfEnabled();
57 | }
58 | }
59 |
60 | class ResumeLoadMore implements Bridge {
61 |
62 | @Override
63 | public void doSomething(PracticalRecyclerView host) {
64 | host.resumeLoadMoreIfEnabled();
65 | }
66 | }
67 |
68 | class AutoLoadMore implements Bridge {
69 |
70 | @Override
71 | public void doSomething(PracticalRecyclerView host) {
72 | host.autoLoadMoreIfEnabled();
73 | }
74 | }
75 |
76 | class ManualLoadMore implements Bridge {
77 |
78 | @Override
79 | public void doSomething(PracticalRecyclerView host) {
80 | host.manualLoadMoreIfEnabled();
81 | }
82 | }
83 |
84 | class SwipeConflicts implements Bridge {
85 |
86 | private boolean enabled;
87 |
88 | SwipeConflicts(boolean enabled) {
89 | this.enabled = enabled;
90 | }
91 |
92 | @Override
93 | public void doSomething(PracticalRecyclerView host) {
94 | host.resolveSwipeConflicts(enabled);
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/java/zlc/season/practicalrecyclerview/Configure.java:
--------------------------------------------------------------------------------
1 | package zlc.season.practicalrecyclerview;
2 |
3 | import android.view.View;
4 |
5 | /**
6 | * Author: Season(ssseasonnn@gmail.com)
7 | * Date: 2016/9/26
8 | * Time: 15:05
9 | * FIXME
10 | */
11 | public interface Configure {
12 | void configureEmptyView(View emptyView);
13 |
14 | void configureErrorView(View errorView);
15 |
16 | void configureLoadingView(View loadingView);
17 |
18 | void configureLoadMoreView(View loadMoreView);
19 |
20 | void configureNoMoreView(View noMoreView);
21 |
22 | void configureLoadMoreFailedView(View loadMoreFailedView);
23 | }
24 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/java/zlc/season/practicalrecyclerview/ConfigureAdapter.java:
--------------------------------------------------------------------------------
1 | package zlc.season.practicalrecyclerview;
2 |
3 | import android.view.View;
4 |
5 | /**
6 | * Author: Season(ssseasonnn@gmail.com)
7 | * Date: 2016/9/26
8 | * Time: 15:11
9 | * FIXME
10 | */
11 | public abstract class ConfigureAdapter implements Configure {
12 |
13 | @Override
14 | public void configureEmptyView(View emptyView) {
15 |
16 | }
17 |
18 | @Override
19 | public void configureErrorView(View errorView) {
20 |
21 | }
22 |
23 | @Override
24 | public void configureLoadingView(View loadingView) {
25 |
26 | }
27 |
28 | @Override
29 | public void configureLoadMoreView(View loadMoreView) {
30 |
31 | }
32 |
33 | @Override
34 | public void configureNoMoreView(View noMoreView) {
35 |
36 | }
37 |
38 | @Override
39 | public void configureLoadMoreFailedView(View loadMoreFailedView) {
40 |
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/java/zlc/season/practicalrecyclerview/ItemType.java:
--------------------------------------------------------------------------------
1 | package zlc.season.practicalrecyclerview;
2 |
3 | /**
4 | * Author: Season(ssseasonnn@gmail.com)
5 | * Date: 2016/9/21
6 | * Time: 15:10
7 | * FIXME
8 | */
9 | public interface ItemType {
10 | int itemType();
11 | }
12 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/java/zlc/season/practicalrecyclerview/SectionItem.java:
--------------------------------------------------------------------------------
1 | package zlc.season.practicalrecyclerview;
2 |
3 | import android.view.View;
4 | import android.view.ViewGroup;
5 |
6 | /**
7 | * Author: Season(ssseasonnn@gmail.com)
8 | * Date: 2016/9/22
9 | * Time: 15:33
10 | * FIXME
11 | */
12 | public interface SectionItem {
13 |
14 | View createView(ViewGroup parent);
15 |
16 | void onBind();
17 | }
18 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/java/zlc/season/practicalrecyclerview/SectionItemImpl.java:
--------------------------------------------------------------------------------
1 | package zlc.season.practicalrecyclerview;
2 |
3 | import android.view.View;
4 | import android.view.ViewGroup;
5 |
6 | /**
7 | * Author: Season(ssseasonnn@gmail.com)
8 | * Date: 2016/9/27
9 | * Time: 17:01
10 | * FIXME
11 | */
12 | public class SectionItemImpl implements SectionItem {
13 |
14 | private View mView;
15 |
16 | public SectionItemImpl() {
17 | }
18 |
19 | public SectionItemImpl(View view) {
20 | mView = view;
21 | }
22 |
23 | @Override
24 | public View createView(ViewGroup parent) {
25 | return mView;
26 | }
27 |
28 | @Override
29 | public void onBind() {
30 |
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/java/zlc/season/practicalrecyclerview/SimpleItemTouchHelperCallback.java:
--------------------------------------------------------------------------------
1 | package zlc.season.practicalrecyclerview;
2 |
3 | import android.support.v7.widget.GridLayoutManager;
4 | import android.support.v7.widget.LinearLayoutManager;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.support.v7.widget.helper.ItemTouchHelper;
7 |
8 | /**
9 | * Author: Season(ssseasonnn@gmail.com)
10 | * Date: 2016/10/12
11 | * Time: 10:28
12 | * FIXME
13 | */
14 | public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
15 |
16 | private boolean isLongPressDragEnabled;
17 | private boolean isSwipeEnabled;
18 | private AbstractAdapter mAdapter;
19 |
20 | /**
21 | * SimpleItemTouchHelperCallback
22 | *
23 | * @param isLongPressDragEnabled 是否启用默认的长按拖动
24 | * @param isSwipeEnabled 是否启用默认的滑动删除
25 | */
26 | public SimpleItemTouchHelperCallback(boolean isLongPressDragEnabled, boolean isSwipeEnabled) {
27 | this.isLongPressDragEnabled = isLongPressDragEnabled;
28 | this.isSwipeEnabled = isSwipeEnabled;
29 | }
30 |
31 | @Override
32 | public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
33 | if (!(recyclerView.getAdapter() instanceof AbstractAdapter)) {
34 | return 0;
35 | }
36 |
37 | mAdapter = (AbstractAdapter) recyclerView.getAdapter();
38 | int currentPosition = viewHolder.getAdapterPosition();
39 | if (!mAdapter.canDrag(currentPosition)) {
40 | return 0;
41 | }
42 |
43 | int dragFlags;
44 | int swipeFlags;
45 | RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
46 | if (layoutManager instanceof GridLayoutManager) {
47 | dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
48 | swipeFlags = 0;
49 | } else if (layoutManager instanceof LinearLayoutManager) {
50 | dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
51 | swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
52 | } else {
53 | dragFlags = 0;
54 | swipeFlags = 0;
55 | }
56 |
57 | return makeMovementFlags(dragFlags, swipeFlags);
58 | }
59 |
60 |
61 | @Override
62 | public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
63 | RecyclerView.ViewHolder target) {
64 | if (!mAdapter.canDrag(viewHolder.getAdapterPosition()) || !mAdapter.canDrag(target.getAdapterPosition())) {
65 | return true;
66 | }
67 | mAdapter.swap(viewHolder.getAdapterPosition(), target.getAdapterPosition());
68 | return true;
69 | }
70 |
71 | @Override
72 | public boolean isLongPressDragEnabled() {
73 | return isLongPressDragEnabled;
74 | }
75 |
76 | @Override
77 | public boolean isItemViewSwipeEnabled() {
78 | return isSwipeEnabled;
79 | }
80 |
81 | @Override
82 | public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
83 | if (!mAdapter.canDrag(viewHolder.getAdapterPosition())) {
84 | return;
85 | }
86 | mAdapter.remove(viewHolder.getAdapterPosition());
87 | }
88 |
89 | @Override
90 | public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
91 | super.onSelectedChanged(viewHolder, actionState);
92 | final boolean enabled = !(actionState == ItemTouchHelper.ACTION_STATE_DRAG ||
93 | actionState == ItemTouchHelper.ACTION_STATE_SWIPE);
94 | mAdapter.resolveSwipeConflicts(enabled);
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/java/zlc/season/practicalrecyclerview/decoration/DividerItemDecoration.java:
--------------------------------------------------------------------------------
1 | package zlc.season.practicalrecyclerview.decoration;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.content.res.TypedArray;
6 | import android.graphics.Canvas;
7 | import android.graphics.Rect;
8 | import android.graphics.drawable.Drawable;
9 | import android.support.annotation.NonNull;
10 | import android.support.v4.view.ViewCompat;
11 | import android.support.v7.widget.RecyclerView;
12 | import android.view.View;
13 | import android.widget.LinearLayout;
14 |
15 | import zlc.season.practicalrecyclerview.AbstractAdapter;
16 |
17 | /**
18 | * Author: Season(ssseasonnn@gmail.com)
19 | * Date: 2017/1/10
20 | * FIXME
21 | */
22 | public class DividerItemDecoration extends RecyclerView.ItemDecoration {
23 |
24 | public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
25 | public static final int VERTICAL = LinearLayout.VERTICAL;
26 | private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
27 | private final Rect mBounds = new Rect();
28 | private Drawable mDivider;
29 | /**
30 | * Current orientation. Either {@link #HORIZONTAL} or {@link #VERTICAL}.
31 | */
32 | private int mOrientation;
33 |
34 | /**
35 | * Creates a divider {@link android.support.v7.widget.RecyclerView.ItemDecoration} that can be
36 | * used with a
37 | * {@link android.support.v7.widget.LinearLayoutManager}.
38 | *
39 | * @param context Current context, it will be used to access resources.
40 | * @param orientation Divider orientation. Should be {@link #HORIZONTAL} or
41 | * {@link #VERTICAL}.
42 | */
43 | public DividerItemDecoration(Context context, int orientation) {
44 | final TypedArray a = context.obtainStyledAttributes(ATTRS);
45 | mDivider = a.getDrawable(0);
46 | a.recycle();
47 | setOrientation(orientation);
48 | }
49 |
50 | /**
51 | * Sets the orientation for this divider. This should be called if
52 | * {@link android.support.v7.widget.RecyclerView.LayoutManager} changes orientation.
53 | *
54 | * @param orientation {@link #HORIZONTAL} or {@link #VERTICAL}
55 | */
56 | public void setOrientation(int orientation) {
57 | if (orientation != HORIZONTAL && orientation != VERTICAL) {
58 | throw new IllegalArgumentException(
59 | "Invalid orientation. It should be either HORIZONTAL or VERTICAL");
60 | }
61 | mOrientation = orientation;
62 | }
63 |
64 | /**
65 | * Sets the {@link android.graphics.drawable.Drawable} for this divider.
66 | *
67 | * @param drawable Drawable that should be used as a divider.
68 | */
69 | public void setDrawable(@NonNull Drawable drawable) {
70 | mDivider = drawable;
71 | }
72 |
73 | @Override
74 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
75 | if (parent.getLayoutManager() == null) {
76 | return;
77 | }
78 | if (mOrientation == VERTICAL) {
79 | drawVertical(c, parent);
80 | } else {
81 | drawHorizontal(c, parent);
82 | }
83 | }
84 |
85 | @SuppressLint("NewApi")
86 | private void drawVertical(Canvas canvas, RecyclerView parent) {
87 | canvas.save();
88 | final int left;
89 | final int right;
90 | if (parent.getClipToPadding()) {
91 | left = parent.getPaddingLeft();
92 | right = parent.getWidth() - parent.getPaddingRight();
93 | canvas.clipRect(left, parent.getPaddingTop(), right,
94 | parent.getHeight() - parent.getPaddingBottom());
95 | } else {
96 | left = 0;
97 | right = parent.getWidth();
98 | }
99 |
100 | final int childCount = parent.getChildCount();
101 | AbstractAdapter adapter = (AbstractAdapter) parent.getAdapter();
102 |
103 | for (int i = 0; i < childCount; i++) {
104 | final View child = parent.getChildAt(i);
105 | final int position = parent.getChildAdapterPosition(child);
106 | if (adapter.isData(position)) {
107 | drawDividerVertical(canvas, parent, left, right, i);
108 | }
109 | }
110 | canvas.restore();
111 | }
112 |
113 | @SuppressLint("NewApi")
114 | private void drawHorizontal(Canvas canvas, RecyclerView parent) {
115 | canvas.save();
116 | final int top;
117 | final int bottom;
118 | if (parent.getClipToPadding()) {
119 | top = parent.getPaddingTop();
120 | bottom = parent.getHeight() - parent.getPaddingBottom();
121 | canvas.clipRect(parent.getPaddingLeft(), top,
122 | parent.getWidth() - parent.getPaddingRight(), bottom);
123 | } else {
124 | top = 0;
125 | bottom = parent.getHeight();
126 | }
127 |
128 | final int childCount = parent.getChildCount();
129 | AbstractAdapter adapter = (AbstractAdapter) parent.getAdapter();
130 |
131 | for (int i = 0; i < childCount; i++) {
132 | final View child = parent.getChildAt(i);
133 | final int position = parent.getChildAdapterPosition(child);
134 | if (adapter.isData(position)) {
135 | drawDividerHorizontal(canvas, parent, top, bottom, i);
136 | }
137 | }
138 | canvas.restore();
139 | }
140 |
141 | private void drawDividerVertical(Canvas canvas, RecyclerView parent, int left, int right,
142 | int i) {
143 | final View child = parent.getChildAt(i);
144 | parent.getDecoratedBoundsWithMargins(child, mBounds);
145 | final int bottom = mBounds.bottom +
146 | Math.round(ViewCompat.getTranslationY(child));
147 | final int top = bottom - mDivider.getIntrinsicHeight();
148 | mDivider.setBounds(left, top, right, bottom);
149 | mDivider.draw(canvas);
150 | }
151 |
152 | private void drawDividerHorizontal(Canvas canvas, RecyclerView parent, int top, int bottom,
153 | int i) {
154 | final View child = parent.getChildAt(i);
155 | parent.getLayoutManager().getDecoratedBoundsWithMargins(child, mBounds);
156 | final int right = mBounds.right + Math.round(ViewCompat.getTranslationX(child));
157 | final int left = right - mDivider.getIntrinsicWidth();
158 | mDivider.setBounds(left, top, right, bottom);
159 | mDivider.draw(canvas);
160 | }
161 |
162 | @Override
163 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
164 | RecyclerView.State state) {
165 | int position = parent.getChildAdapterPosition(view);
166 | AbstractAdapter adapter = (AbstractAdapter) parent.getAdapter();
167 | if (adapter.isData(position)) {
168 | getItemOffset(outRect);
169 | }
170 | }
171 |
172 | private void getItemOffset(Rect outRect) {
173 | if (mOrientation == VERTICAL) {
174 | outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
175 | } else {
176 | outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
177 | }
178 | }
179 | }
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/java/zlc/season/practicalrecyclerview/decoration/ShadowItemDecoration.java:
--------------------------------------------------------------------------------
1 | package zlc.season.practicalrecyclerview.decoration;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.graphics.Canvas;
6 | import android.graphics.Rect;
7 | import android.graphics.drawable.ColorDrawable;
8 | import android.support.annotation.ColorRes;
9 | import android.support.v4.content.ContextCompat;
10 | import android.support.v7.widget.RecyclerView;
11 | import android.view.View;
12 | import android.widget.LinearLayout;
13 |
14 | import zlc.season.practicalrecyclerview.AbstractAdapter;
15 |
16 | /**
17 | * Author: Season(ssseasonnn@gmail.com)
18 | * Date: 2017/1/10
19 | * FIXME
20 | */
21 | public class ShadowItemDecoration extends RecyclerView.ItemDecoration {
22 |
23 | public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
24 | public static final int VERTICAL = LinearLayout.VERTICAL;
25 |
26 | private final Rect mBounds = new Rect();
27 |
28 | private Context mContext;
29 | private ColorDrawable mShadowColor;
30 | private PositionStrategy mStrategy;
31 | /**
32 | * Current orientation. Either {@link #HORIZONTAL} or {@link #VERTICAL}.
33 | */
34 | private int mOrientation;
35 |
36 | /**
37 | * Creates a divider {@link android.support.v7.widget.RecyclerView.ItemDecoration} that can be
38 | * used with a
39 | * {@link android.support.v7.widget.LinearLayoutManager}.
40 | *
41 | * @param context Current context, it will be used to access resources.
42 | * @param orientation Divider orientation. Should be {@link #HORIZONTAL} or
43 | * {@link #VERTICAL}.
44 | */
45 | public ShadowItemDecoration(Context context, int orientation, @ColorRes int color,
46 | PositionStrategy strategy) {
47 | setOrientation(orientation);
48 | mShadowColor = new ColorDrawable(ContextCompat.getColor(context, color));
49 | mContext = context;
50 | this.mStrategy = strategy;
51 | }
52 |
53 | /**
54 | * Set the shadow color
55 | *
56 | * @param color color res
57 | */
58 | public void setShadowColor(@ColorRes int color) {
59 | this.mShadowColor = new ColorDrawable(ContextCompat.getColor(mContext, color));
60 | }
61 |
62 | /**
63 | * Sets the orientation for this divider. This should be called if
64 | * {@link android.support.v7.widget.RecyclerView.LayoutManager} changes orientation.
65 | *
66 | * @param orientation {@link #HORIZONTAL} or {@link #VERTICAL}
67 | */
68 | public void setOrientation(int orientation) {
69 | if (orientation != HORIZONTAL && orientation != VERTICAL) {
70 | throw new IllegalArgumentException(
71 | "Invalid orientation. It should be either HORIZONTAL or VERTICAL");
72 | }
73 | mOrientation = orientation;
74 | }
75 |
76 | public void setStrategy(PositionStrategy mStrategy) {
77 | this.mStrategy = mStrategy;
78 | }
79 |
80 | @Override
81 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
82 | if (parent.getLayoutManager() == null) {
83 | return;
84 | }
85 | if (mOrientation == VERTICAL) {
86 | drawVertical(c, parent);
87 | } else {
88 | drawHorizontal(c, parent);
89 | }
90 | }
91 |
92 | @SuppressLint("NewApi")
93 | private void drawVertical(Canvas canvas, RecyclerView parent) {
94 | canvas.save();
95 | final int left;
96 | final int right;
97 | if (parent.getClipToPadding()) {
98 | left = parent.getPaddingLeft();
99 | right = parent.getWidth() - parent.getPaddingRight();
100 | canvas.clipRect(left, parent.getPaddingTop(), right,
101 | parent.getHeight() - parent.getPaddingBottom());
102 | } else {
103 | left = 0;
104 | right = parent.getWidth();
105 | }
106 |
107 | final int childCount = parent.getChildCount();
108 | AbstractAdapter adapter = (AbstractAdapter) parent.getAdapter();
109 |
110 | for (int i = 0; i < childCount; i++) {
111 | final View child = parent.getChildAt(i);
112 | final int position = parent.getChildAdapterPosition(child);
113 | final int headerSize = adapter.getHeaderSize();
114 |
115 | if (adapter.isData(position)) {
116 | if (mStrategy.strategy(position - headerSize)) {
117 | parent.getDecoratedBoundsWithMargins(child, mBounds);
118 | final int bottom = child.getBottom();
119 | final int top = child.getTop();
120 | mShadowColor.setBounds(left, top, right, bottom);
121 | mShadowColor.draw(canvas);
122 | }
123 | }
124 | }
125 | canvas.restore();
126 | }
127 |
128 | @SuppressLint("NewApi")
129 | private void drawHorizontal(Canvas canvas, RecyclerView parent) {
130 | canvas.save();
131 | final int top;
132 | final int bottom;
133 | if (parent.getClipToPadding()) {
134 | top = parent.getPaddingTop();
135 | bottom = parent.getHeight() - parent.getPaddingBottom();
136 | canvas.clipRect(parent.getPaddingLeft(), top,
137 | parent.getWidth() - parent.getPaddingRight(), bottom);
138 | } else {
139 | top = 0;
140 | bottom = parent.getHeight();
141 | }
142 |
143 | final int childCount = parent.getChildCount();
144 | AbstractAdapter adapter = (AbstractAdapter) parent.getAdapter();
145 |
146 | for (int i = 0; i < childCount; i++) {
147 | final View child = parent.getChildAt(i);
148 | final int position = parent.getChildAdapterPosition(child);
149 | final int headerSize = adapter.getHeaderSize();
150 |
151 | if (adapter.isData(position)) {
152 | if (mStrategy.strategy(position - headerSize)) {
153 | parent.getDecoratedBoundsWithMargins(child, mBounds);
154 | final int right = mBounds.right;
155 | final int left = mBounds.left;
156 | mShadowColor.setBounds(left, top, right, bottom);
157 | mShadowColor.draw(canvas);
158 | }
159 | }
160 | }
161 | canvas.restore();
162 | }
163 |
164 | @Override
165 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
166 | RecyclerView.State state) {
167 | outRect.setEmpty();
168 | }
169 |
170 | /**
171 | * Decide which position should be draw shadow.
172 | */
173 | public interface PositionStrategy {
174 | boolean strategy(int position);
175 | }
176 | }
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/res/layout/default_empty_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/res/layout/default_error_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/res/layout/default_load_more_failed_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/res/layout/default_load_more_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/res/layout/default_loading_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
12 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/res/layout/default_no_more_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/res/layout/recycler_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
16 |
17 |
18 |
23 |
24 |
25 |
30 |
31 |
32 |
37 |
38 |
43 |
44 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/res/values/attr.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SuperRecycler
3 | 没有数据
4 | 网络连接失败,请点击重试
5 | -----我是有底线的-----
6 | 加载失败, 点击重试
7 | 加载中…
8 |
9 |
--------------------------------------------------------------------------------
/practicalrecyclerview/src/test/java/zlc/season/practicalrecyclerview/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package zlc.season.practicalrecyclerview;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/practicalrecyclerview/src/test/java/zlc/season/practicalrecyclerview/SegmentTest.java:
--------------------------------------------------------------------------------
1 | package zlc.season.practicalrecyclerview;
2 |
3 | /**
4 | * Author: Season(ssseasonnn@gmail.com)
5 | * Date: 2016/9/30
6 | * Time: 11:32
7 | * FIXME
8 | */
9 | public class SegmentTest {
10 |
11 | private DataSetObservable dataSet;
12 |
13 | @org.junit.Before
14 | public void setUp() throws Exception {
15 | dataSet = new DataSetObservable();
16 | }
17 |
18 | @org.junit.After
19 | public void tearDown() throws Exception {
20 |
21 | }
22 |
23 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':practicalrecyclerview'
2 |
--------------------------------------------------------------------------------