├── .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 | [![Download](https://api.bintray.com/packages/ssseasonnn/android/PracticalRecyclerView/images/download.svg)](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> 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 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> 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> 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> 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> 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> 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 |