├── .gitignore
├── .idea
├── assetWizardSettings.xml
├── caches
│ └── build_file_checksums.ser
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── gradle.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── jarRepositories.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── baozi
│ │ └── treerecyclerview
│ │ └── ApplicationTest.java
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── baozi
│ │ └── treerecyclerview
│ │ ├── adpater
│ │ ├── TreeRecyclerAdapter.java
│ │ ├── TreeRecyclerType.java
│ │ └── wrapper
│ │ │ ├── BaseWrapper.java
│ │ │ ├── HeaderWrapper.java
│ │ │ ├── LoadingWrapper.java
│ │ │ ├── SwipeWrapper.java
│ │ │ └── TreeLoadWrapper.java
│ │ ├── annotation
│ │ ├── TreeDataType.java
│ │ └── TreeItemType.java
│ │ ├── base
│ │ ├── BaseRecyclerAdapter.java
│ │ └── ViewHolder.java
│ │ ├── factory
│ │ ├── ItemConfig.java
│ │ └── ItemHelperFactory.java
│ │ ├── item
│ │ ├── SimpleTreeItem.java
│ │ ├── SwipeItem.java
│ │ ├── TreeItem.java
│ │ ├── TreeItemGroup.java
│ │ ├── TreeSelectItemGroup.java
│ │ └── TreeSortItem.java
│ │ ├── manager
│ │ ├── ItemManageImpl.java
│ │ └── ItemManager.java
│ │ └── widget
│ │ ├── DragSelectRecyclerAdapter.java
│ │ ├── DragSelectRecyclerView.java
│ │ ├── TreeSortAdapter.java
│ │ └── swipe
│ │ ├── SwipeItemMangerInterface.java
│ │ ├── SwipeLayout.java
│ │ └── SwipeMode.java
│ └── res
│ └── values
│ ├── attr.xml
│ └── values.xml
├── build.gradle
├── demo
├── .gitignore
├── build.gradle
├── libs
│ └── fastjson-1.2.9.jar
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── baozi
│ │ └── demo
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── assets
│ │ ├── city.txt
│ │ └── test.html
│ ├── java
│ │ └── com
│ │ │ └── baozi
│ │ │ └── demo
│ │ │ ├── activity
│ │ │ ├── CartAt.java
│ │ │ ├── CityAt.java
│ │ │ ├── MainActivity.java
│ │ │ ├── SortAt.java
│ │ │ ├── SwipeSortAt.java
│ │ │ ├── TBActivity.java
│ │ │ └── TestActivity.kt
│ │ │ ├── fragment
│ │ │ ├── ClickLoadFg.java
│ │ │ ├── GalleryFg.java
│ │ │ ├── MineFg.java
│ │ │ ├── NewsFg.java
│ │ │ └── SimpleRecyclerViewFg.java
│ │ │ └── item
│ │ │ ├── cart
│ │ │ ├── CartBean.java
│ │ │ ├── CartGroupItem.java
│ │ │ ├── CartGroupItem2.java
│ │ │ ├── CartGroupItem3.java
│ │ │ └── CartItem.java
│ │ │ ├── city
│ │ │ ├── AreaItem.java
│ │ │ ├── CountyItem.java
│ │ │ ├── ProvinceBean.java
│ │ │ └── ProvinceItem.java
│ │ │ ├── clickload
│ │ │ ├── ClickLoadChildItem.java
│ │ │ └── ClickLoadGroupItem.java
│ │ │ ├── mine
│ │ │ ├── MineCategoryBean.java
│ │ │ ├── MineCategoryItem.java
│ │ │ ├── MineHeadItem.java
│ │ │ └── MineItem.java
│ │ │ ├── news
│ │ │ ├── NewsImageItem.java
│ │ │ ├── NewsItem.java
│ │ │ └── NewsItemBean.java
│ │ │ ├── sort
│ │ │ ├── IndexBar.java
│ │ │ ├── SortChildItem.java
│ │ │ └── SortGroupItem.java
│ │ │ ├── swipe
│ │ │ └── SwipeSortItem.java
│ │ │ └── tbhome
│ │ │ ├── GoodsItem.java
│ │ │ ├── HomeCategoryItem.java
│ │ │ ├── HomeItemA.java
│ │ │ ├── HomeItemB.java
│ │ │ ├── HomeItemC.java
│ │ │ ├── HomeItemD.java
│ │ │ ├── HomeItemE.java
│ │ │ └── HomeItemF.java
│ └── res
│ │ ├── drawable
│ │ ├── bg_title.xml
│ │ ├── ic_keyboard_arrow_down_black_24dp.xml
│ │ ├── ic_keyboard_arrow_right_black_24dp.xml
│ │ ├── ic_person_black_24dp.xml
│ │ ├── ic_photo_24dp.xml
│ │ └── shape_radius30_stroke1_gray_333.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── activity_shopping_cart.xml
│ │ ├── activity_sort.xml
│ │ ├── activity_tb_home.xml
│ │ ├── at_test.xml
│ │ ├── item_brand_title.xml
│ │ ├── item_cart_child.xml
│ │ ├── item_cart_group.xml
│ │ ├── item_grallery.xml
│ │ ├── item_image.xml
│ │ ├── item_mine.xml
│ │ ├── item_mine_category.xml
│ │ ├── item_mine_head.xml
│ │ ├── item_news_foot.xml
│ │ ├── item_news_image.xml
│ │ ├── item_news_title.xml
│ │ ├── item_sort_child.xml
│ │ ├── item_sort_group.xml
│ │ ├── item_tb_goods.xml
│ │ ├── item_tb_home_a.xml
│ │ ├── item_tb_home_b.xml
│ │ ├── item_tb_home_c.xml
│ │ ├── item_tb_home_d.xml
│ │ ├── item_tb_home_e.xml
│ │ ├── item_tb_home_f.xml
│ │ ├── item_test_group.xml
│ │ ├── item_three.xml
│ │ ├── item_two.xml
│ │ ├── itme_one.xml
│ │ ├── layout_delete.xml
│ │ ├── layout_empty.xml
│ │ ├── layout_loading.xml
│ │ └── layout_rv_content.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── baozi
│ └── demo
│ └── ExampleUnitTest.java
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── image
├── 20180928114547.png
├── 20180928114623.png
├── 20180928114648.png
├── 20180928120846.png
├── 20180928120934.png
├── 20180928145931.png
└── wx.jpg
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | /.idea/
10 |
--------------------------------------------------------------------------------
/.idea/assetWizardSettings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
51 |
52 |
--------------------------------------------------------------------------------
/.idea/caches/build_file_checksums.ser:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jlanglang/TreeRecyclerView/6f454078ecd9f05619bb1d44b282d6d758f7ffeb/.idea/caches/build_file_checksums.ser
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | xmlns:android
11 |
12 | ^$
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | xmlns:.*
22 |
23 | ^$
24 |
25 |
26 | BY_NAME
27 |
28 |
29 |
30 |
31 |
32 |
33 | .*:id
34 |
35 | http://schemas.android.com/apk/res/android
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | .*:name
45 |
46 | http://schemas.android.com/apk/res/android
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | name
56 |
57 | ^$
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | style
67 |
68 | ^$
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | .*
78 |
79 | ^$
80 |
81 |
82 | BY_NAME
83 |
84 |
85 |
86 |
87 |
88 |
89 | .*
90 |
91 | http://schemas.android.com/apk/res/android
92 |
93 |
94 | ANDROID_ATTRIBUTE_ORDER
95 |
96 |
97 |
98 |
99 |
100 |
101 | .*
102 |
103 | .*
104 |
105 |
106 | BY_NAME
107 |
108 |
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 2021-3-7更新
2 |
3 | 1.优化了获取注解的逻辑,减少了读取class的注解的次数
4 |
5 | 2.ItemManager新增了setTag.getTag方法,可以通过该方法绑定Activity或者Fragment等对象.在TreeItem可以获取该对象
6 |
7 | 3.TreeItem新增了init方法,可以做一些初始化设置,比如默认是否展开等等
8 |
9 | 4.新增了getItemOffsets的重写函数,与ItemDecoration接口保持一致(旧的方法依旧保留)
10 |
11 |
12 |
13 | # 更新
14 |
15 | 新增androidx分支.转换支持androidX
16 | 版本号:v1.3.1-androidx
17 |
18 | 新增Kotlin版本分支.
19 | 版本号v1.3.1-kt
20 |
21 |
22 | [](https://github.com/996icu/996.ICU/blob/master/LICENSE)
23 |
24 | # 特点
25 |
26 | ```
27 | 1.支持实现树形结构列表及大部分列表样式
28 | 2.每一种条目的逻辑独立,充分解耦,支持复用
29 | 3.支持组件化
30 | 4.支持服务器动态下发,动态组合
31 | 5.侵入性低,不修改RecyclerView原有特性
32 | ```
33 |
34 |
35 | # 示例图:
36 |
37 | 
38 | 
39 | 
40 | 
41 | 
42 | 
43 | ##### 以上示例都只使用了一个RecyclerView,没有嵌套
44 |
45 |
46 | # 依赖方式
47 | ```
48 | implementation 'com.github.Jlanglang:TreeRecyclerView:1.3.1.1'
49 | ```
50 | 根build.gradle里面添加
51 | ```
52 | repositories {
53 | maven { url 'https://jitpack.io' }
54 | }
55 | ```
56 |
57 | ---
58 |
59 |
60 | # 如何使用:
61 |
62 | ## 一.你需要创建一个adapter:
63 | ```
64 | //可折叠
65 | TreeRecyclerAdapter treeRecyclerAdapter = new TreeRecyclerAdapter(TreeRecyclerType.SHOW_EXPAND);
66 | ```
67 |
68 | ## 二.你需要选择一种展开方式
69 | ```
70 | public enum TreeRecyclerType {
71 | /**
72 | * 显示所有,不可展开折叠
73 | * 适用场景,不需要折叠,默认显示所有item
74 | */
75 | SHOW_ALL,
76 |
77 | /**
78 | * 根据isExpand的状态显示展开与折叠,
79 | * 适用场景,多级的data数据展示,保存展开状态
80 | */
81 | SHOW_EXPAND,
82 |
83 | /**
84 | * 默认只显示第一级,点击展开,折叠不会影响子级展开折叠
85 | * 适用场景,一级一级展开,保存展开状态
86 | */
87 | SHOW_DEFAULT
88 | }
89 | ```
90 |
91 | 构造函数传入,不传默认则使用`SHOW_DEFAULT`.
92 |
93 | # 三.怎么写Item
94 |
95 | 注意! 使用这个,没有写`ViewHolder`的概念,只有`TreeItem`和`TreeItemGroup`.子级和父级.
96 |
97 | #### 父级示例:
98 | ```
99 | /**
100 | * 城市
101 | */
102 | public class CountyItemParent extends TreeItemGroup {//泛型代表绑定的javabean
103 |
104 | //创建子TreeItem.
105 | @Override
106 | public List initChildList(ProvinceBean.CityBean data) {
107 | return ItemHelperFactory.createItems(data.getAreas(), this);
108 | }
109 |
110 | //该级具体展示的Layout
111 | @Override
112 | public int getLayoutId() {
113 | return R.layout.item_two;
114 | }
115 |
116 | //view和data绑定
117 | @Override
118 | public void onBindViewHolder(@NonNull ViewHolder holder) {
119 | holder.setText(R.id.tv_content, data.getCityName());
120 | }
121 | }
122 | ```
123 |
124 |
125 | #### 子级示例:
126 | ```
127 | /**
128 | * 县
129 | */
130 | public class AreaItem extends TreeItem {//泛型代表绑定的javabean
131 |
132 | @Override
133 | public int getLayoutId() {
134 | return R.layout.item_three;
135 | }
136 | //绑定操作,
137 | @Override
138 | public void onBindViewHolder(@NonNull ViewHolder holder) {
139 | holder.setText(R.id.tv_content, data.getAreaName());
140 | }
141 | //这个Item,在RecyclerView的每行所占比,只有RecyclerView设置了GridLayoutManager才会生效.
142 | //这里之所以用除法,是为了可以做到,只改变GridLayoutManager的总数,无需改变每个Item,当然也可以直接返回一个int值.
143 | @Override
144 | public int getSpanSize(int maxSpan) {
145 | return maxSpan / 6;
146 | }
147 | }
148 |
149 | ```
150 |
151 | # 怎么创建Item:
152 |
153 | 有两种方法:
154 |
155 | #### 第一种:
156 |
157 | 在javabean上使用注解,
158 | ```
159 | @TreeDataType(iClass = AreaItem.class)
160 | public class AreasBean{
161 | ...
162 | }
163 | ```
164 | 然后传入bean对象
165 | ```
166 | ItemHelperFactory.createItems(list, treeItemGroup);
167 | ```
168 |
169 | #### 第二种:
170 |
171 | 直接传入bean对象和item的class,
172 | ```
173 | ItemHelperFactory.createItems(list, Item.class, treeItemGroup);
174 | ```
175 |
176 | ---
177 |
178 | # 四.如何更新adapter:
179 |
180 | 增删该查都有.
181 |
182 | ```
183 | treeRecyclerAdapter.getItemManager().replaceAllItem(items);// 替换全部Item
184 | treeRecyclerAdapter.getItemManager().addItems(items);// 添加一组Item
185 | treeRecyclerAdapter.getItemManager().removeItems(items);// 添加一组Item
186 | ```
187 |
188 | #### 在item里面也是可以更新的:
189 |
190 | ```
191 | @Override
192 | public void onClick(ViewHolder viewHolder) {
193 | super.onClick(viewHolder);
194 | getItemManager().notifyDataChanged();
195 | }
196 | ```
197 |
198 | # 五,如何设置Item点击:
199 |
200 | 1.重写`TreeItem`的`onClick()`
201 |
202 | 2.`adapter`设置`setOnItemClickListener`
203 | ```
204 | adapter.setOnItemClickListener(new BaseRecyclerAdapter.OnItemClickListener() {
205 | @Override
206 | public void onItemClick(@NonNull ViewHolder viewHolder, int position) {
207 |
208 | }
209 | });
210 | ```
211 | ##### 注意.二者冲突.
212 | `ItemClickListener`优先级高于`TreeItem`的`onClick`.
213 |
214 |
215 | # 如果不想写上面的Item类怎么办?
216 |
217 | 使用`SimpleTreeItem`
218 |
219 | ```
220 | ArrayList items = new ArrayList<>();
221 | for (Pair itemPair : itemPairs) {
222 | SimpleTreeItem simpleTreeItem = new SimpleTreeItem(R.layout.item_mine)//传入布局id.
223 | .onItemBind(viewHolder -> {
224 |
225 | })
226 | .onItemClick(viewHolder -> {
227 |
228 | });
229 | simpleTreeItem.setData(itemPair);
230 | items.add(simpleTreeItem);
231 | }
232 | adapter.getItemManager().replaceAllItem(items);
233 | ```
234 |
235 | # 混淆
236 | ```
237 | -keep public class * extends com.baozi.treerecyclerview.item.TreeItem {}
238 | -keep public class * extends android.support.annotation.**
239 |
240 | ```
241 |
242 | # 最后
243 |
244 | 直接设置就行了.adapter可以不先setData
245 | 可以直接setAdapter.然后`adapter.getItemManager().replaceAllItem(items);`
246 |
247 |
248 | ```
249 | recyclerView.setAdapter(adapter);
250 | ```
251 |
252 |
253 |
254 | 更多效果.见demo
255 | ### 欢迎大家留言,提出问题. QQ交流群:493180098
256 |
257 |
258 |
259 |
260 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 28
5 | buildToolsVersion "28.0.3"
6 |
7 | defaultConfig {
8 | minSdkVersion 15
9 | targetSdkVersion 22
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | implementation fileTree(include: ['*.jar'], dir: 'libs')
23 | implementation 'com.android.support:appcompat-v7:28.0.0'
24 | implementation 'com.android.support:recyclerview-v7:28.0.0'
25 | implementation 'com.android.support:design:28.0.0'
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/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 J:\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/com/baozi/treerecyclerview/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview;
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 |
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/adpater/TreeRecyclerType.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.adpater;
2 |
3 | public enum TreeRecyclerType {
4 | /**
5 | * 显示所有,不可展开折叠
6 | * 适用场景,不需要折叠,默认显示所有item
7 | */
8 | SHOW_ALL,
9 |
10 | /**
11 | * 默认只显示第一级,点击展开,折叠不会影响子级展开折叠
12 | * 根据isExpand的状态显示展开与折叠,
13 | * 适用场景,多级的data数据展示,保存展开状态
14 | */
15 | SHOW_EXPAND,
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/adpater/wrapper/BaseWrapper.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.adpater.wrapper;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | import com.baozi.treerecyclerview.base.BaseRecyclerAdapter;
9 | import com.baozi.treerecyclerview.base.ViewHolder;
10 | import com.baozi.treerecyclerview.manager.ItemManager;
11 |
12 | import java.util.List;
13 |
14 | /**
15 | * Created by baozi on 2017/5/16.
16 | */
17 |
18 | public class BaseWrapper extends BaseRecyclerAdapter {
19 |
20 | protected BaseRecyclerAdapter mAdapter;
21 |
22 | public BaseWrapper(BaseRecyclerAdapter adapter) {
23 | mAdapter = adapter;
24 | mAdapter.getItemManager().setAdapter(this);
25 | }
26 |
27 | @Override
28 | public void onBindViewHolderClick(@NonNull ViewHolder holder, View view) {
29 | mAdapter.onBindViewHolderClick(holder, view);
30 | }
31 |
32 | @NonNull
33 | @Override
34 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
35 | return mAdapter.onCreateViewHolder(parent, viewType);
36 | }
37 |
38 | @Override
39 | public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
40 | mAdapter.onAttachedToRecyclerView(recyclerView);
41 | }
42 |
43 | @Override
44 | public void onViewAttachedToWindow(@NonNull ViewHolder holder) {
45 | mAdapter.onViewAttachedToWindow(holder);
46 | }
47 |
48 | @Override
49 | public int getItemViewType(int position) {
50 | return mAdapter.getItemViewType(position);
51 | }
52 |
53 | @Override
54 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
55 | mAdapter.onBindViewHolder(holder, position);
56 | }
57 |
58 | @Override
59 | public int getItemCount() {
60 | return mAdapter.getItemCount();
61 | }
62 |
63 |
64 | @Override
65 | public int getLayoutId(int position) {
66 | return mAdapter.getLayoutId(position);
67 | }
68 |
69 | @Override
70 | public T getData(int position) {
71 | return mAdapter.getData(position);
72 | }
73 |
74 | @Override
75 | public List getData() {
76 | return mAdapter.getData();
77 | }
78 |
79 | @Override
80 | public void setData(List data) {
81 | mAdapter.setData(data);
82 | }
83 |
84 | @Override
85 | public void onBindViewHolder(@NonNull ViewHolder holder, T t, int position) {
86 | mAdapter.onBindViewHolder(holder, t, position);
87 | }
88 |
89 | @Override
90 | public int checkPosition(int position) {
91 | return mAdapter.checkPosition(position);
92 | }
93 |
94 |
95 | @Override
96 | public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
97 | mAdapter.setOnItemClickListener(onItemClickListener);
98 | }
99 |
100 | @Override
101 | public void setOnItemLongClickListener(OnItemLongClickListener onItemLongClickListener) {
102 | mAdapter.setOnItemLongClickListener(onItemLongClickListener);
103 | }
104 |
105 | @Override
106 | public int getItemSpanSize(int position, int maxSpan) {
107 | return mAdapter.getItemSpanSize(position, maxSpan);
108 | }
109 |
110 | @Override
111 | public ItemManager getItemManager() {
112 | return mAdapter.getItemManager();
113 | }
114 |
115 | @Override
116 | public void setItemManager(ItemManager itemManager) {
117 | mAdapter.setItemManager(itemManager);
118 | }
119 |
120 | @Override
121 | public void clear() {
122 | mAdapter.clear();
123 | }
124 |
125 | }
126 |
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/adpater/wrapper/HeaderWrapper.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.adpater.wrapper;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 | import android.util.SparseArray;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import com.baozi.treerecyclerview.base.BaseRecyclerAdapter;
10 | import com.baozi.treerecyclerview.base.ViewHolder;
11 | import com.baozi.treerecyclerview.item.TreeItem;
12 | import com.baozi.treerecyclerview.manager.ItemManager;
13 |
14 | import java.util.List;
15 |
16 | /**
17 | * Created by baozi on 2017/4/30.
18 | * 在最后一个,优先级高于loadwrapper,
19 | */
20 | public class HeaderWrapper extends BaseWrapper {
21 | private static final int HEAD_ITEM = 1000;
22 | private SparseArray mHeaderViews = new SparseArray<>();
23 | private boolean headShow = true;
24 | private int mHeaderSize;
25 |
26 | public HeaderWrapper(BaseRecyclerAdapter adapter) {
27 | super(adapter);
28 | getItemManager().addCheckItemInterfaces(new ItemManager.CheckItemInterface() {
29 | @Override
30 | public int itemToDataPosition(int position) {
31 | return position - getHeadersCount();
32 | }
33 |
34 | @Override
35 | public int dataToItemPosition(int index) {
36 | return index + getHeadersCount();
37 | }
38 | });
39 | }
40 |
41 | @Override
42 | public T getData(int position) {
43 | return mAdapter.getData(position);
44 | }
45 |
46 | @NonNull
47 | @Override
48 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
49 | if (mHeaderViews.get(viewType) != null) {
50 | return ViewHolder.createViewHolder(mHeaderViews.get(viewType));
51 | }
52 | return mAdapter.onCreateViewHolder(parent, viewType);
53 | }
54 |
55 | @Override
56 | public void onBindViewHolderClick(@NonNull ViewHolder holder, View view) {
57 | int layoutPosition = holder.getLayoutPosition();
58 | if (isHeaderViewPos(layoutPosition)) {
59 | return;
60 | }
61 | super.onBindViewHolderClick(holder, view);
62 | }
63 |
64 | @Override
65 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
66 | if (isHeaderViewPos(position)) {
67 | return;
68 | }
69 | super.onBindViewHolder(holder, position - getHeadersCount());
70 | }
71 |
72 | @Override
73 | public int getItemCount() {
74 | return getHeadersCount() + mAdapter.getItemCount();
75 | }
76 |
77 |
78 | @Override
79 | public int getItemSpanSize(int position, int maxSpan) {
80 | if (isHeaderViewPos(position)) {
81 | return maxSpan;
82 | }
83 | return super.getItemSpanSize(position, maxSpan);
84 | }
85 |
86 | @Override
87 | public int getItemViewType(int position) {
88 | if (isHeaderViewPos(position)) {
89 | return mHeaderViews.keyAt(position);
90 | }
91 | return super.getItemViewType(position - getHeadersCount());
92 | }
93 |
94 |
95 | public void addHeaderView(View view) {
96 | int size = mHeaderViews.size();
97 | mHeaderViews.put(HEAD_ITEM + size, view);
98 | mHeaderSize++;
99 | }
100 |
101 | protected boolean isHeaderViewPos(int position) {
102 | return position < getHeadersCount();
103 | }
104 |
105 | public void setShowHeadView(boolean show) {
106 | this.headShow = show;
107 | int size = mHeaderViews.size();
108 | for (int i = 0; i < size; i++) {
109 | View view = mHeaderViews.valueAt(i);
110 | view.setVisibility(show ? View.VISIBLE : View.GONE);
111 | }
112 | }
113 |
114 | public int getHeadersCount() {
115 | if (!headShow) {
116 | return 0;
117 | }
118 | return mHeaderSize;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/annotation/TreeDataType.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.annotation;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Created by 125C01063144 on 2018/2/27.
10 | */
11 | @Retention(RetentionPolicy.RUNTIME)
12 | @Target(ElementType.TYPE)
13 | public @interface TreeDataType {
14 | /**
15 | * 要绑定的item
16 | */
17 | Class iClass() default Object.class;
18 |
19 | String bindField() default "";
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/annotation/TreeItemType.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.annotation;
2 |
3 |
4 | import android.support.annotation.LayoutRes;
5 |
6 | import java.lang.annotation.ElementType;
7 | import java.lang.annotation.Retention;
8 | import java.lang.annotation.RetentionPolicy;
9 | import java.lang.annotation.Target;
10 |
11 | /**
12 | * Created by baozi on 2018/2/27.
13 | * 如果使用在item的类上
14 | */
15 | @Retention(RetentionPolicy.RUNTIME)
16 | @Target({ElementType.FIELD, ElementType.TYPE})
17 | public @interface TreeItemType {
18 | /**
19 | * 映射的type值
20 | *
21 | * @return [type1, type2]
22 | */
23 | String[] type();
24 |
25 | /**
26 | * item的列占比
27 | *
28 | * @return 默认返回0, 也就是不设置
29 | */
30 | int spanSize() default 0;
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/base/BaseRecyclerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.base;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import com.baozi.treerecyclerview.manager.ItemManageImpl;
10 | import com.baozi.treerecyclerview.manager.ItemManager;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | /**
16 | * Created by zhy on 16/4/9.
17 | */
18 | public abstract class BaseRecyclerAdapter extends RecyclerView.Adapter {
19 |
20 | protected ItemManager mItemManager;
21 | protected OnItemClickListener mOnItemClickListener;
22 | protected OnItemLongClickListener mOnItemLongClickListener;
23 | private List data;
24 |
25 | @NonNull
26 | @Override
27 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
28 | ViewHolder holder = ViewHolder.createViewHolder(parent, viewType);
29 | onBindViewHolderClick(holder, holder.itemView);
30 | return holder;
31 | }
32 |
33 | @Override
34 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
35 | onBindViewHolder(holder, getData(position), position);
36 | }
37 |
38 | /**
39 | * 实现item的点击事件
40 | */
41 | public void onBindViewHolderClick(@NonNull final ViewHolder viewHolder, View view) {
42 | //判断当前holder是否已经设置了点击事件
43 | if (!view.hasOnClickListeners()) {
44 | view.setOnClickListener(new View.OnClickListener() {
45 | @Override
46 | public void onClick(View v) {
47 | //获得holder的position
48 | int layoutPosition = viewHolder.getLayoutPosition();
49 | //检查item的position,是否可以点击.
50 | // 检查并得到真实的position
51 | int itemPosition = getItemManager().itemToDataPosition(layoutPosition);
52 | if (mOnItemClickListener != null) {
53 | mOnItemClickListener.onItemClick(viewHolder, itemPosition);
54 | }
55 | }
56 | });
57 | }
58 | if (!view.isLongClickable()) {
59 | view.setOnLongClickListener(new View.OnLongClickListener() {
60 | @Override
61 | public boolean onLongClick(View v) {
62 | //获得holder的position
63 | int layoutPosition = viewHolder.getLayoutPosition();
64 | //检查position是否可以点击
65 | //检查并得到真实的position
66 | int itemPosition = getItemManager().itemToDataPosition(layoutPosition);
67 | if (mOnItemLongClickListener != null) {
68 | return mOnItemLongClickListener.onItemLongClick(viewHolder, itemPosition);
69 | }
70 | return false;
71 | }
72 | });
73 | }
74 | }
75 |
76 | @Override
77 | public int getItemViewType(int position) {
78 | return getLayoutId(position);
79 | }
80 |
81 | @Override
82 | public int getItemCount() {
83 | return getData().size();
84 | }
85 |
86 |
87 | public int getItemSpanSize(int position, int maxSpan) {
88 | return maxSpan;
89 | }
90 |
91 | public List getData() {
92 | if (data == null) {
93 | data = new ArrayList<>();
94 | }
95 | return data;
96 | }
97 |
98 | public void setData(List data) {
99 | if (data != null) {
100 | getData().clear();
101 | getData().addAll(data);
102 | }
103 | }
104 |
105 | @Nullable
106 | public T getData(int position) {
107 | if (position >= 0) {
108 | return getData().get(position);
109 | }
110 | return null;
111 | }
112 |
113 | /**
114 | * 直接强转为指定类型,可以能null
115 | *
116 | * @param position
117 | * @param
118 | * @return
119 | */
120 | public D getCastData(int position) {
121 | try {
122 | return (D) getData(position);
123 | } catch (Exception e) {
124 | e.printStackTrace();
125 | return null;
126 | }
127 | }
128 |
129 | /**
130 | * 操作adapter
131 | *
132 | * @return
133 | */
134 | public ItemManager getItemManager() {
135 | if (mItemManager == null) {
136 | mItemManager = new ItemManageImpl(this);
137 | }
138 | return mItemManager;
139 | }
140 |
141 | public void setItemManager(ItemManager itemManager) {
142 | mItemManager = itemManager;
143 | }
144 |
145 | public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
146 | mOnItemClickListener = onItemClickListener;
147 | }
148 |
149 | public void setOnItemLongClickListener(OnItemLongClickListener onItemLongClickListener) {
150 | mOnItemLongClickListener = onItemLongClickListener;
151 | }
152 |
153 |
154 | public interface OnItemClickListener {
155 | void onItemClick(@NonNull ViewHolder viewHolder, int position);
156 | }
157 |
158 | public interface OnItemLongClickListener {
159 | boolean onItemLongClick(@NonNull ViewHolder viewHolder, int position);
160 | }
161 |
162 | //检查当前position,获取原始角标
163 | public int checkPosition(int position) {
164 | return getItemManager().itemToDataPosition(position);
165 | }
166 |
167 |
168 | /**
169 | * 获取该position的item的layout
170 | *
171 | * @param position 角标
172 | * @return item的layout id
173 | */
174 | public abstract int getLayoutId(int position);
175 |
176 | /**
177 | * view与数据绑定
178 | *
179 | * @param holder ViewHolder
180 | * @param t 数据类型
181 | * @param position position
182 | */
183 | public void onBindViewHolder(@NonNull ViewHolder holder, T t, int position) {
184 |
185 | }
186 |
187 | public void clear() {
188 | getData().clear();
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/factory/ItemConfig.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.factory;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 | import android.text.TextUtils;
6 | import android.util.SparseArray;
7 |
8 | import com.baozi.treerecyclerview.annotation.TreeDataType;
9 | import com.baozi.treerecyclerview.annotation.TreeItemType;
10 | import com.baozi.treerecyclerview.item.TreeItem;
11 |
12 | import java.lang.annotation.Annotation;
13 | import java.lang.reflect.Field;
14 | import java.util.HashMap;
15 |
16 | public class ItemConfig {
17 | /**
18 | * type,TreeClass映射
19 | */
20 | private static final HashMap> treeViewHolderTypes = new HashMap<>();
21 | /**
22 | * TreeDataType映射
23 | */
24 | private static final HashMap treeDataTypeMap = new HashMap<>();
25 | /**
26 | * TreeItemType映射
27 | */
28 | private static final HashMap treeItemTypeMap = new HashMap<>();
29 |
30 | public static Class extends TreeItem> getTreeViewHolderType(String type) {
31 | return treeViewHolderTypes.get(type);
32 | }
33 |
34 | public static void register(String type, Class extends TreeItem> clazz) {
35 | if (null == clazz) {
36 | return;
37 | }
38 | Class extends TreeItem> typeClass = treeViewHolderTypes.get(type);
39 | if (typeClass == null) {
40 | treeViewHolderTypes.put(type, clazz);
41 | return;
42 | }
43 | if (clazz != typeClass) {//如果该type,已经添加了,则抛出异常
44 | throw new IllegalStateException("该type映射了" + typeClass.getSimpleName() + "不能再映射其他TreeItem");
45 | }
46 | }
47 |
48 | public static void register(Class extends TreeItem> zClass) {
49 | if (treeItemTypeMap.get(zClass) != null) {
50 | return;
51 | }
52 | TreeItemType annotation = zClass.getAnnotation(TreeItemType.class);
53 | if (annotation != null) {
54 | treeItemTypeMap.put(zClass, annotation);
55 | String[] typeList = annotation.type();
56 | for (String type : typeList) {
57 | register(type, zClass);
58 | }
59 | }
60 | }
61 |
62 | @SafeVarargs
63 | public static void register(@NonNull Class extends TreeItem>... clazz) {
64 | for (Class extends TreeItem> zClass : clazz) {
65 | register(zClass);
66 | }
67 | }
68 |
69 | /**
70 | * 获取TreeItem的Class
71 | *
72 | * @param data
73 | * @return
74 | */
75 | @Nullable
76 | public static Class extends TreeItem> getTypeClass(Object data) {
77 | Class> dataClass = data.getClass();
78 | //先判断是否继承了ItemData,适用于跨模块获取
79 | //判断是否使用注解绑定了ItemClass,适用当前模块
80 | TreeDataType treeDataType = treeDataTypeMap.get(dataClass);
81 | if (treeDataType == null) {
82 | treeDataType = dataClass.getAnnotation(TreeDataType.class);
83 | }
84 | if (treeDataType != null) {
85 | //缓存注解
86 | treeDataTypeMap.put(dataClass, treeDataType);
87 |
88 | String key = treeDataType.bindField();
89 | if (!TextUtils.isEmpty(key)) {
90 | try {
91 | Field field = dataClass.getField(key);
92 | String type = field.get(data).toString();
93 | Class extends TreeItem> itemClass = getTreeViewHolderType(type);
94 | return itemClass;
95 | } catch (NoSuchFieldException e) {
96 | e.printStackTrace();
97 | } catch (IllegalAccessException e) {
98 | e.printStackTrace();
99 | }
100 | }
101 | return treeDataType.iClass();
102 | }
103 | return null;
104 | }
105 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/factory/ItemHelperFactory.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.factory;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 | import android.text.TextUtils;
6 | import android.util.Log;
7 |
8 | import com.baozi.treerecyclerview.adpater.TreeRecyclerType;
9 | import com.baozi.treerecyclerview.annotation.TreeDataType;
10 | import com.baozi.treerecyclerview.annotation.TreeItemType;
11 | import com.baozi.treerecyclerview.item.TreeItem;
12 | import com.baozi.treerecyclerview.item.TreeItemGroup;
13 |
14 | import java.lang.annotation.Annotation;
15 | import java.lang.reflect.Field;
16 | import java.util.ArrayList;
17 | import java.util.HashMap;
18 | import java.util.List;
19 |
20 | /**
21 | * Created by baozi on 2017/4/29.
22 | */
23 |
24 | public class ItemHelperFactory {
25 | private static final HashMap> classCacheMap = new HashMap<>();
26 |
27 | public static List createItems(@Nullable List list) {
28 | return createItems(list, null, null);
29 | }
30 |
31 | public static List createItems(@Nullable List list, @Nullable TreeItemGroup treeParentItem) {
32 | return createItems(list, null, treeParentItem);
33 | }
34 |
35 | public static List createItems(@Nullable List list, Class extends TreeItem> iClass) {
36 | return createItems(list, iClass, null);
37 | }
38 |
39 | public static List createItems(@Nullable List list, Class extends TreeItem> iClass, @Nullable TreeItemGroup treeParentItem) {
40 | if (null == list) {
41 | return null;
42 | }
43 | int size = list.size();
44 | ArrayList treeItemList = new ArrayList<>();
45 | for (int i = 0; i < size; i++) {
46 | Object itemData = list.get(i);
47 | TreeItem treeItem = createItem(itemData, iClass, treeParentItem);
48 | if (treeItem != null) {
49 | treeItemList.add(treeItem);
50 | }
51 | }
52 | return treeItemList;
53 | }
54 |
55 | /**
56 | * 确定item的class类型,并且添加到了itemConfig,用该方法创建TreeItem
57 | *
58 | * @return
59 | */
60 | public static TreeItem createItem(Object d) {
61 | return createItem(d, null, null);
62 | }
63 |
64 | @Nullable
65 | public static TreeItem createItem(Object data, @Nullable TreeItemGroup treeParentItem) {
66 | return createItem(data, null, treeParentItem);
67 | }
68 |
69 | @Nullable
70 | public static TreeItem createItem(Object data, @Nullable Class zClass) {
71 | return createItem(data, zClass, null);
72 | }
73 |
74 | @Nullable
75 | public static TreeItem createItem(Object data, @Nullable Class zClass, @Nullable TreeItemGroup treeParentItem) {
76 | TreeItem treeItem = null;
77 | Class extends TreeItem> treeItemClass;
78 | try {
79 | if (zClass != null) {
80 | treeItemClass = zClass;
81 | ItemConfig.register(zClass);
82 | } else {
83 | treeItemClass = ItemConfig.getTypeClass(data);
84 | //判断是否是TreeItem的子类
85 | }
86 | if (treeItemClass != null) {
87 | treeItem = treeItemClass.newInstance();
88 | treeItem.setData(data);
89 | treeItem.setParentItem(treeParentItem);
90 | TreeItemType annotation = treeItemClass.getAnnotation(TreeItemType.class);
91 | if (annotation != null) {
92 | int spanSize = annotation.spanSize();
93 | treeItem.setSpanSize(spanSize);
94 | }
95 | }
96 | } catch (ClassCastException e) {
97 | Log.w("ClassCastException", "传入的data与item定义的data泛型不一致");
98 | } catch (Exception e) {
99 | e.printStackTrace();
100 | }
101 | return treeItem;
102 | }
103 |
104 |
105 | /**
106 | * 根据TreeRecyclerType获取子item集合,不包含TreeItemGroup自身
107 | *
108 | * @param itemGroup
109 | * @param type
110 | * @return
111 | */
112 | @NonNull
113 | public static ArrayList getChildItemsWithType(@Nullable TreeItemGroup itemGroup, @NonNull TreeRecyclerType type) {
114 | if (itemGroup == null) {
115 | return new ArrayList();
116 | }
117 | return getChildItemsWithType(itemGroup.getChild(), type);
118 | }
119 |
120 | @NonNull
121 | public static ArrayList getChildItemsWithType(@Nullable List items, @NonNull TreeRecyclerType type) {
122 | ArrayList returnItems = new ArrayList<>();
123 | if (items == null) {
124 | return returnItems;
125 | }
126 | int childCount = items.size();
127 | for (int i = 0; i < childCount; i++) {
128 | TreeItem childItem = items.get(i);//获取当前一级
129 | returnItems.add(childItem);
130 | if (childItem instanceof TreeItemGroup) {//获取下一级
131 | List list = null;
132 | switch (type) {
133 | case SHOW_ALL:
134 | //调用下级的getAllChild遍历,相当于递归遍历
135 | list = getChildItemsWithType((TreeItemGroup) childItem, type);
136 | break;
137 | case SHOW_EXPAND:
138 | //根据isExpand,来决定是否展示
139 | if (((TreeItemGroup) childItem).isExpand()) {
140 | list = getChildItemsWithType((TreeItemGroup) childItem, type);
141 | }
142 | break;
143 | }
144 | if (list != null && list.size() > 0) {
145 | returnItems.addAll(list);
146 | }
147 | }
148 | }
149 | return returnItems;
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/item/SimpleTreeItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.item;
2 |
3 | import android.graphics.Rect;
4 | import android.support.annotation.NonNull;
5 | import android.support.v7.widget.RecyclerView;
6 |
7 | import com.baozi.treerecyclerview.base.ViewHolder;
8 |
9 | /**
10 | * 简单样式的item
11 | */
12 | public class SimpleTreeItem extends TreeItem {
13 | private int layout;
14 | private int spanSize;
15 | private Consumer treeClick;
16 | private Consumer treeBind;
17 | private Rect treeRect;
18 |
19 | public SimpleTreeItem() {
20 | this(0, 0);
21 | }
22 |
23 | public SimpleTreeItem(int layout) {
24 | this(layout, 0);
25 | }
26 |
27 | public SimpleTreeItem(int layout, int spanSize) {
28 | this.layout = layout;
29 | this.spanSize = spanSize;
30 | }
31 |
32 | @Override
33 | public int getLayoutId() {
34 | return layout;
35 | }
36 |
37 | @Override
38 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
39 | if (treeBind != null) {
40 | treeBind.accept(viewHolder);
41 | }
42 | }
43 |
44 | @Override
45 | public void onClick(ViewHolder viewHolder) {
46 | if (treeClick != null) {
47 | treeClick.accept(viewHolder);
48 | }
49 | }
50 |
51 | @Override
52 | public void getItemOffsets(@NonNull Rect outRect, RecyclerView.LayoutParams layoutParams, int position) {
53 | if (treeRect != null) {
54 | outRect.set(treeRect);
55 | }
56 | }
57 |
58 | @Override
59 | public int getSpanSize(int maxSpan) {
60 | return spanSize == 0 ? spanSize : maxSpan / spanSize;
61 | }
62 |
63 | public interface Consumer {
64 | void accept(T t);
65 | }
66 |
67 | public SimpleTreeItem onItemClick(Consumer treeClick) {
68 | this.treeClick = treeClick;
69 | return this;
70 | }
71 |
72 | public SimpleTreeItem onItemBind(Consumer treeOnBind) {
73 | this.treeBind = treeOnBind;
74 | return this;
75 | }
76 |
77 | public SimpleTreeItem setTreeOffset(Rect outRect) {
78 | this.treeRect = outRect;
79 | return this;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/item/SwipeItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.item;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | import com.baozi.treerecyclerview.base.ViewHolder;
6 | import com.baozi.treerecyclerview.widget.swipe.SwipeItemMangerInterface;
7 | import com.baozi.treerecyclerview.widget.swipe.SwipeLayout;
8 |
9 | /**
10 | * Created by Administrator on 2017/8/18 0018.
11 | * 实现该接口,侧滑删除
12 | */
13 |
14 | public interface SwipeItem {
15 |
16 | int getSwipeLayoutId();
17 |
18 | SwipeLayout.DragEdge getDragEdge();
19 |
20 | void onBindSwipeView(@NonNull ViewHolder viewHolder, int position, SwipeItemMangerInterface swipeManger);
21 |
22 | void openCallback();
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/item/TreeItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.item;
2 |
3 | import android.graphics.Rect;
4 | import android.support.annotation.NonNull;
5 | import android.support.annotation.Nullable;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.view.View;
8 |
9 | import com.baozi.treerecyclerview.base.ViewHolder;
10 | import com.baozi.treerecyclerview.manager.ItemManager;
11 |
12 | /**
13 | * TreeRecyclerAdapter的item
14 | */
15 | public abstract class TreeItem {
16 | /**
17 | * 当前item的数据
18 | */
19 | protected D data;
20 | private TreeItemGroup parentItem;
21 | /**
22 | * item在每行中的spansize
23 | * 默认为0,如果为0则占满一行
24 | */
25 | private int spanSize;
26 | private ItemManager mItemManager;
27 |
28 | public TreeItem() {
29 | init();
30 | }
31 |
32 | protected void init() {
33 | }
34 |
35 | public void setParentItem(TreeItemGroup parentItem) {
36 | this.parentItem = parentItem;
37 | }
38 |
39 | /**
40 | * 获取当前item的父级
41 | */
42 | @Nullable
43 | public TreeItemGroup getParentItem() {
44 | return parentItem;
45 | }
46 |
47 | /**
48 | * 应该在void onBindViewHolder(ViewHolder viewHolder)的地方使用.
49 | * 如果要使用,可能为null,请加判断.
50 | */
51 | public ItemManager getItemManager() {
52 | return mItemManager;
53 | }
54 |
55 | public void setItemManager(ItemManager itemManager) {
56 | mItemManager = itemManager;
57 | }
58 |
59 | /**
60 | * 该条目的布局id
61 | *
62 | * @return 布局id
63 | */
64 | public int getLayoutId() {
65 | return 0;
66 | }
67 |
68 | /**
69 | * @param maxSpan 总数
70 | */
71 | public int getSpanSize(int maxSpan) {
72 | return spanSize == 0 ? maxSpan : spanSize;
73 | }
74 |
75 |
76 | public void setSpanSize(int spanSize) {
77 | this.spanSize = spanSize;
78 | }
79 |
80 | /**
81 | * 设置当前条目间隔
82 | * 废弃,2个版本后删除
83 | */
84 | @Deprecated
85 | public void getItemOffsets(@NonNull Rect outRect, RecyclerView.LayoutParams layoutParams, int position) {
86 |
87 | }
88 |
89 | /**
90 | * 设置当前条目间隔等
91 | */
92 | public void getItemOffsets(Rect outRect,
93 | View view,
94 | RecyclerView parent,
95 | RecyclerView.State state,
96 | int checkPosition) {
97 | getItemOffsets(outRect, (RecyclerView.LayoutParams) view.getLayoutParams(), checkPosition);
98 | }
99 |
100 | public D getData() {
101 | return data;
102 | }
103 |
104 | public void setData(D data) {
105 | this.data = data;
106 | }
107 |
108 | /**
109 | * 抽象holder的绑定
110 | */
111 | public abstract void onBindViewHolder(@NonNull ViewHolder viewHolder);
112 |
113 | /**
114 | * 当前条目的点击回调
115 | */
116 | public void onClick(ViewHolder viewHolder) {
117 |
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/item/TreeItemGroup.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.item;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 |
6 | import com.baozi.treerecyclerview.adpater.TreeRecyclerAdapter;
7 | import com.baozi.treerecyclerview.adpater.TreeRecyclerType;
8 | import com.baozi.treerecyclerview.adpater.wrapper.BaseWrapper;
9 | import com.baozi.treerecyclerview.base.BaseRecyclerAdapter;
10 | import com.baozi.treerecyclerview.base.ViewHolder;
11 | import com.baozi.treerecyclerview.factory.ItemHelperFactory;
12 | import com.baozi.treerecyclerview.manager.ItemManager;
13 |
14 | import java.util.List;
15 |
16 | /**
17 | * Created by baozi on 2016/12/22.
18 | * //拥有子集
19 | * //子集可以是parent,也可以是child
20 | * //可展开折叠
21 | */
22 |
23 | public abstract class TreeItemGroup extends TreeItem {
24 |
25 | /**
26 | * 持有的子item
27 | */
28 | private List child;
29 |
30 | /**
31 | * 是否展开
32 | */
33 | private boolean isExpand;
34 | /**
35 | * 是否能展开
36 | */
37 | private boolean isCanExpand = true;
38 |
39 | /**
40 | * 能否展开折叠
41 | */
42 | public boolean isCanExpand() {
43 | return isCanExpand;
44 | }
45 |
46 | public void setCanExpand(boolean canExpand) {
47 | isCanExpand = canExpand;
48 | }
49 |
50 | public boolean isExpand() {
51 | return isExpand;
52 | }
53 |
54 | /**
55 | * 设置为传入
56 | *
57 | * @param expand 传入true则展开,传入false则折叠
58 | */
59 | public final void setExpand(boolean expand) {
60 | if (!isCanExpand()) {
61 | return;
62 | }
63 | if (expand == isExpand) {//防止重复展开
64 | return;
65 | }
66 | isExpand = expand;
67 | if (expand) {
68 | onExpand();
69 | } else {
70 | onCollapse();
71 | }
72 | }
73 |
74 | /**
75 | * 展开
76 | */
77 | protected void onExpand() {
78 | ItemManager itemManager = getItemManager();
79 | if (itemManager == null) {
80 | return;
81 | }
82 | List child = this.getChild();
83 | if (child == null || child.size() == 0) {
84 | isExpand = false;
85 | return;
86 | }
87 | int itemPosition = itemManager.getItemPosition(this);
88 | itemManager.addItems(itemPosition + 1, child);
89 | }
90 |
91 | /**
92 | * 折叠
93 | */
94 | protected void onCollapse() {
95 | ItemManager itemManager = getItemManager();
96 | if (itemManager == null) {
97 | return;
98 | }
99 | List child = this.getChild();
100 | if (child == null || child.size() == 0) {
101 | isExpand = false;
102 | return;
103 | }
104 | itemManager.removeItems(child);
105 | }
106 |
107 |
108 | /**
109 | * 获得所有展开的childs,包括子item的childs
110 | *
111 | * @return
112 | */
113 | @NonNull
114 | public List getExpandChild() {
115 | return ItemHelperFactory.getChildItemsWithType(this, TreeRecyclerType.SHOW_EXPAND);
116 | }
117 |
118 |
119 | public void setData(D data) {
120 | super.setData(data);
121 | child = initChild(data);
122 | }
123 |
124 | /**
125 | * 获得所有childs,包括下下....级item的childs
126 | *
127 | * @return
128 | */
129 | @Nullable
130 | public List getAllChilds() {
131 | return ItemHelperFactory.getChildItemsWithType(this, TreeRecyclerType.SHOW_ALL);
132 | }
133 |
134 | /**
135 | * 获得自己的childs.
136 | *
137 | * @return
138 | */
139 | @Nullable
140 | public List getChild() {
141 | return child;
142 | }
143 |
144 |
145 | public int getChildCount() {
146 | return child == null ? 0 : child.size();
147 | }
148 |
149 | /**
150 | * 初始化子集
151 | *
152 | * @param data
153 | * @return
154 | */
155 | @Nullable
156 | protected List initChild(D data) {
157 | return null;
158 | }
159 |
160 | /**
161 | * 是否消费child的click事件
162 | *
163 | * @param child 具体click的item
164 | * @return 返回true代表消费此次事件,child不会走onclick(),返回false说明不消费此次事件,child依然会走onclick()
165 | */
166 | public boolean onInterceptClick(TreeItem child) {
167 | return false;
168 | }
169 |
170 | @Override
171 | public void onClick(ViewHolder viewHolder) {
172 | super.onClick(viewHolder);
173 | //必须是TreeItemGroup才能展开折叠,并且type不能为 TreeRecyclerType.SHOW_ALL
174 | setExpand(!isExpand());
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/item/TreeSelectItemGroup.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.item;
2 |
3 |
4 | import android.support.annotation.NonNull;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 |
10 | /**
11 | * Created by baozi on 2016/12/22.
12 | * 可以选中子item的TreeItemGroup,点击的item会保存起来.可以通过 getSelectItems()获得选中item
13 | */
14 | public abstract class TreeSelectItemGroup
15 | extends TreeItemGroup {
16 | /**
17 | * 选中的子item.只保存当前的子级
18 | */
19 | private List selectItems;
20 |
21 | public List getSelectItems() {
22 | if (selectItems == null) {
23 | selectItems = new ArrayList<>();
24 | }
25 | return selectItems;
26 | }
27 |
28 | /**
29 | * 是否全选选中
30 | */
31 | public boolean isSelectAll() {
32 | return getSelectItems().containsAll(getChild());
33 | }
34 |
35 |
36 | /**
37 | * 选择全部,取消全部
38 | * 向下递归
39 | *
40 | * @param b 是否全部选中
41 | * @param isMultistage 是否多级关联
42 | */
43 | public void selectAll(boolean b, boolean isMultistage) {
44 | List child = getChild();
45 | if (child == null) {
46 | return;
47 | }
48 | getSelectItems().clear();
49 | for (int i = 0; i < child.size(); i++) {
50 | TreeItem item = child.get(i);
51 | if (item instanceof TreeSelectItemGroup) {
52 | ((TreeSelectItemGroup) item).selectAll(b);
53 | }
54 | if (b && !isSelect(item)) {
55 | getSelectItems().add(item);
56 | }
57 | }
58 | if (isMultistage) {
59 | updateParentSelect();
60 | }
61 | }
62 |
63 | /**
64 | * 选择全部,取消全部
65 | * 向下递归
66 | *
67 | * @param b 是否全部选中
68 | */
69 | public void selectAll(boolean b) {
70 | this.selectAll(b, false);
71 | }
72 |
73 | /**
74 | * 包含的子级是否有选中
75 | */
76 | public boolean isSelect() {
77 | return !getSelectItems().isEmpty();
78 | }
79 |
80 | /**
81 | * 是否选中
82 | */
83 | public boolean isSelect(TreeItem item) {
84 | return getSelectItems().contains(item);
85 | }
86 |
87 | @Override
88 | public boolean onInterceptClick(TreeItem child) {
89 | if (getParentItem() != null) {
90 | return getParentItem().onInterceptClick(this);
91 | }
92 | return super.onInterceptClick(child);
93 | }
94 |
95 | /**
96 | * 添加选中的Item;不建议直接调用该方法,
97 | * 当不需要用onInterceptClick()的时候,可以主动调用添加Item.
98 | * 如果onInterceptClick()生效,还主动调用该方法添加item,将无法添加.
99 | * 向上递归
100 | *
101 | * @param child 要添加选中的item
102 | * @param isMultistage 是否多级关联
103 | */
104 | protected void selectItem(@NonNull TreeItem child, boolean isMultistage) {
105 | if (selectFlag() == SelectFlag.SINGLE_CHOICE) {
106 | if (getSelectItems().size() != 0) {
107 | getSelectItems().set(0, child);
108 | } else {
109 | getSelectItems().add(child);
110 | }
111 | } else {
112 | int index = getSelectItems().indexOf(child);
113 | if (index == -1) {//不存在则添加
114 | getSelectItems().add(child);
115 | } else {//存在则删除
116 | if (child instanceof TreeSelectItemGroup) {
117 | if (((TreeSelectItemGroup) child).isSelect()) {
118 | return;
119 | }
120 | }
121 | getSelectItems().remove(index);
122 | }
123 | if (isMultistage) {
124 | updateParentSelect();
125 | }
126 | }
127 | }
128 |
129 | protected void selectItem(@NonNull TreeItem child) {
130 | this.selectItem(child, false);
131 | }
132 |
133 | public void updateParentSelect() {
134 | TreeItemGroup parentItem = getParentItem();
135 | if (parentItem instanceof TreeSelectItemGroup) {
136 | // 如果当前选中了,但是父类没有选中,则更新
137 | if (isSelect() != ((TreeSelectItemGroup) parentItem).isSelect(this)) {
138 | ((TreeSelectItemGroup) parentItem).selectItem(this, true);
139 | ((TreeSelectItemGroup) parentItem).updateParentSelect();
140 | }
141 | }
142 | }
143 |
144 | /**
145 | * 默认多选
146 | *
147 | * @return
148 | */
149 | public SelectFlag selectFlag() {
150 | return SelectFlag.MULTIPLE_CHOICE;
151 | }
152 |
153 | /**
154 | * 决定TreeSelectItemGroup的选中样式
155 | */
156 | public enum SelectFlag {
157 | /**
158 | * 单选
159 | */
160 | SINGLE_CHOICE,
161 | /**
162 | * 多选
163 | */
164 | MULTIPLE_CHOICE
165 | }
166 |
167 | }
168 |
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/item/TreeSortItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.item;
2 |
3 | /**
4 | * Created by Administrator on 2017/8/8 0008.
5 | */
6 |
7 | public abstract class TreeSortItem extends TreeItemGroup {
8 | protected Object sortKey;
9 |
10 | public void setSortKey(Object sortKey) {
11 | this.sortKey = sortKey;
12 | }
13 |
14 | public Object getSortKey() {
15 | return sortKey;
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/manager/ItemManageImpl.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.manager;
2 |
3 | import com.baozi.treerecyclerview.base.BaseRecyclerAdapter;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * 默认使用 notifyDataChanged();刷新.
9 | * 如果使用带动画效果的,条目过多可能会出现卡顿.
10 | */
11 | public class ItemManageImpl extends ItemManager {
12 |
13 |
14 | public ItemManageImpl(BaseRecyclerAdapter adapter) {
15 | super(adapter);
16 | }
17 |
18 | @Override
19 | public void addItem(T item) {
20 | getData().add(item);
21 | if (!isOpenAnim()) {
22 | notifyDataChanged();
23 | return;
24 | }
25 | int itemPosition = getItemPosition(item);
26 | getAdapter().notifyItemInserted(itemPosition);
27 | }
28 |
29 | @Override
30 | public void addItem(int position, T item) {
31 | getData().add(position, item);
32 | if (!isOpenAnim()) {
33 | notifyDataChanged();
34 | return;
35 | }
36 | position = dataToItemPosition(position);
37 | getAdapter().notifyItemInserted(position);
38 | }
39 |
40 | @Override
41 | public void addItems(List items) {
42 | getData().addAll(items);
43 | if (!isOpenAnim()) {
44 | notifyDataChanged();
45 | return;
46 | }
47 | getAdapter().notifyItemRangeInserted(getData().size(), items.size());
48 | }
49 |
50 | @Override
51 | public void addItems(int position, List items) {
52 | getData().addAll(position, items);
53 | if (!isOpenAnim()) {
54 | notifyDataChanged();
55 | return;
56 | }
57 | int itemPosition = dataToItemPosition(position);
58 | getAdapter().notifyItemRangeInserted(itemPosition, items.size());
59 | }
60 |
61 | @Override
62 | public void removeItem(T item) {
63 | int position = getItemPosition(item);
64 | getData().remove(item);
65 | if (!isOpenAnim()) {
66 | notifyDataChanged();
67 | return;
68 | }
69 | int itemPosition = dataToItemPosition(position);
70 | getAdapter().notifyItemRemoved(itemPosition);
71 | }
72 |
73 | @Override
74 | public void removeItem(int position) {
75 | getData().remove(position);
76 | if (!isOpenAnim()) {
77 | notifyDataChanged();
78 | return;
79 | }
80 | int itemPosition = dataToItemPosition(position);
81 | getAdapter().notifyItemRemoved(itemPosition);
82 | }
83 |
84 | @Override
85 | public void removeItems(List items) {
86 | getData().removeAll(items);
87 | notifyDataChanged();
88 | }
89 |
90 | @Override
91 | public void replaceItem(int position, T item) {
92 | getData().set(position, item);
93 | if (!isOpenAnim()) {
94 | notifyDataChanged();
95 | return;
96 | }
97 | int itemPosition = dataToItemPosition(position);
98 | getAdapter().notifyItemChanged(itemPosition);
99 | }
100 |
101 | @Override
102 | public void replaceAllItem(List items) {
103 | setData(items);
104 | if (!isOpenAnim()) {
105 | notifyDataChanged();
106 | return;
107 | }
108 | getAdapter().notifyItemRangeChanged(0, getData().size());
109 | }
110 |
111 | protected void setData(List items) {
112 | getAdapter().setData(items);
113 | }
114 |
115 | protected List getData() {
116 | return getAdapter().getData();
117 | }
118 |
119 | @Override
120 | public T getItem(int position) {
121 | return getData().get(position);
122 | }
123 |
124 | @Override
125 | public int getItemPosition(T item) {
126 | return getData().indexOf(item);
127 | }
128 |
129 | @Override
130 | public void clean() {
131 | getAdapter().clear();
132 | notifyDataChanged();
133 | }
134 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/manager/ItemManager.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.manager;
2 |
3 |
4 | import com.baozi.treerecyclerview.base.BaseRecyclerAdapter;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | /**
10 | * 条目增删管理类
11 | *
12 | * @param
13 | */
14 | public abstract class ItemManager {
15 |
16 | private BaseRecyclerAdapter mAdapter;
17 | private Object tag;
18 |
19 | public ItemManager(BaseRecyclerAdapter adapter) {
20 | mAdapter = adapter;
21 | }
22 |
23 | public BaseRecyclerAdapter getAdapter() {
24 | return mAdapter;
25 | }
26 |
27 | public void setAdapter(BaseRecyclerAdapter adapter) {
28 | mAdapter = adapter;
29 | }
30 |
31 | private boolean isOpenAnim;
32 |
33 | public boolean isOpenAnim() {
34 | return isOpenAnim;
35 | }
36 |
37 | public void setOpenAnim(boolean openAnim) {
38 | isOpenAnim = openAnim;
39 | }
40 |
41 | //增
42 | public abstract void addItem(T item);
43 |
44 | public abstract void addItem(int position, T item);
45 |
46 | public abstract void addItems(List items);
47 |
48 | public abstract void addItems(int position, List items);
49 |
50 | //删
51 | public abstract void removeItem(T item);
52 |
53 | public abstract void removeItem(int position);
54 |
55 | public abstract void removeItems(List items);
56 |
57 |
58 | //改
59 | public abstract void replaceItem(int position, T item);
60 |
61 | public abstract void replaceAllItem(List items);
62 |
63 | //查
64 | public abstract T getItem(int position);
65 |
66 | public abstract int getItemPosition(T item);
67 |
68 | public abstract void clean();
69 |
70 | //刷新
71 | public void notifyDataChanged() {
72 | mAdapter.notifyDataSetChanged();
73 | }
74 |
75 | public void setTag(Object tag) {
76 | this.tag = tag;
77 | }
78 |
79 | public Object getTag() {
80 | return this.tag;
81 | }
82 |
83 | /**
84 | * 检查item属性
85 | */
86 | public interface CheckItemInterface {
87 | int itemToDataPosition(int position);
88 |
89 | int dataToItemPosition(int index);
90 | }
91 |
92 | public void removeCheckItemInterfaces(CheckItemInterface itemInterface) {
93 | if (checkItemInterfaces == null) return;
94 | checkItemInterfaces.remove(itemInterface);
95 | }
96 |
97 | public void addCheckItemInterfaces(CheckItemInterface itemInterface) {
98 | if (checkItemInterfaces == null) {
99 | checkItemInterfaces = new ArrayList<>();
100 | }
101 | checkItemInterfaces.add(itemInterface);
102 | }
103 |
104 | private ArrayList checkItemInterfaces;
105 |
106 | /**
107 | * 解决holder角标与data的角标不一致问题。
108 | *
109 | * @param position
110 | * @return
111 | */
112 | public int itemToDataPosition(int position) {
113 | if (checkItemInterfaces != null) {
114 | for (CheckItemInterface itemInterface : checkItemInterfaces) {
115 | position = itemInterface.itemToDataPosition(position);
116 | }
117 | }
118 | return position;
119 | }
120 |
121 | /**
122 | * 解决data的角标与holder角标不一致问题。
123 | *
124 | * @param index
125 | * @return
126 | */
127 | public int dataToItemPosition(int index) {
128 | if (checkItemInterfaces != null) {
129 | for (CheckItemInterface itemInterface : checkItemInterfaces) {
130 | index = itemInterface.dataToItemPosition(index);
131 | }
132 | }
133 | return index;
134 | }
135 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/widget/DragSelectRecyclerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.widget;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.NonNull;
5 | import android.view.View;
6 |
7 | import com.baozi.treerecyclerview.base.BaseRecyclerAdapter;
8 | import com.baozi.treerecyclerview.base.ViewHolder;
9 |
10 | import java.util.ArrayList;
11 |
12 |
13 | public abstract class DragSelectRecyclerAdapter extends BaseRecyclerAdapter {
14 |
15 | public interface SelectionListener {
16 | void onDragSelectionChanged(int count);
17 | }
18 |
19 | private ArrayList mSelectedIndices;
20 | private SelectionListener mSelectionListener;
21 | private int mLastCount = -1;
22 | private int mMaxSelectionCount = -1;
23 |
24 | private void fireSelectionListener() {
25 | if (mLastCount == mSelectedIndices.size())
26 | return;
27 | mLastCount = mSelectedIndices.size();
28 | if (mSelectionListener != null)
29 | mSelectionListener.onDragSelectionChanged(mLastCount);
30 | }
31 |
32 | protected DragSelectRecyclerAdapter() {
33 | mSelectedIndices = new ArrayList<>();
34 | }
35 |
36 | @Override
37 | public void onBindViewHolderClick(@NonNull ViewHolder holder, View view) {
38 | super.onBindViewHolderClick(holder, view);
39 | holder.itemView.setTag(holder);
40 | }
41 |
42 | public void setMaxSelectionCount(int maxSelectionCount) {
43 | this.mMaxSelectionCount = maxSelectionCount;
44 | }
45 |
46 | public void setSelectionListener(SelectionListener selectionListener) {
47 | this.mSelectionListener = selectionListener;
48 | }
49 |
50 | public void saveInstanceState(Bundle out) {
51 | saveInstanceState("selected_indices", out);
52 | }
53 |
54 | public void saveInstanceState(String key, Bundle out) {
55 | out.putSerializable(key, mSelectedIndices);
56 | }
57 |
58 | public void restoreInstanceState(Bundle in) {
59 | restoreInstanceState("selected_indices", in);
60 | }
61 |
62 | public void restoreInstanceState(String key, Bundle in) {
63 | if (in != null && in.containsKey(key)) {
64 | //noinspection unchecked
65 | mSelectedIndices = (ArrayList) in.getSerializable(key);
66 | if (mSelectedIndices == null) mSelectedIndices = new ArrayList<>();
67 | else fireSelectionListener();
68 | }
69 | }
70 |
71 | public final void setSelected(int index, boolean selected) {
72 | if (!isIndexSelectable(index))
73 | selected = false;
74 | if (selected) {
75 | if (!mSelectedIndices.contains(index) &&
76 | (mMaxSelectionCount == -1 ||
77 | mSelectedIndices.size() < mMaxSelectionCount)) {
78 | mSelectedIndices.add(index);
79 | notifyDataSetChanged();
80 | }
81 | } else if (mSelectedIndices.contains(index)) {
82 | mSelectedIndices.remove((Integer) index);
83 | notifyDataSetChanged();
84 | }
85 | fireSelectionListener();
86 | }
87 |
88 | public final boolean toggleSelected(int index) {
89 | boolean selectedNow = false;
90 | if (isIndexSelectable(index)) {
91 | if (mSelectedIndices.contains(index)) {
92 | mSelectedIndices.remove((Integer) index);
93 | } else if (mMaxSelectionCount == -1 ||
94 | mSelectedIndices.size() < mMaxSelectionCount) {
95 | mSelectedIndices.add(index);
96 | selectedNow = true;
97 | }
98 | notifyDataSetChanged();
99 | }
100 | fireSelectionListener();
101 | return selectedNow;
102 | }
103 |
104 | protected boolean isIndexSelectable(int index) {
105 | return true;
106 | }
107 |
108 | public final void selectRange(int from, int to, int min, int max) {
109 | if (from == to) {
110 | // Finger is back on the initial item, unselect everything else
111 | for (int i = min; i <= max; i++) {
112 | if (i == from) continue;
113 | setSelected(i, false);
114 | }
115 | fireSelectionListener();
116 | return;
117 | }
118 |
119 | if (to < from) {
120 | // When selecting from one to previous items
121 | for (int i = to; i <= from; i++)
122 | setSelected(i, true);
123 | if (min > -1 && min < to) {
124 | // Unselect items that were selected during this drag but no longer are
125 | for (int i = min; i < to; i++) {
126 | if (i == from) continue;
127 | setSelected(i, false);
128 | }
129 | }
130 | if (max > -1) {
131 | for (int i = from + 1; i <= max; i++)
132 | setSelected(i, false);
133 | }
134 | } else {
135 | // When selecting from one to next items
136 | for (int i = from; i <= to; i++)
137 | setSelected(i, true);
138 | if (max > -1 && max > to) {
139 | // Unselect items that were selected during this drag but no longer are
140 | for (int i = to + 1; i <= max; i++) {
141 | if (i == from) continue;
142 | setSelected(i, false);
143 | }
144 | }
145 | if (min > -1) {
146 | for (int i = min; i < from; i++)
147 | setSelected(i, false);
148 | }
149 | }
150 | fireSelectionListener();
151 | }
152 |
153 | public final void clearSelected() {
154 | mSelectedIndices.clear();
155 | notifyDataSetChanged();
156 | fireSelectionListener();
157 | }
158 |
159 | public final int getSelectedCount() {
160 | return mSelectedIndices.size();
161 | }
162 |
163 | public final ArrayList getSelectedIndices() {
164 | if (mSelectedIndices == null) {
165 | mSelectedIndices = new ArrayList<>();
166 | }
167 | return mSelectedIndices;
168 | }
169 |
170 | public final boolean isIndexSelected(int index) {
171 | return mSelectedIndices.contains(index);
172 | }
173 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/widget/swipe/SwipeItemMangerInterface.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.widget.swipe;
2 |
3 | import java.util.List;
4 |
5 | public interface SwipeItemMangerInterface {
6 | void bind(SwipeLayout swipeLayout, int res, int position);
7 |
8 | void openItem(int position);
9 |
10 | void closeItem(int position);
11 |
12 | void closeAllExcept(SwipeLayout layout);
13 |
14 | void closeAllItems();
15 |
16 | List getOpenItems();
17 |
18 | List getOpenLayouts();
19 |
20 | void removeShownLayouts(SwipeLayout layout);
21 |
22 | boolean isOpen(int position);
23 |
24 | SwipeMode getMode();
25 |
26 | void setMode(SwipeMode mode);
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/baozi/treerecyclerview/widget/swipe/SwipeMode.java:
--------------------------------------------------------------------------------
1 | package com.baozi.treerecyclerview.widget.swipe;
2 |
3 | public enum SwipeMode {
4 | Single, Multiple
5 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/attr.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values/values.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 56dp
10 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.3.50'
5 | repositories {
6 | google()
7 | maven {
8 | url 'https://maven.fabric.io/public'
9 | }
10 | maven {
11 | url 'http://maven.aliyun.com/repository/jcenter'
12 | }
13 | maven {
14 | url 'http://maven.aliyun.com/repository/google'
15 | }
16 | maven {
17 | url 'http://maven.aliyun.com/repository/gradle-plugin'
18 | }
19 | maven {
20 | url 'http://maven.aliyun.com/nexus/content/repositories/releases/'
21 | }
22 | jcenter()
23 | }
24 | dependencies {
25 | classpath 'com.android.tools.build:gradle:3.5.3'
26 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
27 | // NOTE: Do not place your application dependencies here; they belong
28 | // in the individual module build.gradle files
29 | }
30 | }
31 |
32 | allprojects {
33 | repositories {
34 | google()
35 | maven { url "https://jitpack.io" }
36 | maven {
37 | url 'https://maven.fabric.io/public'
38 | }
39 | maven {
40 | url 'http://maven.aliyun.com/repository/jcenter'
41 | }
42 | maven {
43 | url 'http://maven.aliyun.com/repository/google'
44 | }
45 | maven {
46 | url 'http://maven.aliyun.com/repository/gradle-plugin'
47 | }
48 | maven {
49 | url 'http://maven.aliyun.com/nexus/content/repositories/releases/'
50 | }
51 | jcenter()
52 | mavenCentral()
53 | }
54 | }
55 |
56 | task clean(type: Delete) {
57 | delete rootProject.buildDir
58 | }
59 |
--------------------------------------------------------------------------------
/demo/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/demo/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android-extensions'
3 | apply plugin: 'kotlin-android'
4 | apply plugin: 'kotlin-kapt'
5 | android {
6 | compileSdkVersion 28
7 | buildToolsVersion "28.0.3"
8 |
9 | defaultConfig {
10 | applicationId "com.baozi.treerecyclerview"
11 | minSdkVersion 15
12 | targetSdkVersion 28
13 | versionCode 1
14 | versionName "1.0"
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | compileOptions {
23 | targetCompatibility 1.8
24 | sourceCompatibility 1.8
25 | }
26 | }
27 | dependencies {
28 | implementation files('libs/fastjson-1.2.9.jar')
29 | implementation 'com.android.support:appcompat-v7:28.0.0'
30 | implementation 'com.android.support:recyclerview-v7:28.0.0'
31 | implementation 'com.android.support:design:28.0.0'
32 | implementation project(':app')
33 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
34 | }
35 |
--------------------------------------------------------------------------------
/demo/libs/fastjson-1.2.9.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jlanglang/TreeRecyclerView/6f454078ecd9f05619bb1d44b282d6d758f7ffeb/demo/libs/fastjson-1.2.9.jar
--------------------------------------------------------------------------------
/demo/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 J:\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 |
--------------------------------------------------------------------------------
/demo/src/androidTest/java/com/baozi/demo/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.baozi.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 | }
--------------------------------------------------------------------------------
/demo/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/demo/src/main/assets/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 菜翼213
6 |
7 |
8 |
9 |
10 |
11 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/activity/CartAt.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.activity;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.support.v7.widget.LinearLayoutManager;
7 | import android.support.v7.widget.RecyclerView;
8 | import android.widget.CheckBox;
9 | import android.widget.TextView;
10 |
11 | import com.baozi.demo.R;
12 | import com.baozi.demo.item.cart.CartBean;
13 | import com.baozi.demo.item.cart.CartItem;
14 | import com.baozi.treerecyclerview.adpater.TreeRecyclerAdapter;
15 | import com.baozi.treerecyclerview.factory.ItemHelperFactory;
16 | import com.baozi.treerecyclerview.item.TreeItem;
17 | import com.baozi.treerecyclerview.item.TreeSelectItemGroup;
18 |
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | /**
23 | * Created by a123 on 2018/6/5.
24 | * 购物车列表
25 | */
26 | public class CartAt extends AppCompatActivity {
27 | private TreeRecyclerAdapter adapter = new TreeRecyclerAdapter();
28 |
29 | @Override
30 | protected void onCreate(@Nullable Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.activity_shopping_cart);
33 | RecyclerView rv_content = findViewById(R.id.rv_content);
34 | rv_content.setLayoutManager(new LinearLayoutManager(this));
35 | rv_content.setAdapter(adapter);
36 | List beans = new ArrayList<>();
37 | beans.add(new CartBean(3));
38 |
39 | List groupItem = ItemHelperFactory.createItems(beans);
40 |
41 | adapter.getItemManager().replaceAllItem(groupItem);
42 | adapter.setOnItemClickListener((viewHolder, position) -> {
43 | //因为外部和内部会冲突
44 | TreeItem item = adapter.getData(position);
45 | if (item != null) {
46 | item.onClick(viewHolder);
47 | }
48 | notifyPrice();
49 | });
50 | initView();
51 | notifyPrice();
52 | }
53 |
54 | /**
55 | * 更新价格
56 | */
57 | public void notifyPrice() {
58 | boolean isSelectAll = true;//默认全选
59 | int price = 0;
60 | for (TreeItem item : adapter.getData()) {
61 | if (item instanceof TreeSelectItemGroup) {
62 | TreeSelectItemGroup group = (TreeSelectItemGroup) item;
63 | if (!group.isSelect()) {//是否有选择的子类
64 | //有一个没选则不是全选
65 | isSelectAll = false;
66 | continue;
67 | }
68 | if (!group.isSelectAll()) {//是否全选了子类
69 | //有一个没选则不是全选
70 | isSelectAll = false;
71 | }
72 | List selectItems = group.getSelectItems();
73 | for (TreeItem child : selectItems) {
74 | if (child instanceof CartItem) {
75 | Integer data = (Integer) child.getData();
76 | price += data;
77 | }
78 | }
79 | }
80 | }
81 | adapter.notifyDataSetChanged();
82 |
83 | ((TextView) findViewById(R.id.tv_all_price)).setText("¥" + price);
84 | CheckBox checkBox = findViewById(R.id.cb_all_check);
85 | checkBox.setChecked(isSelectAll);
86 | }
87 |
88 | public void initView() {
89 | CheckBox checkBox = findViewById(R.id.cb_all_check);
90 | checkBox.setOnClickListener(v -> {
91 | for (TreeItem item : adapter.getData()) {
92 | if (item instanceof TreeSelectItemGroup) {
93 | TreeSelectItemGroup group = (TreeSelectItemGroup) item;
94 | group.selectAll(((CheckBox) v).isChecked());
95 | }
96 | }
97 | notifyPrice();
98 | });
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/activity/CityAt.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.activity;
2 |
3 | import android.os.Bundle;
4 | import android.os.Handler;
5 | import android.os.Message;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.support.v7.widget.DefaultItemAnimator;
8 | import android.support.v7.widget.GridLayoutManager;
9 | import android.support.v7.widget.RecyclerView;
10 | import android.util.Log;
11 |
12 | import com.alibaba.fastjson.JSON;
13 | import com.baozi.demo.R;
14 | import com.baozi.demo.item.city.ProvinceBean;
15 | import com.baozi.treerecyclerview.adpater.TreeRecyclerAdapter;
16 | import com.baozi.treerecyclerview.adpater.TreeRecyclerType;
17 | import com.baozi.treerecyclerview.factory.ItemHelperFactory;
18 | import com.baozi.treerecyclerview.item.TreeItem;
19 | import com.baozi.treerecyclerview.item.TreeItemGroup;
20 |
21 | import java.io.BufferedReader;
22 | import java.io.InputStreamReader;
23 | import java.lang.ref.WeakReference;
24 | import java.util.List;
25 |
26 | /**
27 | * 城市列表
28 | */
29 | public class CityAt extends AppCompatActivity {
30 | //根据item的状态展示,可折叠
31 | TreeRecyclerAdapter treeRecyclerAdapter = new TreeRecyclerAdapter(TreeRecyclerType.SHOW_EXPAND);
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 | setContentView(R.layout.layout_rv_content);
37 | RecyclerView recyclerView = findViewById(R.id.rv_content);
38 | recyclerView.setLayoutManager(new GridLayoutManager(this, 6));
39 | recyclerView.setItemAnimator(new DefaultItemAnimator());
40 | recyclerView.setAdapter(treeRecyclerAdapter);
41 | new Thread() {
42 | @Override
43 | public void run() {
44 | super.run();
45 | String string = getFromAssets("city.txt");
46 | List cityBeen = JSON.parseArray(string, ProvinceBean.class);
47 | refresh(cityBeen);
48 | }
49 | }.start();
50 |
51 | }
52 |
53 | public String getFromAssets(String fileName) {
54 | StringBuilder result = new StringBuilder();
55 | try {
56 | InputStreamReader inputReader = new InputStreamReader(getResources().getAssets().open(fileName));
57 | BufferedReader bufReader = new BufferedReader(inputReader);
58 | String line;
59 | while ((line = bufReader.readLine()) != null)
60 | result.append(line);
61 | return result.toString();
62 | } catch (Exception e) {
63 | e.printStackTrace();
64 | }
65 | return result.toString();
66 | }
67 |
68 | private void refresh(final List cityBeen) {
69 | runOnUiThread(() -> {
70 | //创建item
71 | //新的
72 | List items = ItemHelperFactory.createItems(cityBeen);
73 | //添加到adapter
74 | treeRecyclerAdapter.getItemManager().replaceAllItem(items);
75 | });
76 |
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/activity/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.activity;
2 |
3 | import android.content.Intent;
4 | import android.graphics.Rect;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 | import android.support.v4.app.Fragment;
8 | import android.support.v4.app.FragmentTransaction;
9 | import android.support.v7.app.AppCompatActivity;
10 | import android.support.v7.widget.LinearLayoutManager;
11 | import android.support.v7.widget.RecyclerView;
12 | import android.util.Log;
13 | import android.util.Pair;
14 | import android.view.View;
15 |
16 | import com.baozi.demo.R;
17 | import com.baozi.demo.fragment.ClickLoadFg;
18 | import com.baozi.demo.fragment.GalleryFg;
19 | import com.baozi.demo.fragment.MineFg;
20 | import com.baozi.demo.fragment.NewsFg;
21 | import com.baozi.demo.item.cart.CartGroupItem;
22 | import com.baozi.demo.item.city.AreaItem;
23 | import com.baozi.treerecyclerview.adpater.TreeRecyclerAdapter;
24 | import com.baozi.treerecyclerview.factory.ItemConfig;
25 | import com.baozi.treerecyclerview.item.SimpleTreeItem;
26 | import com.baozi.treerecyclerview.item.TreeItem;
27 |
28 | import java.util.ArrayList;
29 | import java.util.Arrays;
30 | import java.util.List;
31 |
32 | /**
33 | * @author jlanglang 2016/12/22 9:58
34 | * @版本 2.0
35 | * @Change
36 | */
37 | public class MainActivity extends AppCompatActivity {
38 | //数据集合
39 | private Pair[] itemPairs = {
40 | new Pair("三级城市", CityAt.class),
41 | new Pair("购物车", CartAt.class),
42 | new Pair("新闻", NewsFg.class),
43 | new Pair("索引", SortAt.class),
44 | new Pair("索引加侧滑删除", SwipeSortAt.class),
45 | new Pair("个人中心", MineFg.class),
46 | new Pair("淘宝首页", TBActivity.class),
47 | new Pair("点击懒加载", ClickLoadFg.class),
48 | new Pair("画廊", TestActivity.class)
49 | };
50 | private TreeRecyclerAdapter adapter = new TreeRecyclerAdapter();
51 |
52 | @Override
53 | protected void onCreate(@Nullable Bundle savedInstanceState) {
54 | super.onCreate(savedInstanceState);
55 | setContentView(R.layout.layout_rv_content);
56 | initRecyclerVIew();
57 | initData();
58 | ItemConfig.register(CartGroupItem.class);
59 |
60 | }
61 |
62 | /**
63 | * 简单创建Item
64 | */
65 | private void initData() {
66 | ArrayList items = new ArrayList<>();
67 | for (Pair itemPair : itemPairs) {
68 | SimpleTreeItem simpleTreeItem = new SimpleTreeItem(R.layout.item_mine)
69 | .onItemBind(viewHolder -> {
70 | Pair itemPair1 = itemPairs[viewHolder.getLayoutPosition()];
71 | viewHolder.setText(R.id.tv_name, (String) itemPair1.first);
72 | })
73 | .onItemClick(viewHolder -> {
74 | Pair itemPair12 = itemPairs[viewHolder.getLayoutPosition()];
75 | Class> aClass = (Class>) itemPair12.second;
76 | boolean isFragment = Fragment.class.isAssignableFrom(aClass);//判断是不是fragment的子类
77 | if (isFragment) {
78 | startFragment((Class) itemPair12.second);
79 | } else {
80 | startAt((Class) itemPair12.second);
81 | }
82 | });
83 | simpleTreeItem.setData(itemPair);
84 | items.add(simpleTreeItem);
85 | }
86 | adapter.getItemManager().replaceAllItem(items);
87 | }
88 |
89 | /**
90 | * 初始化列表
91 | */
92 | private void initRecyclerVIew() {
93 | RecyclerView rv_content = findViewById(R.id.rv_content);
94 | rv_content.setLayoutManager(new LinearLayoutManager(this));
95 | rv_content.setAdapter(adapter);
96 | rv_content.addItemDecoration(new RecyclerView.ItemDecoration() {
97 | @Override
98 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
99 | super.getItemOffsets(outRect, view, parent, state);
100 | outRect.top = 10;
101 | }
102 | });
103 | }
104 |
105 | public void startAt(Class zClass) {
106 | Intent intent = new Intent(this, zClass);
107 | startActivity(intent);
108 | }
109 |
110 | public void startFragment(Class zClass) {
111 | try {
112 | Fragment fragment = zClass.newInstance();
113 | FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
114 | fragmentTransaction.add(android.R.id.content, fragment, null);
115 | fragmentTransaction.addToBackStack(null);
116 | fragmentTransaction.commitAllowingStateLoss();
117 | } catch (InstantiationException e) {
118 | e.printStackTrace();
119 | } catch (IllegalAccessException e) {
120 | e.printStackTrace();
121 | }
122 | }
123 | }
124 |
125 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/activity/SortAt.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.activity;
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.RecyclerView;
7 | import android.widget.TextView;
8 |
9 | import com.baozi.demo.R;
10 | import com.baozi.demo.item.sort.IndexBar;
11 | import com.baozi.demo.item.sort.SortGroupItem;
12 | import com.baozi.treerecyclerview.item.TreeItem;
13 | import com.baozi.treerecyclerview.widget.TreeSortAdapter;
14 |
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | /**
19 | * Created by baozi on 2017/8/19.
20 | * 侧滑+索引
21 | */
22 |
23 | public class SortAt extends AppCompatActivity {
24 | private static final String[] LETTERS = new String[]{"A", "B", "C", "D",
25 | "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
26 | "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
27 | private TreeSortAdapter mTreeSortAdapter = new TreeSortAdapter();
28 | private LinearLayoutManager mLinearLayoutManager;
29 |
30 | @Override
31 | public void onCreate(Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | setContentView(R.layout.activity_sort);
34 | final RecyclerView rv_content = findViewById(R.id.rv_content);
35 | TextView tv_index = findViewById(R.id.tv_index);
36 | IndexBar qb_sort = findViewById(R.id.qb_sort);
37 | qb_sort.setOnIndexChangedListener(letter -> {
38 | int sortIndex = mTreeSortAdapter.getSortIndex(letter);
39 | mLinearLayoutManager.scrollToPositionWithOffset(sortIndex, 0);
40 | });
41 | qb_sort.setIndexs(LETTERS);
42 | qb_sort.setSelectedIndexTextView(tv_index);
43 |
44 | mLinearLayoutManager = new LinearLayoutManager(this);
45 | rv_content.setLayoutManager(mLinearLayoutManager);
46 | rv_content.setAdapter(mTreeSortAdapter);
47 | initData();
48 | }
49 |
50 |
51 | private void initData() {
52 | List groupItems = new ArrayList<>();
53 | for (String str : LETTERS) {
54 | SortGroupItem sortGroupItem = new SortGroupItem();
55 | sortGroupItem.setSortKey(str);
56 | sortGroupItem.setData(null);
57 | groupItems.add(sortGroupItem);
58 | }
59 | mTreeSortAdapter.getItemManager().replaceAllItem(groupItems);
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/activity/SwipeSortAt.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.activity;
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.LinearLayoutCompat;
7 | import android.support.v7.widget.LinearLayoutManager;
8 | import android.support.v7.widget.RecyclerView;
9 | import android.view.Gravity;
10 | import android.view.ViewGroup;
11 | import android.widget.TextView;
12 |
13 | import com.baozi.demo.R;
14 | import com.baozi.demo.item.sort.IndexBar;
15 | import com.baozi.demo.item.sort.SortGroupItem;
16 | import com.baozi.treerecyclerview.adpater.wrapper.HeaderWrapper;
17 | import com.baozi.treerecyclerview.adpater.wrapper.SwipeWrapper;
18 | import com.baozi.treerecyclerview.adpater.wrapper.TreeLoadWrapper;
19 | import com.baozi.treerecyclerview.item.SimpleTreeItem;
20 | import com.baozi.treerecyclerview.item.TreeItem;
21 | import com.baozi.treerecyclerview.widget.TreeSortAdapter;
22 |
23 | import java.util.ArrayList;
24 | import java.util.List;
25 |
26 | /**
27 | * Created by baozi on 2017/8/19.
28 | * 在SortActivity的代码逻辑上,加少部分代码实现
29 | */
30 |
31 | public class SwipeSortAt extends AppCompatActivity {
32 | private static final String[] LETTERS = new String[]{"A", "B", "C", "D",
33 | "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
34 | "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
35 | private TreeSortAdapter mTreeSortAdapter;
36 | private LinearLayoutManager mLinearLayoutManager;
37 | private TreeLoadWrapper mWrapper;
38 |
39 | @Override
40 | public void onCreate(Bundle savedInstanceState) {
41 | super.onCreate(savedInstanceState);
42 | setContentView(R.layout.activity_sort);
43 | RecyclerView rv_content = (RecyclerView) findViewById(R.id.rv_content);
44 | TextView tv_index = (TextView) findViewById(R.id.tv_index);
45 | IndexBar qb_sort = (IndexBar) findViewById(R.id.qb_sort);
46 | qb_sort.setOnIndexChangedListener(new IndexBar.OnIndexChangedListener() {
47 | @Override
48 | public void onIndexChanged(String letter) {
49 | int sortIndex = mTreeSortAdapter.getSortIndex(letter);
50 | mLinearLayoutManager.scrollToPositionWithOffset(sortIndex, 0);
51 | }
52 | });
53 | qb_sort.setIndexs(LETTERS);
54 | qb_sort.setSelectedIndexTextView(tv_index);
55 |
56 | mLinearLayoutManager = new GridLayoutManager(this, 2);
57 | rv_content.setLayoutManager(mLinearLayoutManager);
58 | //创建索引adapter
59 | mTreeSortAdapter = new TreeSortAdapter();
60 | mTreeSortAdapter.getItemManager().setOpenAnim(true);
61 | HeaderWrapper headerWrapper = new HeaderWrapper<>(mTreeSortAdapter);
62 | addHeadView(headerWrapper);
63 | //包装成侧滑删除列表
64 | SwipeWrapper adapter = new SwipeWrapper(headerWrapper);
65 | mWrapper = new TreeLoadWrapper(adapter);
66 | mWrapper.setEmptyView(new SimpleTreeItem(R.layout.layout_empty));
67 | mWrapper.setLoadingView(R.layout.layout_loading);
68 |
69 | rv_content.setAdapter(mWrapper);
70 |
71 | initData();
72 | }
73 |
74 | private void addHeadView(HeaderWrapper headerWrapper) {
75 | for (int i = 0; i < 5; i++) {
76 | //添加头部View1
77 | TextView headView = new TextView(this);
78 | headView.setText("headView" + i);
79 | headView.setGravity(Gravity.CENTER);
80 | headView.setLayoutParams(new LinearLayoutCompat.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 320));
81 | headerWrapper.addHeaderView(headView);
82 | }
83 | }
84 |
85 | private void initData() {
86 | final List groupItems = new ArrayList<>();
87 | for (int i = 0; i < LETTERS.length; i++) {
88 | SortGroupItem sortGroupItem = new SortGroupItem();
89 | sortGroupItem.setSortKey(LETTERS[i]);
90 | sortGroupItem.setData(i);
91 | groupItems.add(sortGroupItem);
92 | }
93 | new Thread(new Runnable() {
94 | @Override
95 | public void run() {
96 | try {
97 | Thread.sleep(1000);
98 | } catch (InterruptedException e) {
99 | e.printStackTrace();
100 | }
101 | runOnUiThread(new Runnable() {
102 | @Override
103 | public void run() {
104 | mWrapper.setType(TreeLoadWrapper.Type.REFRESH_OVER);
105 | mWrapper.getItemManager().notifyDataChanged();
106 | }
107 | });
108 | try {
109 | Thread.sleep(1000);
110 | } catch (InterruptedException e) {
111 | e.printStackTrace();
112 | }
113 | runOnUiThread(new Runnable() {
114 | @Override
115 | public void run() {
116 | mWrapper.setType(TreeLoadWrapper.Type.LOADING);
117 | }
118 | });
119 | try {
120 | Thread.sleep(2000);
121 | } catch (InterruptedException e) {
122 | e.printStackTrace();
123 | }
124 | runOnUiThread(new Runnable() {
125 | @Override
126 | public void run() {
127 | mWrapper.setType(TreeLoadWrapper.Type.REFRESH_OVER);
128 | mWrapper.getItemManager().replaceAllItem(groupItems);
129 | }
130 | });
131 | }
132 | }).start();
133 |
134 |
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/activity/TBActivity.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.activity;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.NonNull;
5 | import android.support.annotation.Nullable;
6 | import android.support.design.widget.TabLayout;
7 | import android.support.v4.app.Fragment;
8 | import android.support.v4.app.FragmentPagerAdapter;
9 | import android.support.v4.view.ViewPager;
10 | import android.support.v7.app.AppCompatActivity;
11 | import com.baozi.demo.R;
12 | import com.baozi.demo.fragment.MineFg;
13 |
14 | public class TBActivity extends AppCompatActivity {
15 |
16 | @Override
17 | protected void onCreate(@Nullable Bundle savedInstanceState){
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.activity_tb_home);
20 | ViewPager content = findViewById(R.id.content);
21 | content.setAdapter(new FragmentPagerAdapter(this.getSupportFragmentManager()) {
22 | @Override
23 | public Fragment getItem(int i) {
24 | return new MineFg();
25 | }
26 |
27 | @Override
28 | public int getCount() {
29 | return 5;
30 | }
31 |
32 | @NonNull
33 | @Override
34 | public CharSequence getPageTitle(int position) {
35 | return position + "";
36 | }
37 | });
38 | TabLayout tb_title = findViewById(R.id.tb_title);
39 | tb_title.setupWithViewPager(content);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/fragment/ClickLoadFg.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.fragment;
2 |
3 | import android.graphics.Color;
4 | import android.os.Bundle;
5 | import android.support.annotation.NonNull;
6 | import android.support.annotation.Nullable;
7 | import android.support.v4.app.Fragment;
8 | import android.support.v7.widget.GridLayoutManager;
9 | import android.support.v7.widget.RecyclerView;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 |
14 | import com.baozi.demo.R;
15 | import com.baozi.demo.item.clickload.ClickLoadGroupItem;
16 | import com.baozi.treerecyclerview.adpater.TreeRecyclerAdapter;
17 | import com.baozi.treerecyclerview.factory.ItemHelperFactory;
18 | import com.baozi.treerecyclerview.item.TreeItem;
19 |
20 | import java.util.Arrays;
21 |
22 | /**
23 | * 点击懒加载的demo
24 | */
25 | public class ClickLoadFg extends Fragment {
26 | RecyclerView view;
27 | private TreeRecyclerAdapter adapter = new TreeRecyclerAdapter();
28 |
29 | @Nullable
30 | @Override
31 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
32 | if (view == null) {
33 | view = (RecyclerView) inflater.inflate(R.layout.layout_rv_content, container, false);
34 | view.setBackgroundColor(Color.GRAY);
35 | }
36 | return view;
37 | }
38 |
39 | @Override
40 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
41 | super.onActivityCreated(savedInstanceState);
42 | //初始化recyclerView
43 | view.setLayoutManager(new GridLayoutManager(view.getContext(), 4));
44 | view.setAdapter(adapter);
45 | TreeItem treeItem = ItemHelperFactory.createItem(new String[]{}, ClickLoadGroupItem.class, null);
46 | adapter.getItemManager().replaceAllItem(Arrays.asList(treeItem));
47 | adapter.setOnItemClickListener((viewHolder, position) -> {
48 | TreeItem item = adapter.getData(position);
49 | if (item == null || item.getData() == null) {
50 | return;
51 | }
52 | if (item instanceof ClickLoadGroupItem) {
53 | ClickLoadGroupItem clickLoadGroupItem = (ClickLoadGroupItem) item;
54 | if (clickLoadGroupItem.getChild() == null || clickLoadGroupItem.getChild().isEmpty()) {
55 | clickLoadGroupItem.setData(new String[]{"1", "2", "3"});
56 | clickLoadGroupItem.setExpand(true);
57 | }
58 | }
59 | });
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/fragment/GalleryFg.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.fragment;
2 |
3 | import android.animation.ObjectAnimator;
4 | import android.animation.ValueAnimator;
5 | import android.graphics.Rect;
6 | import android.os.Bundle;
7 | import android.support.annotation.NonNull;
8 | import android.support.annotation.Nullable;
9 | import android.support.v7.widget.LinearLayoutManager;
10 | import android.support.v7.widget.LinearSnapHelper;
11 | import android.support.v7.widget.PagerSnapHelper;
12 | import android.support.v7.widget.RecyclerView;
13 | import android.util.Log;
14 | import android.view.View;
15 | import android.widget.ImageView;
16 | import android.widget.TextView;
17 |
18 | import com.baozi.demo.R;
19 | import com.baozi.treerecyclerview.adpater.TreeRecyclerAdapter;
20 | import com.baozi.treerecyclerview.item.SimpleTreeItem;
21 | import com.baozi.treerecyclerview.item.TreeItem;
22 |
23 | import java.util.ArrayList;
24 | import java.util.List;
25 |
26 | public class GalleryFg extends SimpleRecyclerViewFg {
27 | private LinearSnapHelper snapHelper = new LinearSnapHelper();
28 | LinearLayoutManager linearLayoutManager;
29 |
30 | @Override
31 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
32 | super.onActivityCreated(savedInstanceState);
33 |
34 | linearLayoutManager = new LinearLayoutManager(context, 0, false);
35 | recyclerView.setLayoutManager(linearLayoutManager);
36 | snapHelper.attachToRecyclerView(recyclerView);
37 | recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
38 | @Override
39 | public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
40 | super.onScrolled(recyclerView, dx, dy);
41 | scaleItem();
42 | }
43 | });
44 | adapter.getItemManager().replaceAllItem(getItems());
45 | }
46 |
47 | public void scaleItem() {
48 | int first = linearLayoutManager.findFirstVisibleItemPosition();
49 | int last = linearLayoutManager.findLastVisibleItemPosition();
50 | int center = first + (last - first) / 2;
51 | int range = last - first;
52 | Log.i("position", first + ":" + last + ":" + center + ":" + range);
53 | for (int i = 0; i < range; i++) {
54 | RecyclerView.ViewHolder item = recyclerView.findViewHolderForLayoutPosition(first + i);
55 | if (item == null) {
56 | return;
57 | }
58 | if ((first + i) == center) {
59 | item.itemView.setScaleY(1.2f);
60 | continue;
61 | }
62 | item.itemView.setScaleY(1f);
63 | }
64 | }
65 |
66 | public List getItems() {
67 | ArrayList list = new ArrayList<>();
68 | for (int i = 0; i < 20; i++) {
69 | list.add(
70 | new SimpleTreeItem(R.layout.item_grallery)
71 | .setTreeOffset(new Rect(20, 20, 20, 20))
72 | .onItemBind(viewHolder -> {
73 | TextView itemView = (TextView) viewHolder.itemView;
74 | itemView.setText(viewHolder.getLayoutPosition() + "");
75 | viewHolder.itemView.setScaleY(1);
76 | })
77 | );
78 | }
79 | return list;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/fragment/MineFg.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.fragment;
2 |
3 | import android.graphics.Color;
4 | import android.graphics.Rect;
5 | import android.os.Bundle;
6 | import android.support.annotation.NonNull;
7 | import android.support.annotation.Nullable;
8 | import android.support.v4.app.Fragment;
9 | import android.support.v7.widget.GridLayoutManager;
10 | import android.support.v7.widget.RecyclerView;
11 | import android.view.LayoutInflater;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 |
15 | import com.baozi.demo.R;
16 | import com.baozi.demo.item.mine.MineCategoryBean;
17 | import com.baozi.demo.item.mine.MineItem;
18 | import com.baozi.treerecyclerview.adpater.TreeRecyclerAdapter;
19 | import com.baozi.treerecyclerview.factory.ItemHelperFactory;
20 | import com.baozi.treerecyclerview.item.SimpleTreeItem;
21 | import com.baozi.treerecyclerview.item.TreeItem;
22 |
23 | import java.util.Arrays;
24 | import java.util.List;
25 |
26 | //RecyclerView实现首页我的页面
27 | public class MineFg extends Fragment {
28 |
29 | private RecyclerView view;
30 | private TreeRecyclerAdapter adapter = new TreeRecyclerAdapter();
31 | private List heads = Arrays.asList(
32 | new MineCategoryBean("公开文章", null, "39", true),
33 | new MineCategoryBean("关注", null, "57", true),
34 | new MineCategoryBean("粉丝", null, "501", true),
35 | new MineCategoryBean("每日签到", "1", null, true)
36 | );
37 | private List category = Arrays.asList(
38 | new MineCategoryBean("私密文章", "1", null),
39 | new MineCategoryBean("我的收藏", "1", null),
40 | new MineCategoryBean("我的喜欢", "1", null),
41 | new MineCategoryBean("已购内容", "1", null),
42 | new MineCategoryBean("我的专题", "1", null, true),
43 | new MineCategoryBean("我的文集", "1", null, true),
44 | new MineCategoryBean("关注内容", "1", null, true),
45 | new MineCategoryBean("我的钱包", "1", null, true)
46 | );
47 | private List item = Arrays.asList("条目1", "条目2", "条目3", "条目4", "条目5", "条目6");
48 |
49 | @Nullable
50 | @Override
51 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
52 | if (view == null) {
53 | view = (RecyclerView) inflater.inflate(R.layout.layout_rv_content, container, false);
54 | view.setBackgroundColor(Color.GRAY);
55 | }
56 | return view;
57 | }
58 |
59 | @Override
60 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
61 | super.onActivityCreated(savedInstanceState);
62 | //初始化recyclerView
63 | view.setLayoutManager(new GridLayoutManager(view.getContext(), 4));
64 | view.setAdapter(adapter);
65 | adapter.getItemManager().clean();
66 | //添加头部
67 | adapter.getItemManager().addItem(
68 | new SimpleTreeItem(R.layout.item_mine_head)
69 | .setTreeOffset(new Rect(0, 0, 0, 2))
70 | );
71 | //添加头部分类item
72 | adapter.getItemManager().addItems(ItemHelperFactory.createItems(heads));
73 | //添加分类item
74 | adapter.getItemManager().addItems(ItemHelperFactory.createItems(category));
75 | //添加横条item
76 | adapter.getItemManager().addItems(ItemHelperFactory.createItems(item, MineItem.class));
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/fragment/NewsFg.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.fragment;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.support.v7.widget.GridLayoutManager;
7 | import android.support.v7.widget.LinearLayoutManager;
8 | import android.support.v7.widget.RecyclerView;
9 |
10 | import com.baozi.demo.R;
11 | import com.baozi.demo.fragment.SimpleRecyclerViewFg;
12 | import com.baozi.demo.item.news.NewsItemBean;
13 | import com.baozi.treerecyclerview.adpater.TreeRecyclerAdapter;
14 | import com.baozi.treerecyclerview.adpater.TreeRecyclerType;
15 | import com.baozi.treerecyclerview.factory.ItemHelperFactory;
16 | import com.baozi.treerecyclerview.item.TreeItem;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 | import java.util.Random;
21 |
22 | /**
23 | * @author jlanglang 2017/7/5 10:22
24 | * @版本 2017-8-19;有点勉强,不建议这样使用- -
25 | */
26 |
27 | public class NewsFg extends SimpleRecyclerViewFg {
28 | protected TreeRecyclerAdapter adapter = new TreeRecyclerAdapter(TreeRecyclerType.SHOW_ALL);
29 |
30 | @Override
31 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
32 | super.onActivityCreated(savedInstanceState);
33 | recyclerView.setLayoutManager(new GridLayoutManager(context, 6));
34 | recyclerView.setAdapter(adapter);
35 | ArrayList list = new ArrayList<>();
36 | for (int i = 0; i < 5; i++) {
37 | NewsItemBean newsItemBean = new NewsItemBean();
38 | newsItemBean.title = "123";
39 | newsItemBean.images = new Random().nextInt(9) + 1;
40 | list.add(newsItemBean);
41 | }
42 | List itemList = ItemHelperFactory.createItems(list);
43 | adapter.getItemManager().replaceAllItem(itemList);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/fragment/SimpleRecyclerViewFg.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.fragment;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.os.Bundle;
6 | import android.support.annotation.NonNull;
7 | import android.support.annotation.Nullable;
8 | import android.support.v4.app.Fragment;
9 | import android.support.v7.widget.DefaultItemAnimator;
10 | import android.support.v7.widget.LinearLayoutManager;
11 | import android.support.v7.widget.RecyclerView;
12 | import android.view.LayoutInflater;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 |
16 | import com.baozi.demo.R;
17 | import com.baozi.treerecyclerview.adpater.TreeRecyclerAdapter;
18 | import com.baozi.treerecyclerview.base.BaseRecyclerAdapter;
19 |
20 |
21 | public abstract class SimpleRecyclerViewFg extends Fragment {
22 | protected RecyclerView recyclerView;
23 | protected Context context;
24 | protected TreeRecyclerAdapter adapter = new TreeRecyclerAdapter();
25 |
26 | @Override
27 | public void onAttach(Context context) {
28 | super.onAttach(context);
29 | this.context = context;
30 | }
31 |
32 | @Nullable
33 | @Override
34 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
35 | if (recyclerView == null) {
36 | recyclerView = (RecyclerView) inflater.inflate(R.layout.layout_rv_content, container, false);
37 | recyclerView.setBackgroundColor(Color.GRAY);
38 | }
39 | return recyclerView;
40 | }
41 |
42 | @Override
43 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
44 | super.onActivityCreated(savedInstanceState);
45 | recyclerView.setItemAnimator(new DefaultItemAnimator());
46 | recyclerView.setLayoutManager(new LinearLayoutManager(context));
47 | recyclerView.setAdapter(adapter);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/cart/CartBean.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.cart;
2 |
3 | import com.baozi.treerecyclerview.annotation.TreeDataType;
4 |
5 |
6 | @TreeDataType(bindField = "type")
7 | public class CartBean {
8 | int childSum; //子条目数量
9 | public int type = 1;
10 |
11 | public CartBean(int childSum) {
12 | this.childSum = childSum;
13 | }
14 |
15 | @TreeDataType(iClass = CartGroupItem2.class)
16 | public static class CartBean2 {
17 | int childSum; //子条目数量
18 |
19 | public CartBean2(int childSum) {
20 | this.childSum = childSum;
21 | }
22 |
23 | @TreeDataType(iClass = CartGroupItem3.class)
24 | public static class CartBean3 {
25 | int childSum; //子条目数量
26 |
27 | public CartBean3(int childSum) {
28 | this.childSum = childSum;
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/cart/CartGroupItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.cart;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 | import android.view.View;
6 | import android.widget.CheckBox;
7 |
8 | import com.baozi.demo.R;
9 | import com.baozi.demo.activity.CartAt;
10 | import com.baozi.treerecyclerview.annotation.TreeItemType;
11 | import com.baozi.treerecyclerview.base.ViewHolder;
12 | import com.baozi.treerecyclerview.factory.ItemHelperFactory;
13 | import com.baozi.treerecyclerview.item.TreeItem;
14 | import com.baozi.treerecyclerview.item.TreeSelectItemGroup;
15 |
16 | import java.util.ArrayList;
17 | import java.util.List;
18 |
19 | /**
20 | * Created by a123 on 2018/6/5.
21 | */
22 | @TreeItemType(type = {"1"})
23 | public class CartGroupItem extends TreeSelectItemGroup {
24 |
25 | @Nullable
26 | @Override
27 | protected List initChild(CartBean data) {
28 | ArrayList list = new ArrayList<>();
29 | for (int i = 0; i < data.childSum; i++) {
30 | list.add(new CartBean.CartBean2(2));
31 | }
32 | return ItemHelperFactory.createItems(list, this);
33 | }
34 |
35 | @Override
36 | public int getLayoutId() {
37 | return R.layout.item_cart_group;
38 | }
39 |
40 | @Override
41 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
42 | viewHolder.setText(R.id.cb_ischeck, "电脑(一级)");
43 | viewHolder.setChecked(R.id.cb_ischeck, isSelect());
44 | viewHolder.getView(R.id.cb_ischeck).setOnClickListener((v) -> {
45 | selectAll(!isSelectAll(), true);
46 | ((CartAt) viewHolder.itemView.getContext()).notifyPrice();
47 | });
48 | viewHolder.itemView.setPadding(0, 0, 0, 0);
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/cart/CartGroupItem2.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.cart;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 | import android.widget.CheckBox;
6 |
7 | import com.baozi.demo.R;
8 | import com.baozi.demo.activity.CartAt;
9 | import com.baozi.treerecyclerview.base.ViewHolder;
10 | import com.baozi.treerecyclerview.factory.ItemHelperFactory;
11 | import com.baozi.treerecyclerview.item.TreeItem;
12 | import com.baozi.treerecyclerview.item.TreeSelectItemGroup;
13 |
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | /**
18 | * Created by a123 on 2018/6/5.
19 | */
20 | public class CartGroupItem2 extends TreeSelectItemGroup {
21 |
22 | @Nullable
23 | @Override
24 | protected List initChild(CartBean.CartBean2 data) {
25 | ArrayList list = new ArrayList<>();
26 | for (int i = 0; i < data.childSum; i++) {
27 | list.add(new CartBean.CartBean2.CartBean3(3));
28 | }
29 | return ItemHelperFactory.createItems(list, this);
30 | }
31 |
32 | @Override
33 | public int getLayoutId() {
34 | return R.layout.item_cart_group;
35 | }
36 |
37 | @Override
38 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
39 | viewHolder.setText(R.id.cb_ischeck, "笔记本(二级)");
40 | viewHolder.setChecked(R.id.cb_ischeck, isSelect());
41 | viewHolder.getView(R.id.cb_ischeck).setOnClickListener((v) -> {
42 | selectAll(!isSelectAll(), true);
43 | ((CartAt) viewHolder.itemView.getContext()).notifyPrice();
44 | });
45 | viewHolder.itemView.setPadding(20, 0, 0, 0);
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/cart/CartGroupItem3.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.cart;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 | import android.widget.CheckBox;
6 |
7 | import com.baozi.demo.R;
8 | import com.baozi.demo.activity.CartAt;
9 | import com.baozi.treerecyclerview.annotation.TreeItemType;
10 | import com.baozi.treerecyclerview.base.ViewHolder;
11 | import com.baozi.treerecyclerview.factory.ItemHelperFactory;
12 | import com.baozi.treerecyclerview.item.TreeItem;
13 | import com.baozi.treerecyclerview.item.TreeSelectItemGroup;
14 |
15 | import java.util.ArrayList;
16 | import java.util.List;
17 | import java.util.Random;
18 |
19 | /**
20 | * Created by a123 on 2018/6/5.
21 | */
22 | @TreeItemType(type = "1")
23 | public class CartGroupItem3 extends TreeSelectItemGroup {
24 |
25 | @Nullable
26 | @Override
27 | protected List initChild(CartBean.CartBean2.CartBean3 data) {
28 | ArrayList list = new ArrayList<>();
29 | for (int i = 0; i < data.childSum; i++) {
30 | list.add(new Random().nextInt(300));
31 | }
32 | return ItemHelperFactory.createItems(list, CartItem.class, this);
33 | }
34 |
35 | @Override
36 | public int getLayoutId() {
37 | return R.layout.item_cart_group;
38 | }
39 |
40 | @Override
41 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
42 | viewHolder.setText(R.id.cb_ischeck, "联想(三级)");
43 | viewHolder.setChecked(R.id.cb_ischeck, isSelect());
44 | viewHolder.getView(R.id.cb_ischeck).setOnClickListener((v) -> {
45 | selectAll(!isSelectAll(), true);
46 | ((CartAt) viewHolder.itemView.getContext()).notifyPrice();
47 | });
48 | viewHolder.itemView.setPadding(40, 0, 0, 0);
49 | }
50 |
51 | @Override
52 | public boolean onInterceptClick(TreeItem child) {
53 | selectItem(child, true);
54 | return super.onInterceptClick(child);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/cart/CartItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.cart;
2 |
3 | import android.graphics.Rect;
4 | import android.support.annotation.NonNull;
5 | import android.support.v7.widget.RecyclerView;
6 |
7 | import com.baozi.demo.R;
8 | import com.baozi.treerecyclerview.base.ViewHolder;
9 | import com.baozi.treerecyclerview.item.TreeItem;
10 | import com.baozi.treerecyclerview.item.TreeItemGroup;
11 |
12 | /**
13 | * Created by a123 on 2018/6/5.
14 | */
15 |
16 | public class CartItem extends TreeItem {
17 |
18 |
19 | @Override
20 | public int getLayoutId() {
21 | return R.layout.item_cart_child;
22 | }
23 |
24 | @Override
25 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
26 | TreeItemGroup parentItem = getParentItem();
27 | if (parentItem instanceof CartGroupItem3) {
28 | viewHolder.setChecked(R.id.cb_ischeck, ((CartGroupItem3) parentItem).isSelect(this));
29 | }
30 | viewHolder.setText(R.id.tv_price, data + "");
31 | viewHolder.itemView.setPadding(50, 0, 0, 0);
32 |
33 | }
34 |
35 |
36 | @Override
37 | public void getItemOffsets(@NonNull Rect outRect, RecyclerView.LayoutParams layoutParams, int position) {
38 | super.getItemOffsets(outRect, layoutParams, position);
39 | outRect.bottom = 1;
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/city/AreaItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.city;
2 |
3 | import android.graphics.Rect;
4 | import android.support.annotation.NonNull;
5 | import android.support.v7.widget.RecyclerView;
6 |
7 | import com.baozi.demo.R;
8 | import com.baozi.treerecyclerview.annotation.TreeItemType;
9 | import com.baozi.treerecyclerview.base.ViewHolder;
10 | import com.baozi.treerecyclerview.item.TreeItem;
11 |
12 | /**
13 | *
14 | */
15 | public class AreaItem extends TreeItem {
16 |
17 | @Override
18 | public int getLayoutId() {
19 | return R.layout.item_three;
20 | }
21 |
22 | @Override
23 | public void onBindViewHolder(@NonNull ViewHolder holder) {
24 | holder.setText(R.id.tv_content, data.areaName);
25 | }
26 |
27 | @Override
28 | public int getSpanSize(int maxSpan) {
29 | return maxSpan / 3;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/city/CountyItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.city;
2 |
3 | import android.graphics.Rect;
4 | import android.support.annotation.NonNull;
5 | import android.support.v7.widget.RecyclerView;
6 |
7 | import com.baozi.demo.R;
8 | import com.baozi.treerecyclerview.factory.ItemHelperFactory;
9 | import com.baozi.treerecyclerview.base.ViewHolder;
10 | import com.baozi.treerecyclerview.item.TreeItem;
11 | import com.baozi.treerecyclerview.item.TreeItemGroup;
12 |
13 | import java.util.List;
14 |
15 | /**
16 | *
17 | */
18 | public class CountyItem extends TreeItemGroup {
19 |
20 | @Override
21 | public List initChild(ProvinceBean.CityBean data) {
22 | return ItemHelperFactory.createItems(data.areas, this);
23 | }
24 |
25 | @Override
26 | public int getLayoutId() {
27 | return R.layout.item_two;
28 | }
29 |
30 | @Override
31 | public void onBindViewHolder(@NonNull ViewHolder holder) {
32 | holder.setText(R.id.tv_content, data.cityName);
33 | }
34 |
35 | @Override
36 | public void getItemOffsets(@NonNull Rect outRect, RecyclerView.LayoutParams layoutParams, int position) {
37 | super.getItemOffsets(outRect, layoutParams, position);
38 | outRect.top = 1;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/city/ProvinceItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.city;
2 |
3 | import android.graphics.Rect;
4 | import android.support.annotation.NonNull;
5 | import android.support.v7.widget.RecyclerView;
6 |
7 | import com.baozi.demo.R;
8 | import com.baozi.treerecyclerview.factory.ItemHelperFactory;
9 | import com.baozi.treerecyclerview.item.TreeItem;
10 | import com.baozi.treerecyclerview.base.ViewHolder;
11 | import com.baozi.treerecyclerview.item.TreeItemGroup;
12 | import com.baozi.treerecyclerview.manager.ItemManager;
13 |
14 | import java.util.List;
15 |
16 | /**
17 | * Created by baozi on 2016/12/8.
18 | */
19 | public class ProvinceItem extends TreeItemGroup {
20 | @Override
21 | protected void init() {
22 | super.init();
23 | setExpand(false);
24 | }
25 |
26 | @Override
27 | public List initChild(ProvinceBean data) {
28 | List items = ItemHelperFactory.createItems(data.citys, this);
29 | for (int i = 0; i < items.size(); i++) {
30 | TreeItemGroup treeItem = (TreeItemGroup) items.get(i);
31 | treeItem.setExpand(false);
32 | }
33 | return items;
34 | }
35 |
36 | @Override
37 | public int getLayoutId() {
38 | return R.layout.itme_one;
39 | }
40 |
41 | @Override
42 | public boolean isCanExpand() {
43 | return true;
44 | }
45 |
46 | @Override
47 | public void onBindViewHolder(@NonNull ViewHolder holder) {
48 | holder.setText(R.id.tv_content, data.provinceName);
49 | }
50 |
51 | @Override
52 | public void getItemOffsets(@NonNull Rect outRect, RecyclerView.LayoutParams layoutParams, int position) {
53 | super.getItemOffsets(outRect, layoutParams, position);
54 | outRect.bottom = 1;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/clickload/ClickLoadChildItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.clickload;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 |
6 | import com.baozi.demo.R;
7 | import com.baozi.treerecyclerview.base.ViewHolder;
8 | import com.baozi.treerecyclerview.factory.ItemHelperFactory;
9 | import com.baozi.treerecyclerview.item.TreeItem;
10 | import com.baozi.treerecyclerview.item.TreeItemGroup;
11 |
12 | import java.util.Arrays;
13 | import java.util.List;
14 |
15 | public class ClickLoadChildItem extends TreeItem {
16 | @Override
17 | public int getLayoutId() {
18 | return R.layout.item_sort_child;
19 | }
20 |
21 | @Override
22 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/clickload/ClickLoadGroupItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.clickload;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.annotation.Nullable;
5 |
6 | import com.baozi.demo.R;
7 | import com.baozi.treerecyclerview.base.ViewHolder;
8 | import com.baozi.treerecyclerview.factory.ItemHelperFactory;
9 | import com.baozi.treerecyclerview.item.TreeItem;
10 | import com.baozi.treerecyclerview.item.TreeItemGroup;
11 |
12 | import java.util.Arrays;
13 | import java.util.List;
14 |
15 | public class ClickLoadGroupItem extends TreeItemGroup {
16 | @Override
17 | public int getLayoutId() {
18 | return R.layout.item_sort_group;
19 | }
20 |
21 | @Nullable
22 | @Override
23 | protected List initChild(String[] data) {
24 | return ItemHelperFactory.createItems(Arrays.asList(data), ClickLoadChildItem.class, this);
25 | }
26 |
27 | @Override
28 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
29 |
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/mine/MineCategoryBean.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.mine;
2 |
3 | import com.baozi.treerecyclerview.annotation.TreeDataType;
4 |
5 | @TreeDataType(iClass = MineCategoryItem.class)
6 | public class MineCategoryBean {
7 | public String title;
8 | public String url;//
9 | public String content;
10 | public boolean isEnd;
11 |
12 | /**
13 | * @param content 内容
14 | * @param url 图片,如果为null则隐藏
15 | * @param title 如果为null则隐藏
16 | */
17 | public MineCategoryBean(String content, String url, String title) {
18 | this(content, url, title, false);
19 | }
20 |
21 | /**
22 | * @param content 内容
23 | * @param url 图片,如果为null则隐藏
24 | * @param title 如果为null则隐藏
25 | * @param isEnd 是否是该组最后一排
26 | */
27 | public MineCategoryBean(String content, String url, String title, boolean isEnd) {
28 | this.title = title;
29 | this.url = url;
30 | this.content = content;
31 | this.isEnd = isEnd;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/mine/MineCategoryItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.mine;
2 |
3 | import android.graphics.Rect;
4 | import android.support.annotation.NonNull;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.text.TextUtils;
7 |
8 | import com.baozi.demo.R;
9 | import com.baozi.treerecyclerview.base.ViewHolder;
10 | import com.baozi.treerecyclerview.item.TreeItem;
11 |
12 | /**
13 | * 分类
14 | */
15 | public class MineCategoryItem extends TreeItem {
16 | @Override
17 | public int getLayoutId() {
18 | return R.layout.item_mine_category;
19 | }
20 |
21 | @Override
22 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
23 | viewHolder.setText(R.id.tv_content, data.content);
24 |
25 | viewHolder.setVisible(R.id.tv_title, !TextUtils.isEmpty(data.title));
26 | viewHolder.setText(R.id.tv_title, data.title);
27 |
28 | viewHolder.setVisible(R.id.iv_content, !TextUtils.isEmpty(data.url));
29 |
30 | }
31 |
32 | @Override
33 | public int getSpanSize(int maxSpan) {
34 | return maxSpan / 4;
35 | }
36 |
37 | @Override
38 | public void getItemOffsets(@NonNull Rect outRect, RecyclerView.LayoutParams layoutParams, int position) {
39 | super.getItemOffsets(outRect, layoutParams, position);
40 | if (data.isEnd){
41 | outRect.bottom = 20;
42 | }else {
43 | outRect.bottom = 0;
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/mine/MineHeadItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.mine;
2 |
3 | import android.graphics.Rect;
4 | import android.support.annotation.NonNull;
5 | import android.support.v7.widget.RecyclerView;
6 |
7 | import com.baozi.demo.R;
8 | import com.baozi.treerecyclerview.base.ViewHolder;
9 | import com.baozi.treerecyclerview.item.TreeItem;
10 |
11 | public class MineHeadItem extends TreeItem {
12 | @Override
13 | public int getLayoutId() {
14 | return R.layout.item_mine_head;
15 | }
16 |
17 | @Override
18 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
19 | }
20 |
21 | @Override
22 | public void getItemOffsets(@NonNull Rect outRect, RecyclerView.LayoutParams layoutParams, int position) {
23 | super.getItemOffsets(outRect, layoutParams, position);
24 | outRect.bottom = 1;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/mine/MineItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.mine;
2 |
3 | import android.graphics.Rect;
4 | import android.support.annotation.NonNull;
5 | import android.support.v7.widget.RecyclerView;
6 |
7 | import com.baozi.demo.R;
8 | import com.baozi.treerecyclerview.base.ViewHolder;
9 | import com.baozi.treerecyclerview.item.TreeItem;
10 |
11 | public class MineItem extends TreeItem {
12 | @Override
13 | public int getLayoutId() {
14 | return R.layout.item_mine;
15 | }
16 |
17 | @Override
18 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
19 | viewHolder.setText(R.id.tv_name, data);
20 | }
21 |
22 | @Override
23 | public void getItemOffsets(@NonNull Rect outRect, RecyclerView.LayoutParams layoutParams, int position) {
24 | super.getItemOffsets(outRect, layoutParams, position);
25 | outRect.top = 2;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/news/NewsImageItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.news;
2 |
3 | import android.graphics.Rect;
4 | import android.support.annotation.NonNull;
5 | import android.support.v7.widget.RecyclerView;
6 |
7 | import com.baozi.demo.R;
8 | import com.baozi.treerecyclerview.base.ViewHolder;
9 | import com.baozi.treerecyclerview.item.TreeItem;
10 |
11 | /**
12 | * @author jlanglang 2017/7/5 17:15
13 | * @版本 2.0
14 | * @Change
15 | */
16 |
17 | public class NewsImageItem extends TreeItem {
18 | @Override
19 | public int getLayoutId() {
20 | return R.layout.item_news_image;
21 | }
22 |
23 | @Override
24 | public int getSpanSize(int maxSpan) {
25 | return maxSpan / 3;
26 | }
27 |
28 | @Override
29 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
30 |
31 | }
32 |
33 | @Override
34 | public void getItemOffsets(@NonNull Rect outRect, RecyclerView.LayoutParams layoutParams, int position) {
35 | super.getItemOffsets(outRect, layoutParams, position);
36 | outRect.set(1, 1, 1, 1);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/news/NewsItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.news;
2 |
3 | import android.graphics.Rect;
4 | import android.support.annotation.NonNull;
5 |
6 | import com.baozi.demo.R;
7 | import com.baozi.treerecyclerview.base.ViewHolder;
8 | import com.baozi.treerecyclerview.factory.ItemHelperFactory;
9 | import com.baozi.treerecyclerview.item.SimpleTreeItem;
10 | import com.baozi.treerecyclerview.item.TreeItem;
11 | import com.baozi.treerecyclerview.item.TreeItemGroup;
12 |
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | /**
17 | * @author jlanglang 2017/7/5 17:15
18 | * @版本 2.0
19 | * @Change
20 | */
21 | //新闻列表,一级父
22 | public class NewsItem extends TreeItemGroup {
23 | @Override
24 | protected List initChild(NewsItemBean data) {
25 | //添加图片
26 | int images = data.images;
27 | ArrayList child = new ArrayList<>();
28 | for (int i = 0; i < images; i++) {
29 | child.add("");
30 | }
31 | List treeItemList = ItemHelperFactory.createItems(child, NewsImageItem.class, this);
32 |
33 | //添加尾部
34 | treeItemList.add(new SimpleTreeItem(R.layout.item_news_foot)
35 | .onItemClick(viewHolder -> {
36 | //点击跳转
37 | }).setTreeOffset(new Rect(0, 0, 0, 20)));
38 | return treeItemList;
39 | }
40 |
41 | @Override
42 | public int getLayoutId() {
43 | return R.layout.item_news_title;
44 | }
45 |
46 | @Override
47 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
48 | viewHolder.setText(R.id.tv_title, data.title);
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/news/NewsItemBean.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.news;
2 |
3 | import com.baozi.treerecyclerview.annotation.TreeDataType;
4 |
5 | /**
6 | * @author jlanglang 2017/7/5 17:34
7 | * @版本 2.0
8 | * @Change
9 | */
10 | @TreeDataType(iClass = NewsItem.class)
11 | public class NewsItemBean {
12 | public String title;
13 | public int images;
14 | }
15 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/sort/IndexBar.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.sort;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.graphics.Rect;
7 | import android.util.AttributeSet;
8 | import android.view.MotionEvent;
9 | import android.view.View;
10 | import android.widget.TextView;
11 |
12 |
13 | /**
14 | * Created by SouthernBox on 2016/10/25 0025.
15 | * 侧边索引栏控件
16 | */
17 |
18 | public class IndexBar extends View {
19 |
20 | /**
21 | * 索引字母颜色
22 | */
23 | private static final int LETTER_COLOR = 0xFF2e2e2e;
24 | /**
25 | * 按下颜色
26 | */
27 | private static final int DOWN_COLOR = 0x11000000;
28 | /**
29 | * 抬起颜色
30 | */
31 | private static final int UP_COLOR = 0x00000000;
32 | /**
33 | * 索引字母数组
34 | */
35 | public String[] indexs = {};
36 |
37 | /**
38 | * 控件的宽高
39 | */
40 | private int mWidth;
41 | private int mHeight;
42 |
43 | /**
44 | * 单元格的高度
45 | */
46 | private float mCellHeight;
47 |
48 | /**
49 | * 顶部间距
50 | */
51 | private float mMarginTop;
52 |
53 | private Paint mPaint;
54 |
55 | public IndexBar(Context context) {
56 | super(context);
57 | init();
58 | }
59 |
60 | public IndexBar(Context context, AttributeSet attrs) {
61 | super(context, attrs);
62 | init();
63 | }
64 |
65 | private void init() {
66 | mPaint = new Paint();
67 | mPaint.setColor(LETTER_COLOR);
68 | mPaint.setTextSize(36);
69 | mPaint.setAntiAlias(true); // 去掉锯齿,让字体边缘变得平滑
70 | }
71 |
72 | public void setIndexs(String[] indexs) {
73 | this.indexs = indexs;
74 | mMarginTop = (mHeight - mCellHeight * indexs.length) / 2;
75 | invalidate();
76 | }
77 |
78 | @Override
79 | protected void onDraw(Canvas canvas) {
80 | //字母的坐标点:(x,y)
81 | if (indexs.length <= 0) {
82 | return;
83 | }
84 | for (int i = 0; i < indexs.length; i++) {
85 | String letter = indexs[i];
86 | float x = mWidth / 2 - getTextWidth(letter) / 2;
87 | float y = mCellHeight / 2 + getTextHeight(letter) / 2 + mCellHeight * i + mMarginTop;
88 | canvas.drawText(letter, x, y, mPaint);
89 | }
90 | }
91 |
92 | /**
93 | * 获取字符的宽度
94 | *
95 | * @param text 需要测量的字母
96 | * @return 对应字母的高度
97 | */
98 | public float getTextWidth(String text) {
99 | Rect bounds = new Rect();
100 | mPaint.getTextBounds(text, 0, text.length(), bounds);
101 | return bounds.width();
102 | }
103 |
104 | /**
105 | * 获取字符的高度
106 | *
107 | * @param text 需要测量的字母
108 | * @return 对应字母的高度
109 | */
110 | public float getTextHeight(String text) {
111 | Rect bounds = new Rect();
112 | mPaint.getTextBounds(text, 0, text.length(), bounds);
113 | return bounds.height();
114 | }
115 |
116 |
117 | @Override
118 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
119 | super.onSizeChanged(w, h, oldw, oldh);
120 | mWidth = getMeasuredWidth();
121 | mHeight = getMeasuredHeight();
122 | mCellHeight = (mHeight * 0.8f / 27); //26个字母加上“#”
123 | mMarginTop = (mHeight - mCellHeight * indexs.length) / 2;
124 | }
125 |
126 | // 处理Touch事件
127 | @Override
128 | public boolean onTouchEvent(MotionEvent event) {
129 | switch (event.getAction()) {
130 | case MotionEvent.ACTION_DOWN:
131 | case MotionEvent.ACTION_MOVE:
132 | setBackgroundColor(DOWN_COLOR);
133 | // 按下字母的下标
134 | int letterIndex = (int) ((event.getY() - mMarginTop) / mCellHeight);
135 | // 判断是否越界
136 | if (letterIndex >= 0 && letterIndex < indexs.length) {
137 | // 显示按下的字母
138 | if (textView != null) {
139 | textView.setVisibility(View.VISIBLE);
140 | textView.setText(indexs[letterIndex]);
141 | }
142 | //通过回调方法通知列表定位
143 | if (mOnIndexChangedListener != null) {
144 | mOnIndexChangedListener.onIndexChanged(indexs[letterIndex]);
145 | }
146 | }
147 | break;
148 | case MotionEvent.ACTION_UP:
149 | case MotionEvent.ACTION_CANCEL:
150 | setBackgroundColor(UP_COLOR);
151 | if (textView != null) {
152 | textView.setVisibility(View.GONE);
153 | }
154 | break;
155 | }
156 |
157 | return true;
158 | }
159 |
160 | public interface OnIndexChangedListener {
161 | /**
162 | * 按下字母改变了
163 | *
164 | * @param letter 按下的字母
165 | */
166 | void onIndexChanged(String letter);
167 | }
168 |
169 | private OnIndexChangedListener mOnIndexChangedListener;
170 |
171 | private TextView textView;
172 |
173 | public void setOnIndexChangedListener(OnIndexChangedListener onIndexChangedListener) {
174 | this.mOnIndexChangedListener = onIndexChangedListener;
175 | }
176 |
177 | /**
178 | * 设置显示按下首字母的TextView
179 | */
180 | public void setSelectedIndexTextView(TextView textView) {
181 | this.textView = textView;
182 | }
183 | }
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/sort/SortChildItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.sort;
2 |
3 | import android.graphics.Rect;
4 | import android.support.annotation.NonNull;
5 | import android.support.v7.widget.RecyclerView;
6 |
7 | import com.baozi.demo.R;
8 | import com.baozi.treerecyclerview.base.ViewHolder;
9 | import com.baozi.treerecyclerview.item.TreeItem;
10 |
11 | /**
12 | * Created by baozi on 2017/8/19.
13 | */
14 |
15 | public class SortChildItem extends TreeItem {
16 | @Override
17 | public int getLayoutId() {
18 | return R.layout.item_sort_child;
19 | }
20 |
21 | @Override
22 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
23 | viewHolder.setText(R.id.tv_content, data);
24 | }
25 |
26 | @Override
27 | public void getItemOffsets(@NonNull Rect outRect, RecyclerView.LayoutParams layoutParams, int position) {
28 | super.getItemOffsets(outRect, layoutParams, position);
29 | outRect.top = 1;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/sort/SortGroupItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.sort;
2 |
3 | import android.graphics.Rect;
4 | import android.support.annotation.NonNull;
5 | import android.support.v7.widget.RecyclerView;
6 |
7 | import com.baozi.demo.R;
8 | import com.baozi.demo.item.swipe.SwipeSortItem;
9 | import com.baozi.treerecyclerview.base.ViewHolder;
10 | import com.baozi.treerecyclerview.item.TreeItem;
11 | import com.baozi.treerecyclerview.item.TreeSortItem;
12 |
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | /**
17 | * Created by baozi on 2017/8/19.
18 | */
19 |
20 | public class SortGroupItem extends TreeSortItem {
21 | @Override
22 | protected List initChild(Object childs) {
23 | ArrayList treeItems = new ArrayList<>();
24 | for (int i = 0; i < 5; i++) {
25 | SwipeSortItem sortChildItem = new SwipeSortItem();
26 | sortChildItem.setData(i + "");
27 | treeItems.add(sortChildItem);
28 | }
29 | return treeItems;
30 | }
31 |
32 |
33 | @Override
34 | public int getLayoutId() {
35 | return R.layout.item_sort_group;
36 | }
37 |
38 | @Override
39 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
40 | if (isExpand()) {
41 | viewHolder.setImageResource(R.id.iv_right, R.drawable.ic_keyboard_arrow_down_black_24dp);
42 | } else {
43 | viewHolder.setImageResource(R.id.iv_right, R.drawable.ic_keyboard_arrow_right_black_24dp);
44 | }
45 | viewHolder.setText(R.id.tv_content, (String) getSortKey());
46 | }
47 |
48 | @Override
49 | public void onClick(ViewHolder viewHolder) {
50 | super.onClick(viewHolder);
51 | if (isExpand()) {
52 | viewHolder.setImageResource(R.id.iv_right, R.drawable.ic_keyboard_arrow_down_black_24dp);
53 | } else {
54 | viewHolder.setImageResource(R.id.iv_right, R.drawable.ic_keyboard_arrow_right_black_24dp);
55 | }
56 | }
57 |
58 | @Override
59 | public void getItemOffsets(@NonNull Rect outRect, RecyclerView.LayoutParams layoutParams, int position) {
60 | super.getItemOffsets(outRect, layoutParams, position);
61 | outRect.top = 10;
62 | if (position == 0) {
63 | outRect.top = 0;
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/swipe/SwipeSortItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.swipe;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.view.View;
5 | import android.widget.Toast;
6 |
7 | import com.baozi.demo.R;
8 | import com.baozi.demo.item.sort.SortChildItem;
9 | import com.baozi.treerecyclerview.item.SwipeItem;
10 | import com.baozi.treerecyclerview.widget.swipe.SwipeItemMangerInterface;
11 | import com.baozi.treerecyclerview.widget.swipe.SwipeLayout;
12 | import com.baozi.treerecyclerview.base.ViewHolder;
13 |
14 | /**
15 | * Created by baozi on 2017/8/20.
16 | */
17 |
18 | public class SwipeSortItem extends SortChildItem implements SwipeItem {
19 | @Override
20 | public int getSwipeLayoutId() {
21 | return R.layout.layout_delete;
22 | }
23 |
24 | @Override
25 | public SwipeLayout.DragEdge getDragEdge() {
26 | return SwipeLayout.DragEdge.Right;
27 | }
28 |
29 | @Override
30 | public void onBindSwipeView(@NonNull ViewHolder viewHolder, int position, final SwipeItemMangerInterface swipeManger) {
31 | viewHolder.setOnClickListener(R.id.tv_delete, new View.OnClickListener() {
32 | @Override
33 | public void onClick(View v) {
34 | Toast.makeText(v.getContext(), "删除", Toast.LENGTH_SHORT).show();
35 | swipeManger.closeAllItems();
36 | }
37 | });
38 | }
39 |
40 | @Override
41 | public void openCallback() {
42 |
43 | }
44 |
45 | @Override
46 | public void onClick(ViewHolder viewHolder) {
47 | super.onClick(viewHolder);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/tbhome/GoodsItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.tbhome;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | import com.baozi.demo.R;
6 | import com.baozi.treerecyclerview.base.ViewHolder;
7 | import com.baozi.treerecyclerview.item.TreeItem;
8 |
9 | /**
10 | * 模板A
11 | */
12 | public class GoodsItem extends TreeItem {
13 | @Override
14 | public int getLayoutId() {
15 | return R.layout.item_tb_goods;
16 | }
17 |
18 | @Override
19 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
20 |
21 | }
22 |
23 | @Override
24 | public int getSpanSize(int maxSpan) {
25 | return super.getSpanSize(maxSpan)/3;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/tbhome/HomeCategoryItem.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.tbhome;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | import com.baozi.demo.R;
6 | import com.baozi.treerecyclerview.base.ViewHolder;
7 | import com.baozi.treerecyclerview.item.TreeItem;
8 |
9 | public class HomeCategoryItem extends TreeItem {
10 | @Override
11 | public int getLayoutId() {
12 | return R.layout.item_mine_category;
13 | }
14 |
15 | @Override
16 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
17 |
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/tbhome/HomeItemA.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.tbhome;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | import com.baozi.demo.R;
6 | import com.baozi.treerecyclerview.base.ViewHolder;
7 | import com.baozi.treerecyclerview.item.TreeItem;
8 |
9 | /**
10 | * 模板B
11 | */
12 | public class HomeItemA extends TreeItem {
13 | @Override
14 | public int getLayoutId() {
15 | return R.layout.item_tb_home_a;
16 | }
17 |
18 | @Override
19 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
20 |
21 | }
22 |
23 | @Override
24 | public int getSpanSize(int maxSpan) {
25 | return maxSpan / 2;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/tbhome/HomeItemB.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.tbhome;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | import com.baozi.demo.R;
6 | import com.baozi.treerecyclerview.base.ViewHolder;
7 | import com.baozi.treerecyclerview.item.TreeItem;
8 |
9 | /**
10 | * 模板A
11 | */
12 | public class HomeItemB extends TreeItem {
13 | @Override
14 | public int getLayoutId() {
15 | return R.layout.item_tb_home_b;
16 | }
17 |
18 | @Override
19 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
20 |
21 | }
22 |
23 | @Override
24 | public int getSpanSize(int maxSpan) {
25 | return maxSpan/ 3 * 2;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/tbhome/HomeItemC.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.tbhome;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | import com.baozi.demo.R;
6 | import com.baozi.treerecyclerview.base.ViewHolder;
7 | import com.baozi.treerecyclerview.item.TreeItem;
8 |
9 | /**
10 | * 模板C
11 | */
12 | public class HomeItemC extends TreeItem {
13 | @Override
14 | public int getLayoutId() {
15 | return R.layout.item_tb_home_c;
16 | }
17 |
18 | @Override
19 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
20 |
21 | }
22 |
23 | @Override
24 | public int getSpanSize(int maxSpan) {
25 | return maxSpan/3;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/tbhome/HomeItemD.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.tbhome;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | import com.baozi.demo.R;
6 | import com.baozi.treerecyclerview.base.ViewHolder;
7 | import com.baozi.treerecyclerview.item.TreeItem;
8 |
9 | /**
10 | * 模板D
11 | */
12 | public class HomeItemD extends TreeItem {
13 | @Override
14 | public int getLayoutId() {
15 | return R.layout.item_tb_home_d;
16 | }
17 |
18 | @Override
19 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
20 |
21 | }
22 |
23 | @Override
24 | public int getSpanSize(int maxSpan) {
25 | return maxSpan/3;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/tbhome/HomeItemE.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.tbhome;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | import com.baozi.demo.R;
6 | import com.baozi.treerecyclerview.base.ViewHolder;
7 | import com.baozi.treerecyclerview.item.TreeItem;
8 |
9 | /**
10 | * 模板E
11 | */
12 | public class HomeItemE extends TreeItem {
13 | @Override
14 | public int getLayoutId() {
15 | return R.layout.item_tb_home_e;
16 | }
17 |
18 | @Override
19 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
20 |
21 | }
22 |
23 | @Override
24 | public int getSpanSize(int maxSpan) {
25 | return maxSpan/3;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/demo/src/main/java/com/baozi/demo/item/tbhome/HomeItemF.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo.item.tbhome;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | import com.baozi.demo.R;
6 | import com.baozi.treerecyclerview.base.ViewHolder;
7 | import com.baozi.treerecyclerview.item.TreeItem;
8 |
9 | /**
10 | * 模板F
11 | */
12 | public class HomeItemF extends TreeItem {
13 | @Override
14 | public int getLayoutId() {
15 | return R.layout.item_tb_home_f;
16 | }
17 |
18 | @Override
19 | public void onBindViewHolder(@NonNull ViewHolder viewHolder) {
20 |
21 | }
22 |
23 | @Override
24 | public int getSpanSize(int maxSpan) {
25 | return maxSpan/3;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/bg_title.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/ic_keyboard_arrow_down_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/ic_keyboard_arrow_right_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/ic_person_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/ic_photo_24dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/demo/src/main/res/drawable/shape_radius30_stroke1_gray_333.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
17 |
22 |
27 |
32 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/activity_shopping_cart.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
17 |
18 |
23 |
24 |
33 |
34 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/activity_sort.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
23 |
24 |
29 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/activity_tb_home.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
11 |
12 |
18 |
22 |
26 |
30 |
34 |
35 |
44 |
45 |
46 |
52 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/at_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_brand_title.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
18 |
24 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_cart_child.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
23 |
24 |
30 |
31 |
38 |
39 |
46 |
47 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_cart_group.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_grallery.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_mine.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_mine_category.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
18 |
19 |
27 |
28 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_mine_head.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
23 |
24 |
32 |
33 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_news_foot.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
16 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_news_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_news_title.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
15 |
16 |
25 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_sort_child.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_sort_group.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
19 |
20 |
26 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_tb_goods.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
20 |
21 |
27 |
28 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_tb_home_a.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
21 |
22 |
26 |
27 |
34 |
35 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_tb_home_b.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
20 |
21 |
31 |
32 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_tb_home_c.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
16 |
17 |
26 |
27 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_tb_home_d.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
21 |
22 |
31 |
32 |
33 |
34 |
41 |
42 |
50 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_tb_home_e.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
16 |
17 |
25 |
26 |
30 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_tb_home_f.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
14 |
15 |
21 |
22 |
29 |
30 |
31 |
32 |
39 |
40 |
48 |
49 |
57 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_test_group.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
22 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_three.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/item_two.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/itme_one.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/layout_delete.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
16 |
23 |
24 |
31 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/layout_empty.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/layout_loading.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
--------------------------------------------------------------------------------
/demo/src/main/res/layout/layout_rv_content.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jlanglang/TreeRecyclerView/6f454078ecd9f05619bb1d44b282d6d758f7ffeb/demo/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jlanglang/TreeRecyclerView/6f454078ecd9f05619bb1d44b282d6d758f7ffeb/demo/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jlanglang/TreeRecyclerView/6f454078ecd9f05619bb1d44b282d6d758f7ffeb/demo/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jlanglang/TreeRecyclerView/6f454078ecd9f05619bb1d44b282d6d758f7ffeb/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jlanglang/TreeRecyclerView/6f454078ecd9f05619bb1d44b282d6d758f7ffeb/demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/demo/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #01579B
4 | #01579B
5 | #0288D1
6 | #fff
7 |
8 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | TreeRecyclerView
4 |
5 |
--------------------------------------------------------------------------------
/demo/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
17 |
18 |
21 |
22 |
28 |
29 |
32 |
33 |
--------------------------------------------------------------------------------
/demo/src/test/java/com/baozi/demo/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.baozi.demo;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants recyclerView.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## Project-wide Gradle settings.
2 | #
3 | # For more details on how to configure your build environment visit
4 | # http://www.gradle.org/docs/current/userguide/build_environment.html
5 | #
6 | # Specifies the JVM arguments used for the daemon process.
7 | # The setting is particularly useful for tweaking memory settings.
8 | # Default value: -Xmx1024m -XX:MaxPermSize=256m
9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | #
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 | #Sat Jul 15 09:57:20 CST 2017
16 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jlanglang/TreeRecyclerView/6f454078ecd9f05619bb1d44b282d6d758f7ffeb/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue May 07 17:24:05 CST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/image/20180928114547.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jlanglang/TreeRecyclerView/6f454078ecd9f05619bb1d44b282d6d758f7ffeb/image/20180928114547.png
--------------------------------------------------------------------------------
/image/20180928114623.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jlanglang/TreeRecyclerView/6f454078ecd9f05619bb1d44b282d6d758f7ffeb/image/20180928114623.png
--------------------------------------------------------------------------------
/image/20180928114648.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jlanglang/TreeRecyclerView/6f454078ecd9f05619bb1d44b282d6d758f7ffeb/image/20180928114648.png
--------------------------------------------------------------------------------
/image/20180928120846.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jlanglang/TreeRecyclerView/6f454078ecd9f05619bb1d44b282d6d758f7ffeb/image/20180928120846.png
--------------------------------------------------------------------------------
/image/20180928120934.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jlanglang/TreeRecyclerView/6f454078ecd9f05619bb1d44b282d6d758f7ffeb/image/20180928120934.png
--------------------------------------------------------------------------------
/image/20180928145931.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jlanglang/TreeRecyclerView/6f454078ecd9f05619bb1d44b282d6d758f7ffeb/image/20180928145931.png
--------------------------------------------------------------------------------
/image/wx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jlanglang/TreeRecyclerView/6f454078ecd9f05619bb1d44b282d6d758f7ffeb/image/wx.jpg
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':demo',':app'
2 |
--------------------------------------------------------------------------------