├── .gitignore ├── .idea ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── wanjian │ │ └── view │ │ └── demo │ │ ├── AddDemoActivity.java │ │ ├── ExpandListDemoActivity.java │ │ ├── GroupDemoActivity.java │ │ ├── GroupDividerDemoActivity.java │ │ ├── MainActivity.java │ │ ├── RefreshDemoActivity.java │ │ ├── RemoveDemoActivity.java │ │ ├── adapter │ │ ├── AddAdapter.java │ │ ├── GroupAdapter.java │ │ ├── HDividerAdapter.java │ │ ├── RefreshAdapter.java │ │ ├── RemoveAdapter.java │ │ ├── VDividerAdapter.java │ │ └── VExpandableAdapter.java │ │ ├── data │ │ ├── Goods.java │ │ └── Shop.java │ │ ├── utils │ │ └── Utils.java │ │ └── vh │ │ ├── ChildVH.java │ │ ├── GroupVH.java │ │ ├── child │ │ ├── ClothesVH.java │ │ ├── FoodVH.java │ │ └── MilkVH.java │ │ └── group │ │ ├── AllVH.java │ │ ├── OffLineVH.java │ │ └── OnLineVH.java │ └── res │ ├── drawable │ ├── h_divider_after_last.xml │ ├── h_divider_before_first.xml │ ├── h_divider_between_child.xml │ ├── h_divider_between_group.xml │ ├── h_divider_between_group_child.xml │ ├── v_divider_after_last.xml │ ├── v_divider_before_first.xml │ ├── v_divider_between_child.xml │ ├── v_divider_between_group.xml │ └── v_divider_between_group_child.xml │ ├── layout │ ├── activity_add.xml │ ├── activity_divider.xml │ ├── activity_expandlist.xml │ ├── activity_group.xml │ ├── activity_main.xml │ ├── activity_refresh.xml │ ├── activity_remove.xml │ ├── h_item_child_clothes.xml │ ├── h_item_child_food.xml │ ├── h_item_child_milk.xml │ ├── h_item_group_all.xml │ ├── h_item_group_offline.xml │ ├── h_item_group_online.xml │ ├── test.xml │ ├── v_item_child_clothes.xml │ ├── v_item_child_food.xml │ ├── v_item_child_milk.xml │ ├── v_item_group_all.xml │ ├── v_item_group_offline.xml │ └── v_item_group_online.xml │ ├── mipmap-hdpi │ ├── header.png │ └── ic_launcher.png │ ├── mipmap-mdpi │ ├── header.png │ └── ic_launcher.png │ ├── mipmap-xhdpi │ ├── header.png │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ ├── amazon_logo.png │ ├── clothes.png │ ├── end.png │ ├── footer.png │ ├── hamberger.png │ ├── header.png │ ├── ic_launcher.png │ ├── milk.png │ ├── shop.png │ ├── shop_car.png │ ├── suning_logo.png │ ├── tile.png │ └── welcome.png │ ├── mipmap-xxxhdpi │ ├── header.png │ └── ic_launcher.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── divider.jpg ├── expan.gif ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── group.jpg ├── lib ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── wanjian │ │ └── view │ │ ├── ExpandableAdapter.java │ │ ├── NestedAdapter.java │ │ └── NestedAdapterDivider.java │ └── res │ └── values │ └── strings.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 wanjian 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # expandable-recyclerview 2 | 可以展开、折叠分组,支持添加多种divider的adapter 3 | 4 | `compile 'com.wanjian:expandable-recyclerview:0.0.1'` 5 | 6 | ### 分组RecyclerView 7 | 8 | 支持多种group布局和多种child布局 9 | 10 | ![group](https://github.com/android-notes/expandable-recyclerview/blob/master/group.jpg?raw=true) 11 | 12 | 继承`NestedAdapter`,实现下列方法即可,跟使用`ExpandableListview`类似 13 | 14 | ```java 15 | 16 | protected abstract int getGroupCount(); 17 | 18 | protected abstract int getChildCount(int groupIndex); 19 | 20 | protected int getGroupItemViewType(int groupIndex) { 21 | return 1; 22 | } 23 | 24 | protected int getChildItemViewType(int groupIndex, int childIndex) { 25 | return 1; 26 | } 27 | 28 | protected abstract G onCreateGroupViewHolder(ViewGroup parent, int viewType); 29 | 30 | protected abstract void onBindGroupViewHolder(G holder, int groupIndex); 31 | 32 | protected abstract C onCreateChildViewHolder(ViewGroup parent, int viewType); 33 | 34 | protected abstract void onBindChildViewHolder(C holder, int groupIndex, int childIndex); 35 | 36 | 37 | ``` 38 | 39 | 40 | 41 | ### 为NestedAdapter添加divider 42 | 43 | ![divider](https://github.com/android-notes/expandable-recyclerview/blob/master/divider.jpg?raw=true) 44 | 45 | 支持添加头部,尾部,group间,child间,group和child间添加自定义divider 46 | 47 | ```java 48 | 49 | public NestedAdapterDivider setDividerBetweenGroup(Drawable dividerBetweenGroup) 50 | 51 | public NestedAdapterDivider setDividerBetweenChild(Drawable dividerBetweenChild) 52 | 53 | public NestedAdapterDivider setDividerBetweenGroupAndChild(Drawable dividerBetweenGroupAndChild) 54 | 55 | public NestedAdapterDivider setDividerBeforeFirstGroup(Drawable dividerBeforeFirstGroup) 56 | 57 | public NestedAdapterDivider setDividerAfterLastGroup(Drawable dividerAfterLastGroup) 58 | 59 | 60 | ``` 61 | 62 | ### 展开折叠Recyclerview 63 | 64 | ![group](https://github.com/android-notes/expandable-recyclerview/blob/master/expan.gif?raw=true) 65 | 66 | 67 | 继承自ExpandableAdapter即可,调用如下方法实现展开折叠,同样支持多种group布局和多种child布局 68 | 69 | ```java 70 | 71 | 72 | public void collapseGroup(int groupIndex) 73 | 74 | public void expandGroup(int groupIndex) 75 | 76 | public boolean isExpand(int groupIndex) 77 | 78 | public void collapseAllGroup() 79 | 80 | 81 | ``` 82 | 83 | 84 | ### 支持局部刷新,局部移除添加 85 | 86 | 相关方法如下 87 | 88 | ```java 89 | 90 | public void notifyGroupItemChanged(int groupIndex) 91 | 92 | public void notifyGroupChanged(int groupIndex) 93 | 94 | public final void notifyChildItemChanged(int groupIndex, int childIndex) 95 | 96 | public final void notifyChildItemRangeChanged(int groupIndex, int childIndex, int itemCount) 97 | 98 | public final void notifyChildItemInserted(int groupIndex, int childIndex) 99 | 100 | public final void notifyChildItemRangeInserted(int groupIndex, int childIndex, int itemCount) 101 | 102 | public final void notifyChildItemRemoved(int groupIndex, int childIndex) 103 | 104 | public final void notifyChildItemRangeRemoved(int groupIndex, int childIndex, int itemCount) 105 | 106 | ``` 107 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | buildToolsVersion "26.0.1" 6 | defaultConfig { 7 | applicationId "com.wanjian.view.demo" 8 | minSdkVersion 14 9 | targetSdkVersion 26 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(include: ['*.jar'], dir: 'libs') 23 | compile 'com.android.support:appcompat-v7:26.1.0' 24 | // compile 'com.android.support.test.espresso:espresso-core:3.0.1' 25 | compile project(':lib') 26 | 27 | compile 'com.android.support:recyclerview-v7:26.1.0' 28 | 29 | // https://mvnrepository.com/artifact/com.google.code.gson/gson 30 | compile group: 'com.google.code.gson', name: 'gson', version: '2.8.0' 31 | 32 | } 33 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/AddDemoActivity.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo; 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.view.View; 9 | 10 | import com.wanjian.view.ExpandableAdapter; 11 | import com.wanjian.view.demo.adapter.AddAdapter; 12 | import com.wanjian.view.demo.data.Shop; 13 | 14 | import java.util.List; 15 | 16 | import static com.wanjian.view.demo.utils.Utils.geneRandomData; 17 | import static com.wanjian.view.demo.utils.Utils.showJson; 18 | 19 | 20 | /** 21 | * Created by wanjian on 2018/1/29. 22 | */ 23 | public class AddDemoActivity extends AppCompatActivity { 24 | List shopList; 25 | ExpandableAdapter adapter; 26 | 27 | @Override 28 | protected void onCreate(@Nullable Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | 31 | setContentView(R.layout.activity_add); 32 | final RecyclerView recyclerView = findViewById(R.id.recyclerView); 33 | 34 | shopList = geneRandomData(); 35 | showJson(shopList); 36 | 37 | vertical(recyclerView); 38 | 39 | 40 | findViewById(R.id.refresh).setOnClickListener(new View.OnClickListener() { 41 | @Override 42 | public void onClick(View v) { 43 | List newData = geneRandomData(); 44 | shopList.clear(); 45 | 46 | shopList.addAll(newData); 47 | showJson(shopList); 48 | adapter.notifyDataSetChanged(); 49 | } 50 | }); 51 | 52 | 53 | } 54 | 55 | 56 | private void vertical(RecyclerView recyclerView) { 57 | recyclerView.setLayoutManager(new LinearLayoutManager(this)); 58 | 59 | adapter = new AddAdapter(shopList); 60 | recyclerView.setAdapter(adapter); 61 | 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/ExpandListDemoActivity.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo; 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.view.View; 9 | 10 | import com.wanjian.view.ExpandableAdapter; 11 | import com.wanjian.view.demo.adapter.VExpandableAdapter; 12 | import com.wanjian.view.demo.data.Shop; 13 | 14 | import java.util.List; 15 | 16 | import static com.wanjian.view.demo.utils.Utils.geneRandomData; 17 | import static com.wanjian.view.demo.utils.Utils.showJson; 18 | 19 | 20 | /** 21 | * Created by wanjian on 2018/1/29. 22 | */ 23 | public class ExpandListDemoActivity extends AppCompatActivity { 24 | List shopList; 25 | ExpandableAdapter adapter; 26 | 27 | @Override 28 | protected void onCreate(@Nullable Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | 31 | setContentView(R.layout.activity_expandlist); 32 | final RecyclerView recyclerView = findViewById(R.id.recyclerView); 33 | 34 | shopList = geneRandomData(); 35 | showJson(shopList); 36 | 37 | vertical(recyclerView); 38 | 39 | 40 | findViewById(R.id.refresh).setOnClickListener(new View.OnClickListener() { 41 | @Override 42 | public void onClick(View v) { 43 | List newData = geneRandomData(); 44 | shopList.clear(); 45 | 46 | shopList.addAll(newData); 47 | showJson(shopList); 48 | adapter.notifyDataSetChanged(); 49 | } 50 | }); 51 | 52 | findViewById(R.id.close).setOnClickListener(new View.OnClickListener() { 53 | @Override 54 | public void onClick(View v) { 55 | adapter.collapseAllGroup(); 56 | } 57 | }); 58 | findViewById(R.id.open).setOnClickListener(new View.OnClickListener() { 59 | @Override 60 | public void onClick(View v) { 61 | adapter.expandAllGroup(); 62 | } 63 | }); 64 | 65 | } 66 | 67 | 68 | private void vertical(RecyclerView recyclerView) { 69 | recyclerView.setLayoutManager(new LinearLayoutManager(this)); 70 | 71 | adapter = new VExpandableAdapter(shopList); 72 | recyclerView.setAdapter(adapter); 73 | 74 | } 75 | 76 | 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/GroupDemoActivity.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo; 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.view.View; 9 | 10 | import com.wanjian.view.demo.adapter.GroupAdapter; 11 | import com.wanjian.view.demo.data.Shop; 12 | 13 | import java.util.List; 14 | 15 | import static com.wanjian.view.demo.utils.Utils.geneRandomData; 16 | import static com.wanjian.view.demo.utils.Utils.showJson; 17 | 18 | 19 | /** 20 | * Created by wanjian on 2018/1/29. 21 | */ 22 | public class GroupDemoActivity extends AppCompatActivity { 23 | List shopList; 24 | RecyclerView.Adapter adapter; 25 | 26 | @Override 27 | protected void onCreate(@Nullable Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | 30 | setContentView(R.layout.activity_group); 31 | final RecyclerView recyclerView = findViewById(R.id.recyclerView); 32 | 33 | shopList = geneRandomData(); 34 | showJson(shopList); 35 | 36 | vertical(recyclerView); 37 | 38 | 39 | findViewById(R.id.refresh).setOnClickListener(new View.OnClickListener() { 40 | @Override 41 | public void onClick(View v) { 42 | List newData = geneRandomData(); 43 | shopList.clear(); 44 | 45 | shopList.addAll(newData); 46 | showJson(shopList); 47 | adapter.notifyDataSetChanged(); 48 | } 49 | }); 50 | 51 | 52 | } 53 | 54 | 55 | private void vertical(RecyclerView recyclerView) { 56 | recyclerView.setLayoutManager(new LinearLayoutManager(this)); 57 | adapter = new GroupAdapter(shopList); 58 | recyclerView.setAdapter(adapter); 59 | 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/GroupDividerDemoActivity.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo; 2 | 3 | import android.graphics.drawable.Drawable; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.support.v7.widget.LinearLayoutManager; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.view.View; 10 | 11 | import com.wanjian.view.NestedAdapterDivider; 12 | import com.wanjian.view.demo.adapter.HDividerAdapter; 13 | import com.wanjian.view.demo.adapter.VDividerAdapter; 14 | import com.wanjian.view.demo.data.Shop; 15 | 16 | import java.util.List; 17 | 18 | import static com.wanjian.view.demo.utils.Utils.geneRandomData; 19 | import static com.wanjian.view.demo.utils.Utils.showJson; 20 | 21 | 22 | /** 23 | * Created by wanjian on 2018/1/29. 24 | */ 25 | public class GroupDividerDemoActivity extends AppCompatActivity { 26 | NestedAdapterDivider divider; 27 | List shopList; 28 | RecyclerView.Adapter adapter; 29 | 30 | @Override 31 | protected void onCreate(@Nullable Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | 34 | setContentView(R.layout.activity_divider); 35 | final RecyclerView recyclerView = findViewById(R.id.recyclerView); 36 | 37 | shopList = geneRandomData(); 38 | showJson(shopList); 39 | 40 | vertical(recyclerView); 41 | 42 | 43 | findViewById(R.id.refresh).setOnClickListener(new View.OnClickListener() { 44 | @Override 45 | public void onClick(View v) { 46 | List newData = geneRandomData(); 47 | shopList.clear(); 48 | 49 | shopList.addAll(newData); 50 | showJson(shopList); 51 | adapter.notifyDataSetChanged(); 52 | } 53 | }); 54 | 55 | findViewById(R.id.orientation).setOnClickListener(new View.OnClickListener() { 56 | boolean vertical = true; 57 | 58 | @Override 59 | public void onClick(View v) { 60 | vertical = !vertical; 61 | recyclerView.getRecycledViewPool().clear(); 62 | if (vertical) { 63 | vertical(recyclerView); 64 | } else { 65 | horizontal(recyclerView); 66 | } 67 | 68 | } 69 | }); 70 | } 71 | 72 | 73 | private void horizontal(RecyclerView recyclerView) { 74 | recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); 75 | if (divider != null) { 76 | recyclerView.removeItemDecoration(divider); 77 | } 78 | divider = new NestedAdapterDivider(this, NestedAdapterDivider.HORIZONTAL); 79 | 80 | divider 81 | .setDividerBeforeFirstGroup(getDividerDrawable(R.drawable.v_divider_before_first)) 82 | .setDividerBetweenGroup(getDividerDrawable(R.drawable.v_divider_between_group)) 83 | .setDividerAfterLastGroup(getDividerDrawable(R.drawable.v_divider_after_last)) 84 | .setDividerBetweenChild(getDividerDrawable(R.drawable.v_divider_between_child)) 85 | .setDividerBetweenGroupAndChild(getDividerDrawable(R.drawable.v_divider_between_group_child)) 86 | ; 87 | 88 | recyclerView.addItemDecoration(divider); 89 | 90 | adapter = new HDividerAdapter(shopList); 91 | recyclerView.setAdapter(adapter); 92 | } 93 | 94 | private void vertical(RecyclerView recyclerView) { 95 | recyclerView.setLayoutManager(new LinearLayoutManager(this)); 96 | if (divider != null) { 97 | recyclerView.removeItemDecoration(divider); 98 | } 99 | divider = new NestedAdapterDivider(this, NestedAdapterDivider.VERTICAL); 100 | 101 | divider 102 | .setDividerBeforeFirstGroup(getDividerDrawable(R.drawable.h_divider_before_first)) 103 | .setDividerBetweenGroup(getDividerDrawable(R.drawable.h_divider_between_group)) 104 | .setDividerAfterLastGroup(getDividerDrawable(R.drawable.h_divider_after_last)) 105 | .setDividerBetweenChild(getDividerDrawable(R.drawable.h_divider_between_child)) 106 | .setDividerBetweenGroupAndChild(getDividerDrawable(R.drawable.h_divider_between_group_child)) 107 | ; 108 | 109 | recyclerView.addItemDecoration(divider); 110 | 111 | adapter = new VDividerAdapter(shopList); 112 | recyclerView.setAdapter(adapter); 113 | 114 | } 115 | 116 | public Drawable getDividerDrawable(int resId) { 117 | return getResources().getDrawable(resId); 118 | } 119 | 120 | 121 | } 122 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.View; 8 | 9 | /** 10 | * Created by wanjian on 2018/1/29. 11 | */ 12 | 13 | public class MainActivity extends AppCompatActivity { 14 | 15 | @Override 16 | protected void onCreate(@Nullable Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | 19 | setContentView(R.layout.activity_main); 20 | 21 | findViewById(R.id.group).setOnClickListener(new View.OnClickListener() { 22 | @Override 23 | public void onClick(View v) { 24 | startActivity(new Intent(getApplicationContext(), GroupDemoActivity.class)); 25 | } 26 | }); 27 | findViewById(R.id.divider).setOnClickListener(new View.OnClickListener() { 28 | @Override 29 | public void onClick(View v) { 30 | startActivity(new Intent(getApplicationContext(), GroupDividerDemoActivity.class)); 31 | } 32 | }); 33 | findViewById(R.id.expandListDemo).setOnClickListener(new View.OnClickListener() { 34 | @Override 35 | public void onClick(View v) { 36 | startActivity(new Intent(getApplicationContext(), ExpandListDemoActivity.class)); 37 | } 38 | }); 39 | findViewById(R.id.add).setOnClickListener(new View.OnClickListener() { 40 | @Override 41 | public void onClick(View v) { 42 | startActivity(new Intent(getApplicationContext(), AddDemoActivity.class)); 43 | } 44 | }); 45 | findViewById(R.id.remove).setOnClickListener(new View.OnClickListener() { 46 | @Override 47 | public void onClick(View v) { 48 | startActivity(new Intent(getApplicationContext(), RemoveDemoActivity.class)); 49 | } 50 | }); 51 | findViewById(R.id.refresh).setOnClickListener(new View.OnClickListener() { 52 | @Override 53 | public void onClick(View v) { 54 | startActivity(new Intent(getApplicationContext(), RefreshDemoActivity.class)); 55 | } 56 | }); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/RefreshDemoActivity.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo; 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.view.View; 9 | 10 | import com.wanjian.view.ExpandableAdapter; 11 | import com.wanjian.view.demo.adapter.RefreshAdapter; 12 | import com.wanjian.view.demo.data.Shop; 13 | 14 | import java.util.List; 15 | 16 | import static com.wanjian.view.demo.utils.Utils.geneRandomData; 17 | import static com.wanjian.view.demo.utils.Utils.showJson; 18 | 19 | 20 | /** 21 | * Created by wanjian on 2018/1/29. 22 | */ 23 | public class RefreshDemoActivity extends AppCompatActivity { 24 | List shopList; 25 | ExpandableAdapter adapter; 26 | 27 | @Override 28 | protected void onCreate(@Nullable Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | 31 | setContentView(R.layout.activity_refresh); 32 | final RecyclerView recyclerView = findViewById(R.id.recyclerView); 33 | 34 | shopList = geneRandomData(); 35 | showJson(shopList); 36 | 37 | vertical(recyclerView); 38 | 39 | 40 | findViewById(R.id.refresh).setOnClickListener(new View.OnClickListener() { 41 | @Override 42 | public void onClick(View v) { 43 | List newData = geneRandomData(); 44 | shopList.clear(); 45 | 46 | shopList.addAll(newData); 47 | showJson(shopList); 48 | adapter.notifyDataSetChanged(); 49 | } 50 | }); 51 | 52 | 53 | } 54 | 55 | 56 | private void vertical(RecyclerView recyclerView) { 57 | recyclerView.setLayoutManager(new LinearLayoutManager(this)); 58 | 59 | adapter = new RefreshAdapter(shopList); 60 | recyclerView.setAdapter(adapter); 61 | 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/RemoveDemoActivity.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo; 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.view.View; 9 | 10 | import com.wanjian.view.ExpandableAdapter; 11 | import com.wanjian.view.demo.adapter.RemoveAdapter; 12 | import com.wanjian.view.demo.data.Shop; 13 | 14 | import java.util.List; 15 | 16 | import static com.wanjian.view.demo.utils.Utils.geneRandomData; 17 | import static com.wanjian.view.demo.utils.Utils.showJson; 18 | 19 | 20 | /** 21 | * Created by wanjian on 2018/1/29. 22 | */ 23 | public class RemoveDemoActivity extends AppCompatActivity { 24 | List shopList; 25 | ExpandableAdapter adapter; 26 | 27 | @Override 28 | protected void onCreate(@Nullable Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | 31 | setContentView(R.layout.activity_remove); 32 | final RecyclerView recyclerView = findViewById(R.id.recyclerView); 33 | 34 | shopList = geneRandomData(); 35 | showJson(shopList); 36 | 37 | vertical(recyclerView); 38 | 39 | 40 | findViewById(R.id.refresh).setOnClickListener(new View.OnClickListener() { 41 | @Override 42 | public void onClick(View v) { 43 | List newData = geneRandomData(); 44 | shopList.clear(); 45 | 46 | shopList.addAll(newData); 47 | showJson(shopList); 48 | adapter.notifyDataSetChanged(); 49 | } 50 | }); 51 | 52 | 53 | } 54 | 55 | 56 | private void vertical(RecyclerView recyclerView) { 57 | recyclerView.setLayoutManager(new LinearLayoutManager(this)); 58 | 59 | adapter = new RemoveAdapter(shopList); 60 | recyclerView.setAdapter(adapter); 61 | 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/adapter/AddAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.adapter; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.wanjian.view.ExpandableAdapter; 10 | import com.wanjian.view.demo.R; 11 | import com.wanjian.view.demo.data.Goods; 12 | import com.wanjian.view.demo.data.Shop; 13 | import com.wanjian.view.demo.vh.ChildVH; 14 | import com.wanjian.view.demo.vh.GroupVH; 15 | import com.wanjian.view.demo.vh.child.ClothesVH; 16 | import com.wanjian.view.demo.vh.child.FoodVH; 17 | import com.wanjian.view.demo.vh.child.MilkVH; 18 | import com.wanjian.view.demo.vh.group.AllVH; 19 | import com.wanjian.view.demo.vh.group.OffLineVH; 20 | import com.wanjian.view.demo.vh.group.OnLineVH; 21 | 22 | import java.util.List; 23 | 24 | import static com.wanjian.view.demo.data.Goods.TYPE_FOOD; 25 | 26 | /** 27 | * Created by wanjian on 2018/1/29. 28 | */ 29 | 30 | public class AddAdapter extends ExpandableAdapter { 31 | 32 | 33 | private List shopList; 34 | 35 | public AddAdapter(List shopList) { 36 | super(); 37 | this.shopList = shopList; 38 | } 39 | 40 | @Override 41 | public int getGroupCount() { 42 | return shopList.size(); 43 | } 44 | 45 | @Override 46 | public int getChildCount(int groupIndex) { 47 | return shopList.get(groupIndex).goods.size(); 48 | } 49 | 50 | @Override 51 | public int getGroupItemViewType(int groupIndex) { 52 | return shopList.get(groupIndex).shopType; 53 | } 54 | 55 | @Override 56 | public int getChildItemViewType(int groupIndex, int childIndex) { 57 | return shopList.get(groupIndex).goods.get(childIndex).goodsType; 58 | } 59 | 60 | @Override 61 | public GroupVH onCreateGroupViewHolder(ViewGroup parent, int viewType) { 62 | Log.d(TAG, ">>> onCreateGroupViewHolder: " + viewType); 63 | Context context = parent.getContext(); 64 | if (viewType == Shop.TYPE_ALL) { 65 | return new AllVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_all, parent, false)); 66 | } else if (viewType == Shop.TYPE_OFFLINE) { 67 | return new OffLineVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_offline, parent, false)); 68 | } else { 69 | return new OnLineVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_online, parent, false)); 70 | } 71 | } 72 | 73 | @Override 74 | public void onBindGroupViewHolder(final GroupVH holder, final int position) { 75 | Log.d(TAG, "onBindGroupViewHolder: " + position + " " + holder); 76 | View.OnClickListener listener = new View.OnClickListener() { 77 | @Override 78 | public void onClick(View v) { 79 | // notifyGroupChanged(position); 80 | // 81 | // notifyChildItemRangeChanged(position, 0, getChildCount(position)); 82 | // 83 | // notifyChildItemRangeChanged(position, 1, getChildCount(position) - 1); 84 | // 85 | // notifyChildItemRangeRemoved(position, 0, getChildCount(position)); 86 | // shopList.get(position).goods.clear(); 87 | 88 | 89 | int count = 2; 90 | int start = getChildCount(position); 91 | notifyChildItemRangeInserted(position, start, count); 92 | for (int i = start; i < start + count; i++) { 93 | shopList.get(position).goods.add(start, new Goods("add", i, TYPE_FOOD, 0)); 94 | } 95 | } 96 | }; 97 | 98 | 99 | int type = getGroupItemViewType(position); 100 | if (type == Shop.TYPE_ALL) { 101 | AllVH vh = ((AllVH) holder); 102 | vh.index.setText((shopList.get(position).reBindTimes++) + ""); 103 | vh.count.setText("" + getChildCount(position)); 104 | vh.name.setText(shopList.get(position).shopName + " TYPE_ALL"); 105 | vh.refresh.setOnClickListener(listener); 106 | vh.refresh.setText("Add"); 107 | } else if (type == Shop.TYPE_OFFLINE) { 108 | OffLineVH vh = (OffLineVH) holder; 109 | vh.index.setText((shopList.get(position).reBindTimes++) + ""); 110 | vh.count.setText("" + getChildCount(position)); 111 | vh.name.setText(shopList.get(position).shopName + " TYPE_OFFLINE"); 112 | vh.refresh.setOnClickListener(listener); 113 | vh.refresh.setText("Add"); 114 | } else { 115 | OnLineVH vh = (OnLineVH) holder; 116 | vh.index.setText((shopList.get(position).reBindTimes++) + ""); 117 | vh.count.setText("" + getChildCount(position)); 118 | vh.name.setText(shopList.get(position).shopName + " TYPE_ONLINE"); 119 | vh.refresh.setOnClickListener(listener); 120 | vh.refresh.setText("Add"); 121 | } 122 | 123 | } 124 | 125 | @Override 126 | public ChildVH onCreateChildViewHolder(ViewGroup parent, int viewType) { 127 | Log.d(TAG, ">>> onCreateChildViewHolder: " + viewType); 128 | Context context = parent.getContext(); 129 | if (viewType == Goods.TYPE_CLOTHES) { 130 | return new ClothesVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_clothes, parent, false)); 131 | 132 | } else if (viewType == TYPE_FOOD) { 133 | return new FoodVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_food, parent, false)); 134 | } else { 135 | return new MilkVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_milk, parent, false)); 136 | 137 | } 138 | } 139 | 140 | @Override 141 | public void onBindChildViewHolder(ChildVH holder, final int groupIndex, final int childIndex) { 142 | Log.d(TAG, "onBindChildViewHolder: " + groupIndex + ":" + childIndex); 143 | int type = getChildItemViewType(groupIndex, childIndex); 144 | if (type == Goods.TYPE_CLOTHES) { 145 | ClothesVH vh = (ClothesVH) holder; 146 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 147 | vh.index.setText((goods.reBindTimes++) + ""); 148 | vh.name.setText(goods.name); 149 | vh.sku.setText("TYPE_CLOTHES"); 150 | } else if (type == TYPE_FOOD) { 151 | 152 | FoodVH vh = (FoodVH) holder; 153 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 154 | vh.index.setText((goods.reBindTimes++) + ""); 155 | vh.name.setText(goods.name); 156 | vh.sku.setText("TYPE_FOOD"); 157 | } else { 158 | 159 | MilkVH vh = (MilkVH) holder; 160 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 161 | vh.index.setText((goods.reBindTimes++) + ""); 162 | vh.name.setText(goods.name); 163 | vh.sku.setText("TYPE_MILK"); 164 | } 165 | 166 | } 167 | 168 | 169 | } 170 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/adapter/GroupAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.adapter; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.wanjian.view.NestedAdapter; 10 | import com.wanjian.view.demo.R; 11 | import com.wanjian.view.demo.data.Goods; 12 | import com.wanjian.view.demo.data.Shop; 13 | import com.wanjian.view.demo.vh.ChildVH; 14 | import com.wanjian.view.demo.vh.GroupVH; 15 | import com.wanjian.view.demo.vh.child.ClothesVH; 16 | import com.wanjian.view.demo.vh.child.FoodVH; 17 | import com.wanjian.view.demo.vh.child.MilkVH; 18 | import com.wanjian.view.demo.vh.group.AllVH; 19 | import com.wanjian.view.demo.vh.group.OffLineVH; 20 | import com.wanjian.view.demo.vh.group.OnLineVH; 21 | 22 | import java.util.List; 23 | 24 | import static com.wanjian.view.demo.data.Goods.TYPE_FOOD; 25 | 26 | /** 27 | * Created by wanjian on 2018/1/29. 28 | */ 29 | 30 | public class GroupAdapter extends NestedAdapter { 31 | 32 | 33 | private List shopList; 34 | 35 | public GroupAdapter(List shopList) { 36 | super(); 37 | this.shopList = shopList; 38 | } 39 | 40 | @Override 41 | public int getGroupCount() { 42 | return shopList.size(); 43 | } 44 | 45 | @Override 46 | public int getChildCount(int groupIndex) { 47 | return shopList.get(groupIndex).goods.size(); 48 | } 49 | 50 | @Override 51 | public int getGroupItemViewType(int groupIndex) { 52 | return shopList.get(groupIndex).shopType; 53 | } 54 | 55 | @Override 56 | public int getChildItemViewType(int groupIndex, int childIndex) { 57 | return shopList.get(groupIndex).goods.get(childIndex).goodsType; 58 | } 59 | 60 | @Override 61 | public GroupVH onCreateGroupViewHolder(ViewGroup parent, int viewType) { 62 | Log.d(TAG, ">>> onCreateGroupViewHolder: " + viewType); 63 | Context context = parent.getContext(); 64 | if (viewType == Shop.TYPE_ALL) { 65 | return new AllVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_all, parent, false)); 66 | } else if (viewType == Shop.TYPE_OFFLINE) { 67 | return new OffLineVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_offline, parent, false)); 68 | } else { 69 | return new OnLineVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_online, parent, false)); 70 | } 71 | } 72 | 73 | @Override 74 | public void onBindGroupViewHolder(final GroupVH holder, final int position) { 75 | Log.d(TAG, "onBindGroupViewHolder: " + position + " " + holder); 76 | 77 | int type = getGroupItemViewType(position); 78 | if (type == Shop.TYPE_ALL) { 79 | AllVH vh = ((AllVH) holder); 80 | vh.index.setText("" + position); 81 | vh.count.setText("child:" + getChildCount(position)); 82 | vh.name.setText(shopList.get(position).shopName + " TYPE_ALL"); 83 | vh.refresh.setVisibility(View.GONE); 84 | } else if (type == Shop.TYPE_OFFLINE) { 85 | OffLineVH vh = (OffLineVH) holder; 86 | vh.index.setText("" + position); 87 | vh.count.setText("child:" + getChildCount(position)); 88 | vh.name.setText(shopList.get(position).shopName + " TYPE_OFFLINE"); 89 | vh.refresh.setVisibility(View.GONE); 90 | } else { 91 | OnLineVH vh = (OnLineVH) holder; 92 | vh.index.setText("" + position); 93 | vh.count.setText("child:" + getChildCount(position)); 94 | vh.name.setText(shopList.get(position).shopName + " TYPE_ONLINE"); 95 | vh.refresh.setVisibility(View.GONE); 96 | } 97 | 98 | } 99 | 100 | @Override 101 | public ChildVH onCreateChildViewHolder(ViewGroup parent, int viewType) { 102 | Log.d(TAG, ">>> onCreateChildViewHolder: " + viewType); 103 | Context context = parent.getContext(); 104 | if (viewType == Goods.TYPE_CLOTHES) { 105 | return new ClothesVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_clothes, parent, false)); 106 | 107 | } else if (viewType == TYPE_FOOD) { 108 | return new FoodVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_food, parent, false)); 109 | } else { 110 | return new MilkVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_milk, parent, false)); 111 | 112 | } 113 | } 114 | 115 | @Override 116 | public void onBindChildViewHolder(ChildVH holder, final int groupIndex, final int childIndex) { 117 | Log.d(TAG, "onBindChildViewHolder: " + groupIndex + ":" + childIndex); 118 | int type = getChildItemViewType(groupIndex, childIndex); 119 | if (type == Goods.TYPE_CLOTHES) { 120 | ClothesVH vh = (ClothesVH) holder; 121 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 122 | vh.index.setText("" + childIndex); 123 | vh.name.setText(goods.name); 124 | vh.sku.setText("TYPE_CLOTHES"); 125 | } else if (type == TYPE_FOOD) { 126 | 127 | FoodVH vh = (FoodVH) holder; 128 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 129 | vh.index.setText("" + childIndex); 130 | vh.name.setText(goods.name); 131 | vh.sku.setText("TYPE_FOOD"); 132 | } else { 133 | 134 | MilkVH vh = (MilkVH) holder; 135 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 136 | vh.index.setText("" + childIndex); 137 | vh.name.setText(goods.name); 138 | vh.sku.setText("TYPE_MILK"); 139 | } 140 | 141 | } 142 | 143 | 144 | } 145 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/adapter/HDividerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.adapter; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.view.LayoutInflater; 6 | import android.view.ViewGroup; 7 | 8 | import com.wanjian.view.NestedAdapter; 9 | import com.wanjian.view.demo.R; 10 | import com.wanjian.view.demo.data.Goods; 11 | import com.wanjian.view.demo.data.Shop; 12 | import com.wanjian.view.demo.vh.ChildVH; 13 | import com.wanjian.view.demo.vh.GroupVH; 14 | import com.wanjian.view.demo.vh.child.ClothesVH; 15 | import com.wanjian.view.demo.vh.child.FoodVH; 16 | import com.wanjian.view.demo.vh.child.MilkVH; 17 | import com.wanjian.view.demo.vh.group.AllVH; 18 | import com.wanjian.view.demo.vh.group.OffLineVH; 19 | import com.wanjian.view.demo.vh.group.OnLineVH; 20 | 21 | import java.util.List; 22 | 23 | /** 24 | * Created by wanjian on 2018/1/29. 25 | */ 26 | 27 | public class HDividerAdapter extends NestedAdapter { 28 | 29 | 30 | private List shopList; 31 | 32 | public HDividerAdapter(List shopList) { 33 | super(); 34 | this.shopList = shopList; 35 | } 36 | 37 | @Override 38 | public int getGroupCount() { 39 | return shopList.size(); 40 | } 41 | 42 | @Override 43 | public int getChildCount(int groupIndex) { 44 | return shopList.get(groupIndex).goods.size(); 45 | } 46 | 47 | @Override 48 | public int getGroupItemViewType(int groupIndex) { 49 | return shopList.get(groupIndex).shopType; 50 | } 51 | 52 | @Override 53 | public int getChildItemViewType(int groupIndex, int childIndex) { 54 | return shopList.get(groupIndex).goods.get(childIndex).goodsType; 55 | } 56 | 57 | @Override 58 | public GroupVH onCreateGroupViewHolder(ViewGroup parent, int viewType) { 59 | Log.d(TAG, ">>> onCreateGroupViewHolder: " + viewType); 60 | Context context = parent.getContext(); 61 | if (viewType == Shop.TYPE_ALL) { 62 | return new AllVH(LayoutInflater.from(context).inflate(R.layout.v_item_group_all, parent, false)); 63 | } else if (viewType == Shop.TYPE_OFFLINE) { 64 | return new OffLineVH(LayoutInflater.from(context).inflate(R.layout.v_item_group_offline, parent, false)); 65 | } else { 66 | return new OnLineVH(LayoutInflater.from(context).inflate(R.layout.v_item_group_online, parent, false)); 67 | } 68 | } 69 | 70 | @Override 71 | public void onBindGroupViewHolder(GroupVH holder, int position) { 72 | Log.d(TAG, "onBindGroupViewHolder: " + position + " " + holder); 73 | int type = getGroupItemViewType(position); 74 | if (type == Shop.TYPE_ALL) { 75 | AllVH vh = ((AllVH) holder); 76 | vh.index.setText("" + position); 77 | vh.count.setText("" + getChildCount(position)); 78 | vh.name.setText(shopList.get(position).shopName + "\nTYPE_ALL"); 79 | } else if (type == Shop.TYPE_OFFLINE) { 80 | OffLineVH vh = (OffLineVH) holder; 81 | vh.index.setText("" + position); 82 | vh.count.setText("" + getChildCount(position)); 83 | vh.name.setText(shopList.get(position).shopName + "\nTYPE_OFFLINE"); 84 | } else { 85 | OnLineVH vh = (OnLineVH) holder; 86 | vh.index.setText("" + position); 87 | vh.count.setText("" + getChildCount(position)); 88 | vh.name.setText(shopList.get(position).shopName + "\nTYPE_ONLINE"); 89 | 90 | } 91 | } 92 | 93 | @Override 94 | public ChildVH onCreateChildViewHolder(ViewGroup parent, int viewType) { 95 | Log.d(TAG, ">>> onCreateChildViewHolder: " + viewType); 96 | Context context = parent.getContext(); 97 | if (viewType == Goods.TYPE_CLOTHES) { 98 | return new ClothesVH(LayoutInflater.from(context).inflate(R.layout.v_item_child_clothes, parent, false)); 99 | 100 | } else if (viewType == Goods.TYPE_FOOD) { 101 | return new FoodVH(LayoutInflater.from(context).inflate(R.layout.v_item_child_food, parent, false)); 102 | } else { 103 | return new MilkVH(LayoutInflater.from(context).inflate(R.layout.v_item_child_milk, parent, false)); 104 | 105 | } 106 | } 107 | 108 | @Override 109 | public void onBindChildViewHolder(ChildVH holder, int groupIndex, int childIndex) { 110 | Log.d(TAG, "onBindChildViewHolder: " + groupIndex + ":" + childIndex); 111 | int type = getChildItemViewType(groupIndex, childIndex); 112 | if (type == Goods.TYPE_CLOTHES) { 113 | ClothesVH vh = (ClothesVH) holder; 114 | vh.index.setText(groupIndex + ":" + childIndex); 115 | vh.name.setText(shopList.get(groupIndex).goods.get(childIndex).name); 116 | vh.sku.setText("TYPE_CLOTHES"); 117 | } else if (type == Goods.TYPE_FOOD) { 118 | 119 | FoodVH vh = (FoodVH) holder; 120 | vh.index.setText(groupIndex + ":" + childIndex); 121 | vh.name.setText(shopList.get(groupIndex).goods.get(childIndex).name); 122 | vh.sku.setText("TYPE_FOOD"); 123 | } else { 124 | 125 | MilkVH vh = (MilkVH) holder; 126 | vh.index.setText(groupIndex + ":" + childIndex); 127 | vh.name.setText(shopList.get(groupIndex).goods.get(childIndex).name); 128 | vh.sku.setText("TYPE_MILK"); 129 | } 130 | } 131 | 132 | 133 | } 134 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/adapter/RefreshAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.adapter; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.wanjian.view.ExpandableAdapter; 10 | import com.wanjian.view.demo.R; 11 | import com.wanjian.view.demo.data.Goods; 12 | import com.wanjian.view.demo.data.Shop; 13 | import com.wanjian.view.demo.vh.ChildVH; 14 | import com.wanjian.view.demo.vh.GroupVH; 15 | import com.wanjian.view.demo.vh.child.ClothesVH; 16 | import com.wanjian.view.demo.vh.child.FoodVH; 17 | import com.wanjian.view.demo.vh.child.MilkVH; 18 | import com.wanjian.view.demo.vh.group.AllVH; 19 | import com.wanjian.view.demo.vh.group.OffLineVH; 20 | import com.wanjian.view.demo.vh.group.OnLineVH; 21 | 22 | import java.util.List; 23 | 24 | import static com.wanjian.view.demo.data.Goods.TYPE_FOOD; 25 | 26 | /** 27 | * Created by wanjian on 2018/1/29. 28 | */ 29 | 30 | public class RefreshAdapter extends ExpandableAdapter { 31 | 32 | 33 | private List shopList; 34 | 35 | public RefreshAdapter(List shopList) { 36 | super(); 37 | this.shopList = shopList; 38 | } 39 | 40 | @Override 41 | public int getGroupCount() { 42 | return shopList.size(); 43 | } 44 | 45 | @Override 46 | public int getChildCount(int groupIndex) { 47 | return shopList.get(groupIndex).goods.size(); 48 | } 49 | 50 | @Override 51 | public int getGroupItemViewType(int groupIndex) { 52 | return shopList.get(groupIndex).shopType; 53 | } 54 | 55 | @Override 56 | public int getChildItemViewType(int groupIndex, int childIndex) { 57 | return shopList.get(groupIndex).goods.get(childIndex).goodsType; 58 | } 59 | 60 | @Override 61 | public GroupVH onCreateGroupViewHolder(ViewGroup parent, int viewType) { 62 | Log.d(TAG, ">>> onCreateGroupViewHolder: " + viewType); 63 | Context context = parent.getContext(); 64 | if (viewType == Shop.TYPE_ALL) { 65 | return new AllVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_all, parent, false)); 66 | } else if (viewType == Shop.TYPE_OFFLINE) { 67 | return new OffLineVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_offline, parent, false)); 68 | } else { 69 | return new OnLineVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_online, parent, false)); 70 | } 71 | } 72 | 73 | @Override 74 | public void onBindGroupViewHolder(final GroupVH holder, final int position) { 75 | Log.d(TAG, "onBindGroupViewHolder: " + position + " " + holder); 76 | View.OnClickListener listener = new View.OnClickListener() { 77 | @Override 78 | public void onClick(View v) { 79 | notifyGroupChanged(position); 80 | } 81 | }; 82 | 83 | 84 | int type = getGroupItemViewType(position); 85 | if (type == Shop.TYPE_ALL) { 86 | AllVH vh = ((AllVH) holder); 87 | vh.index.setText((shopList.get(position).reBindTimes++) + ""); 88 | vh.count.setText("" + getChildCount(position)); 89 | vh.name.setText(shopList.get(position).shopName + " TYPE_ALL"); 90 | vh.refresh.setOnClickListener(listener); 91 | vh.refresh.setText("Refresh Group"); 92 | } else if (type == Shop.TYPE_OFFLINE) { 93 | OffLineVH vh = (OffLineVH) holder; 94 | vh.index.setText((shopList.get(position).reBindTimes++) + ""); 95 | vh.count.setText("" + getChildCount(position)); 96 | vh.name.setText(shopList.get(position).shopName + " TYPE_OFFLINE"); 97 | vh.refresh.setOnClickListener(listener); 98 | vh.refresh.setText("Refresh Group"); 99 | } else { 100 | OnLineVH vh = (OnLineVH) holder; 101 | vh.index.setText((shopList.get(position).reBindTimes++) + ""); 102 | vh.count.setText("" + getChildCount(position)); 103 | vh.name.setText(shopList.get(position).shopName + " TYPE_ONLINE"); 104 | vh.refresh.setOnClickListener(listener); 105 | vh.refresh.setText("Refresh Group"); 106 | } 107 | holder.itemView.setOnClickListener(new View.OnClickListener() { 108 | @Override 109 | public void onClick(View v) { 110 | notifyGroupItemChanged(position); 111 | } 112 | }); 113 | 114 | } 115 | 116 | @Override 117 | public ChildVH onCreateChildViewHolder(ViewGroup parent, int viewType) { 118 | Log.d(TAG, ">>> onCreateChildViewHolder: " + viewType); 119 | Context context = parent.getContext(); 120 | if (viewType == Goods.TYPE_CLOTHES) { 121 | return new ClothesVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_clothes, parent, false)); 122 | 123 | } else if (viewType == TYPE_FOOD) { 124 | return new FoodVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_food, parent, false)); 125 | } else { 126 | return new MilkVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_milk, parent, false)); 127 | 128 | } 129 | } 130 | 131 | @Override 132 | public void onBindChildViewHolder(ChildVH holder, final int groupIndex, final int childIndex) { 133 | Log.d(TAG, "onBindChildViewHolder: " + groupIndex + ":" + childIndex); 134 | int type = getChildItemViewType(groupIndex, childIndex); 135 | if (type == Goods.TYPE_CLOTHES) { 136 | ClothesVH vh = (ClothesVH) holder; 137 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 138 | vh.index.setText((goods.reBindTimes++) + ""); 139 | vh.name.setText(goods.name); 140 | vh.sku.setText("TYPE_CLOTHES"); 141 | } else if (type == TYPE_FOOD) { 142 | 143 | FoodVH vh = (FoodVH) holder; 144 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 145 | vh.index.setText((goods.reBindTimes++) + ""); 146 | vh.name.setText(goods.name); 147 | vh.sku.setText("TYPE_FOOD"); 148 | } else { 149 | 150 | MilkVH vh = (MilkVH) holder; 151 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 152 | vh.index.setText((goods.reBindTimes++) + ""); 153 | vh.name.setText(goods.name); 154 | vh.sku.setText("TYPE_MILK"); 155 | } 156 | holder.itemView.setOnClickListener(new View.OnClickListener() { 157 | @Override 158 | public void onClick(View v) { 159 | notifyChildItemChanged(groupIndex, childIndex); 160 | } 161 | }); 162 | 163 | } 164 | 165 | 166 | } 167 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/adapter/RemoveAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.adapter; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.wanjian.view.ExpandableAdapter; 10 | import com.wanjian.view.demo.R; 11 | import com.wanjian.view.demo.data.Goods; 12 | import com.wanjian.view.demo.data.Shop; 13 | import com.wanjian.view.demo.vh.ChildVH; 14 | import com.wanjian.view.demo.vh.GroupVH; 15 | import com.wanjian.view.demo.vh.child.ClothesVH; 16 | import com.wanjian.view.demo.vh.child.FoodVH; 17 | import com.wanjian.view.demo.vh.child.MilkVH; 18 | import com.wanjian.view.demo.vh.group.AllVH; 19 | import com.wanjian.view.demo.vh.group.OffLineVH; 20 | import com.wanjian.view.demo.vh.group.OnLineVH; 21 | 22 | import java.util.List; 23 | 24 | import static com.wanjian.view.demo.data.Goods.TYPE_FOOD; 25 | 26 | /** 27 | * Created by wanjian on 2018/1/29. 28 | */ 29 | 30 | public class RemoveAdapter extends ExpandableAdapter { 31 | 32 | 33 | private List shopList; 34 | 35 | public RemoveAdapter(List shopList) { 36 | super(); 37 | this.shopList = shopList; 38 | } 39 | 40 | @Override 41 | public int getGroupCount() { 42 | return shopList.size(); 43 | } 44 | 45 | @Override 46 | public int getChildCount(int groupIndex) { 47 | return shopList.get(groupIndex).goods.size(); 48 | } 49 | 50 | @Override 51 | public int getGroupItemViewType(int groupIndex) { 52 | return shopList.get(groupIndex).shopType; 53 | } 54 | 55 | @Override 56 | public int getChildItemViewType(int groupIndex, int childIndex) { 57 | return shopList.get(groupIndex).goods.get(childIndex).goodsType; 58 | } 59 | 60 | @Override 61 | public GroupVH onCreateGroupViewHolder(ViewGroup parent, int viewType) { 62 | Log.d(TAG, ">>> onCreateGroupViewHolder: " + viewType); 63 | Context context = parent.getContext(); 64 | if (viewType == Shop.TYPE_ALL) { 65 | return new AllVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_all, parent, false)); 66 | } else if (viewType == Shop.TYPE_OFFLINE) { 67 | return new OffLineVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_offline, parent, false)); 68 | } else { 69 | return new OnLineVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_online, parent, false)); 70 | } 71 | } 72 | 73 | @Override 74 | public void onBindGroupViewHolder(final GroupVH holder, final int position) { 75 | Log.d(TAG, "onBindGroupViewHolder: " + position + " " + holder); 76 | View.OnClickListener listener = new View.OnClickListener() { 77 | @Override 78 | public void onClick(View v) { 79 | // notifyGroupChanged(position); 80 | // 81 | // notifyChildItemRangeChanged(position, 0, getChildCount(position)); 82 | // 83 | // notifyChildItemRangeChanged(position, 1, getChildCount(position) - 1); 84 | // 85 | notifyChildItemRangeRemoved(position, 0, getChildCount(position)); 86 | shopList.get(position).goods.clear(); 87 | } 88 | }; 89 | 90 | 91 | int type = getGroupItemViewType(position); 92 | if (type == Shop.TYPE_ALL) { 93 | AllVH vh = ((AllVH) holder); 94 | vh.index.setText((shopList.get(position).reBindTimes++) + ""); 95 | vh.count.setText("" + getChildCount(position)); 96 | vh.name.setText(shopList.get(position).shopName + " TYPE_ALL"); 97 | vh.refresh.setOnClickListener(listener); 98 | vh.refresh.setText("Remove"); 99 | } else if (type == Shop.TYPE_OFFLINE) { 100 | OffLineVH vh = (OffLineVH) holder; 101 | vh.index.setText((shopList.get(position).reBindTimes++) + ""); 102 | vh.count.setText("" + getChildCount(position)); 103 | vh.name.setText(shopList.get(position).shopName + " TYPE_OFFLINE"); 104 | vh.refresh.setOnClickListener(listener); 105 | vh.refresh.setText("Remove"); 106 | } else { 107 | OnLineVH vh = (OnLineVH) holder; 108 | vh.index.setText((shopList.get(position).reBindTimes++) + ""); 109 | vh.count.setText("" + getChildCount(position)); 110 | vh.name.setText(shopList.get(position).shopName + " TYPE_ONLINE"); 111 | vh.refresh.setOnClickListener(listener); 112 | vh.refresh.setText("Remove"); 113 | } 114 | 115 | } 116 | 117 | @Override 118 | public ChildVH onCreateChildViewHolder(ViewGroup parent, int viewType) { 119 | Log.d(TAG, ">>> onCreateChildViewHolder: " + viewType); 120 | Context context = parent.getContext(); 121 | if (viewType == Goods.TYPE_CLOTHES) { 122 | return new ClothesVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_clothes, parent, false)); 123 | 124 | } else if (viewType == TYPE_FOOD) { 125 | return new FoodVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_food, parent, false)); 126 | } else { 127 | return new MilkVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_milk, parent, false)); 128 | 129 | } 130 | } 131 | 132 | @Override 133 | public void onBindChildViewHolder(ChildVH holder, final int groupIndex, final int childIndex) { 134 | Log.d(TAG, "onBindChildViewHolder: " + groupIndex + ":" + childIndex); 135 | int type = getChildItemViewType(groupIndex, childIndex); 136 | if (type == Goods.TYPE_CLOTHES) { 137 | ClothesVH vh = (ClothesVH) holder; 138 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 139 | vh.index.setText((goods.reBindTimes++) + ""); 140 | vh.name.setText(goods.name); 141 | vh.sku.setText("TYPE_CLOTHES"); 142 | } else if (type == TYPE_FOOD) { 143 | 144 | FoodVH vh = (FoodVH) holder; 145 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 146 | vh.index.setText((goods.reBindTimes++) + ""); 147 | vh.name.setText(goods.name); 148 | vh.sku.setText("TYPE_FOOD"); 149 | } else { 150 | 151 | MilkVH vh = (MilkVH) holder; 152 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 153 | vh.index.setText((goods.reBindTimes++) + ""); 154 | vh.name.setText(goods.name); 155 | vh.sku.setText("TYPE_MILK"); 156 | } 157 | 158 | } 159 | 160 | 161 | } 162 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/adapter/VDividerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.adapter; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.wanjian.view.NestedAdapter; 10 | import com.wanjian.view.demo.R; 11 | import com.wanjian.view.demo.data.Goods; 12 | import com.wanjian.view.demo.data.Shop; 13 | import com.wanjian.view.demo.vh.ChildVH; 14 | import com.wanjian.view.demo.vh.GroupVH; 15 | import com.wanjian.view.demo.vh.child.ClothesVH; 16 | import com.wanjian.view.demo.vh.child.FoodVH; 17 | import com.wanjian.view.demo.vh.child.MilkVH; 18 | import com.wanjian.view.demo.vh.group.AllVH; 19 | import com.wanjian.view.demo.vh.group.OffLineVH; 20 | import com.wanjian.view.demo.vh.group.OnLineVH; 21 | 22 | import java.util.List; 23 | 24 | import static com.wanjian.view.demo.data.Goods.TYPE_FOOD; 25 | 26 | /** 27 | * Created by wanjian on 2018/1/29. 28 | */ 29 | 30 | public class VDividerAdapter extends NestedAdapter { 31 | 32 | 33 | private List shopList; 34 | 35 | public VDividerAdapter(List shopList) { 36 | super(); 37 | this.shopList = shopList; 38 | } 39 | 40 | @Override 41 | public int getGroupCount() { 42 | return shopList.size(); 43 | } 44 | 45 | @Override 46 | public int getChildCount(int groupIndex) { 47 | return shopList.get(groupIndex).goods.size(); 48 | } 49 | 50 | @Override 51 | public int getGroupItemViewType(int groupIndex) { 52 | return shopList.get(groupIndex).shopType; 53 | } 54 | 55 | @Override 56 | public int getChildItemViewType(int groupIndex, int childIndex) { 57 | return shopList.get(groupIndex).goods.get(childIndex).goodsType; 58 | } 59 | 60 | @Override 61 | public GroupVH onCreateGroupViewHolder(ViewGroup parent, int viewType) { 62 | Log.d(TAG, ">>> onCreateGroupViewHolder: " + viewType); 63 | Context context = parent.getContext(); 64 | if (viewType == Shop.TYPE_ALL) { 65 | return new AllVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_all, parent, false)); 66 | } else if (viewType == Shop.TYPE_OFFLINE) { 67 | return new OffLineVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_offline, parent, false)); 68 | } else { 69 | return new OnLineVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_online, parent, false)); 70 | } 71 | } 72 | 73 | @Override 74 | public void onBindGroupViewHolder(final GroupVH holder, final int position) { 75 | Log.d(TAG, "onBindGroupViewHolder: " + position + " " + holder); 76 | 77 | int type = getGroupItemViewType(position); 78 | if (type == Shop.TYPE_ALL) { 79 | AllVH vh = ((AllVH) holder); 80 | vh.index.setText("" + position); 81 | vh.count.setText("child:" + getChildCount(position)); 82 | vh.name.setText(shopList.get(position).shopName + " TYPE_ALL"); 83 | vh.refresh.setVisibility(View.GONE); 84 | 85 | } else if (type == Shop.TYPE_OFFLINE) { 86 | OffLineVH vh = (OffLineVH) holder; 87 | vh.index.setText("" + position); 88 | vh.count.setText("child:" + getChildCount(position)); 89 | vh.name.setText(shopList.get(position).shopName + " TYPE_OFFLINE"); 90 | vh.refresh.setVisibility(View.GONE); 91 | 92 | } else { 93 | OnLineVH vh = (OnLineVH) holder; 94 | vh.index.setText("" + position); 95 | vh.count.setText("child:" + getChildCount(position)); 96 | vh.name.setText(shopList.get(position).shopName + " TYPE_ONLINE"); 97 | vh.refresh.setVisibility(View.GONE); 98 | 99 | 100 | } 101 | 102 | } 103 | 104 | @Override 105 | public ChildVH onCreateChildViewHolder(ViewGroup parent, int viewType) { 106 | Log.d(TAG, ">>> onCreateChildViewHolder: " + viewType); 107 | Context context = parent.getContext(); 108 | if (viewType == Goods.TYPE_CLOTHES) { 109 | return new ClothesVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_clothes, parent, false)); 110 | 111 | } else if (viewType == TYPE_FOOD) { 112 | return new FoodVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_food, parent, false)); 113 | } else { 114 | return new MilkVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_milk, parent, false)); 115 | 116 | } 117 | } 118 | 119 | @Override 120 | public void onBindChildViewHolder(ChildVH holder, final int groupIndex, final int childIndex) { 121 | Log.d(TAG, "onBindChildViewHolder: " + groupIndex + ":" + childIndex); 122 | int type = getChildItemViewType(groupIndex, childIndex); 123 | if (type == Goods.TYPE_CLOTHES) { 124 | ClothesVH vh = (ClothesVH) holder; 125 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 126 | vh.index.setText("" + childIndex); 127 | vh.name.setText(goods.name); 128 | vh.sku.setText("TYPE_CLOTHES"); 129 | } else if (type == TYPE_FOOD) { 130 | 131 | FoodVH vh = (FoodVH) holder; 132 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 133 | vh.index.setText("" + childIndex); 134 | vh.name.setText(goods.name); 135 | vh.sku.setText("TYPE_FOOD"); 136 | } else { 137 | 138 | MilkVH vh = (MilkVH) holder; 139 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 140 | vh.index.setText("" + childIndex); 141 | vh.name.setText(goods.name); 142 | vh.sku.setText("TYPE_MILK"); 143 | } 144 | 145 | } 146 | 147 | 148 | } 149 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/adapter/VExpandableAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.adapter; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.Button; 9 | 10 | import com.wanjian.view.ExpandableAdapter; 11 | import com.wanjian.view.demo.R; 12 | import com.wanjian.view.demo.data.Goods; 13 | import com.wanjian.view.demo.data.Shop; 14 | import com.wanjian.view.demo.vh.ChildVH; 15 | import com.wanjian.view.demo.vh.GroupVH; 16 | import com.wanjian.view.demo.vh.child.ClothesVH; 17 | import com.wanjian.view.demo.vh.child.FoodVH; 18 | import com.wanjian.view.demo.vh.child.MilkVH; 19 | import com.wanjian.view.demo.vh.group.AllVH; 20 | import com.wanjian.view.demo.vh.group.OffLineVH; 21 | import com.wanjian.view.demo.vh.group.OnLineVH; 22 | 23 | import java.util.List; 24 | 25 | import static com.wanjian.view.demo.data.Goods.TYPE_FOOD; 26 | 27 | /** 28 | * Created by wanjian on 2018/1/29. 29 | */ 30 | 31 | public class VExpandableAdapter extends ExpandableAdapter { 32 | 33 | 34 | private List shopList; 35 | 36 | public VExpandableAdapter(List shopList) { 37 | super(); 38 | this.shopList = shopList; 39 | } 40 | 41 | @Override 42 | public int getGroupCount() { 43 | return shopList.size(); 44 | } 45 | 46 | @Override 47 | public int getChildCount(int groupIndex) { 48 | return shopList.get(groupIndex).goods.size(); 49 | } 50 | 51 | @Override 52 | public int getGroupItemViewType(int groupIndex) { 53 | return shopList.get(groupIndex).shopType; 54 | } 55 | 56 | @Override 57 | public int getChildItemViewType(int groupIndex, int childIndex) { 58 | return shopList.get(groupIndex).goods.get(childIndex).goodsType; 59 | } 60 | 61 | @Override 62 | public GroupVH onCreateGroupViewHolder(ViewGroup parent, int viewType) { 63 | Log.d(TAG, ">>> onCreateGroupViewHolder: " + viewType); 64 | Context context = parent.getContext(); 65 | if (viewType == Shop.TYPE_ALL) { 66 | return new AllVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_all, parent, false)); 67 | } else if (viewType == Shop.TYPE_OFFLINE) { 68 | return new OffLineVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_offline, parent, false)); 69 | } else { 70 | return new OnLineVH(LayoutInflater.from(context).inflate(R.layout.h_item_group_online, parent, false)); 71 | } 72 | } 73 | 74 | @Override 75 | public void onBindGroupViewHolder(final GroupVH holder, final int position) { 76 | Log.d(TAG, "onBindGroupViewHolder: " + position + " " + holder); 77 | View.OnClickListener listener = new View.OnClickListener() { 78 | @Override 79 | public void onClick(View v) { 80 | 81 | if (isExpanded(position)) { 82 | collapseGroup(position); 83 | ((Button) v).setText("Open"); 84 | } else { 85 | expandGroup(position); 86 | ((Button) v).setText("Close"); 87 | } 88 | } 89 | }; 90 | 91 | int type = getGroupItemViewType(position); 92 | if (type == Shop.TYPE_ALL) { 93 | AllVH vh = ((AllVH) holder); 94 | vh.index.setText((shopList.get(position).reBindTimes++) + ""); 95 | vh.count.setText("" + getChildCount(position)); 96 | vh.name.setText(shopList.get(position).shopName + " TYPE_ALL"); 97 | vh.refresh.setOnClickListener(listener); 98 | vh.refresh.setText(isExpanded(position) ? "Close" : "Open"); 99 | } else if (type == Shop.TYPE_OFFLINE) { 100 | OffLineVH vh = (OffLineVH) holder; 101 | vh.index.setText((shopList.get(position).reBindTimes++) + ""); 102 | vh.count.setText("" + getChildCount(position)); 103 | vh.name.setText(shopList.get(position).shopName + " TYPE_OFFLINE"); 104 | vh.refresh.setOnClickListener(listener); 105 | vh.refresh.setText(isExpanded(position) ? "Close" : "Open"); 106 | 107 | } else { 108 | OnLineVH vh = (OnLineVH) holder; 109 | vh.index.setText((shopList.get(position).reBindTimes++) + ""); 110 | vh.count.setText("" + getChildCount(position)); 111 | vh.name.setText(shopList.get(position).shopName + " TYPE_ONLINE"); 112 | vh.refresh.setOnClickListener(listener); 113 | vh.refresh.setText(isExpanded(position) ? "Close" : "Open"); 114 | } 115 | 116 | } 117 | 118 | @Override 119 | public ChildVH onCreateChildViewHolder(ViewGroup parent, int viewType) { 120 | Log.d(TAG, ">>> onCreateChildViewHolder: " + viewType); 121 | Context context = parent.getContext(); 122 | if (viewType == Goods.TYPE_CLOTHES) { 123 | return new ClothesVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_clothes, parent, false)); 124 | 125 | } else if (viewType == TYPE_FOOD) { 126 | return new FoodVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_food, parent, false)); 127 | } else { 128 | return new MilkVH(LayoutInflater.from(context).inflate(R.layout.h_item_child_milk, parent, false)); 129 | 130 | } 131 | } 132 | 133 | @Override 134 | public void onBindChildViewHolder(ChildVH holder, final int groupIndex, final int childIndex) { 135 | Log.d(TAG, "onBindChildViewHolder: " + groupIndex + ":" + childIndex); 136 | int type = getChildItemViewType(groupIndex, childIndex); 137 | if (type == Goods.TYPE_CLOTHES) { 138 | ClothesVH vh = (ClothesVH) holder; 139 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 140 | vh.index.setText((goods.reBindTimes++) + ""); 141 | vh.name.setText(goods.name); 142 | vh.sku.setText("TYPE_CLOTHES"); 143 | } else if (type == TYPE_FOOD) { 144 | 145 | FoodVH vh = (FoodVH) holder; 146 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 147 | vh.index.setText((goods.reBindTimes++) + ""); 148 | vh.name.setText(goods.name); 149 | vh.sku.setText("TYPE_FOOD"); 150 | } else { 151 | 152 | MilkVH vh = (MilkVH) holder; 153 | Goods goods = shopList.get(groupIndex).goods.get(childIndex); 154 | vh.index.setText((goods.reBindTimes++) + ""); 155 | vh.name.setText(goods.name); 156 | vh.sku.setText("TYPE_MILK"); 157 | } 158 | 159 | } 160 | 161 | 162 | } 163 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/data/Goods.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.data; 2 | 3 | /** 4 | * Created by wanjian on 2018/1/29. 5 | */ 6 | 7 | public class Goods { 8 | 9 | 10 | public static final int TYPE_FOOD = 1; 11 | public static final int TYPE_CLOTHES = 2; 12 | public static final int TYPE_MILK = 3; 13 | 14 | public String name; 15 | public int index; 16 | public int goodsType; 17 | 18 | public int reBindTimes = 0; 19 | 20 | public Goods() { 21 | } 22 | 23 | public Goods(String name, int index, int goodsType, int reBindTimes) { 24 | this.name = name; 25 | this.index = index; 26 | this.goodsType = goodsType; 27 | this.reBindTimes = reBindTimes; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/data/Shop.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.data; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by wanjian on 2018/1/29. 7 | */ 8 | 9 | public class Shop { 10 | 11 | public static final int TYPE_ONLINE = 1; 12 | public static final int TYPE_OFFLINE = 2; 13 | public static final int TYPE_ALL = 3; 14 | 15 | public String shopName; 16 | public int index; 17 | public int shopType; 18 | 19 | public int reBindTimes = 0; 20 | public List goods; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.utils; 2 | 3 | import android.util.Log; 4 | 5 | import com.google.gson.Gson; 6 | import com.google.gson.GsonBuilder; 7 | import com.google.gson.JsonElement; 8 | import com.google.gson.JsonParser; 9 | import com.wanjian.view.NestedAdapter; 10 | import com.wanjian.view.demo.data.Goods; 11 | import com.wanjian.view.demo.data.Shop; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | /** 17 | * Created by wanjian on 2018/1/31. 18 | */ 19 | 20 | public class Utils { 21 | 22 | public static void showJson(List shopList) { 23 | String s = new Gson().toJson(shopList); 24 | Gson gson = new GsonBuilder().setPrettyPrinting().create(); 25 | JsonParser jp = new JsonParser(); 26 | JsonElement je = jp.parse(s); 27 | s = gson.toJson(je); 28 | Log.d(NestedAdapter.TAG, "showJson: \n" + s); 29 | } 30 | 31 | public static List geneRandomData() { 32 | List shopList = new ArrayList<>(); 33 | int count = (int) (Math.random() * 30); 34 | for (int i = 0; i < count; i++) { 35 | Shop shop = new Shop(); 36 | shop.index = i; 37 | 38 | double random = Math.random(); 39 | if (random < 0.3) { 40 | shop.shopType = Shop.TYPE_ONLINE; 41 | shop.shopName = "Amazon NO:" + i; 42 | } else if (random < 0.6) { 43 | shop.shopType = Shop.TYPE_OFFLINE; 44 | shop.shopName = "Suning NO:" + i; 45 | } else { 46 | shop.shopType = Shop.TYPE_ALL; 47 | shop.shopName = "Shop NO:" + i; 48 | } 49 | 50 | shop.goods = geneGoodsInfo(i); 51 | 52 | shopList.add(shop); 53 | } 54 | 55 | return shopList; 56 | 57 | } 58 | 59 | private static List geneGoodsInfo(int i) { 60 | List goodsList = new ArrayList<>(); 61 | 62 | int count = (int) (Math.random() * 5); 63 | for (int j = 0; j < count; j++) { 64 | Goods goods = new Goods(); 65 | 66 | goods.index = j; 67 | 68 | double random = Math.random(); 69 | if (random < 0.3) { 70 | goods.goodsType = Goods.TYPE_CLOTHES; 71 | goods.name = "Clothes NO:" + j; 72 | 73 | } else if (random < 0.6) { 74 | goods.goodsType = Goods.TYPE_FOOD; 75 | goods.name = "Food NO:" + j; 76 | 77 | } else { 78 | goods.goodsType = Goods.TYPE_MILK; 79 | goods.name = "Milk NO:" + j; 80 | 81 | } 82 | goodsList.add(goods); 83 | } 84 | 85 | return goodsList; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/vh/ChildVH.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.vh; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.View; 5 | 6 | /** 7 | * Created by wanjian on 2018/1/29. 8 | */ 9 | 10 | public class ChildVH extends RecyclerView.ViewHolder { 11 | public ChildVH(View itemView) { 12 | super(itemView); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/vh/GroupVH.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.vh; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.View; 5 | 6 | /** 7 | * Created by wanjian on 2018/1/29. 8 | */ 9 | 10 | public class GroupVH extends RecyclerView.ViewHolder { 11 | public GroupVH(View itemView) { 12 | super(itemView); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/vh/child/ClothesVH.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.vh.child; 2 | 3 | import android.view.View; 4 | import android.widget.TextView; 5 | 6 | import com.wanjian.view.demo.R; 7 | import com.wanjian.view.demo.vh.ChildVH; 8 | 9 | /** 10 | * Created by wanjian on 2018/1/29. 11 | */ 12 | 13 | public class ClothesVH extends ChildVH { 14 | 15 | public TextView index; 16 | public TextView name; 17 | public TextView sku; 18 | 19 | public ClothesVH(View itemView) { 20 | super(itemView); 21 | index = itemView.findViewById(R.id.index); 22 | name = itemView.findViewById(R.id.name); 23 | sku = itemView.findViewById(R.id.sku); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/vh/child/FoodVH.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.vh.child; 2 | 3 | import android.view.View; 4 | import android.widget.TextView; 5 | 6 | import com.wanjian.view.demo.R; 7 | import com.wanjian.view.demo.vh.ChildVH; 8 | 9 | /** 10 | * Created by wanjian on 2018/1/29. 11 | */ 12 | 13 | public class FoodVH extends ChildVH { 14 | 15 | 16 | public TextView index; 17 | public TextView name; 18 | public TextView sku; 19 | 20 | public FoodVH(View itemView) { 21 | super(itemView); 22 | index = itemView.findViewById(R.id.index); 23 | name = itemView.findViewById(R.id.name); 24 | sku = itemView.findViewById(R.id.sku); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/vh/child/MilkVH.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.vh.child; 2 | 3 | import android.view.View; 4 | import android.widget.TextView; 5 | 6 | import com.wanjian.view.demo.R; 7 | import com.wanjian.view.demo.vh.ChildVH; 8 | 9 | /** 10 | * Created by wanjian on 2018/1/29. 11 | */ 12 | 13 | public class MilkVH extends ChildVH { 14 | 15 | public TextView index; 16 | public TextView name; 17 | public TextView sku; 18 | 19 | public MilkVH(View itemView) { 20 | super(itemView); 21 | index = itemView.findViewById(R.id.index); 22 | name = itemView.findViewById(R.id.name); 23 | sku = itemView.findViewById(R.id.sku); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/vh/group/AllVH.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.vh.group; 2 | 3 | import android.view.View; 4 | import android.widget.Button; 5 | import android.widget.TextView; 6 | 7 | import com.wanjian.view.demo.R; 8 | import com.wanjian.view.demo.vh.GroupVH; 9 | 10 | /** 11 | * Created by wanjian on 2018/1/29. 12 | */ 13 | 14 | public class AllVH extends GroupVH { 15 | public TextView index; 16 | public TextView name; 17 | public TextView count; 18 | public Button refresh; 19 | 20 | public AllVH(View itemView) { 21 | super(itemView); 22 | index = itemView.findViewById(R.id.index); 23 | name = itemView.findViewById(R.id.name); 24 | count = itemView.findViewById(R.id.count); 25 | refresh = itemView.findViewById(R.id.refresh); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/vh/group/OffLineVH.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.vh.group; 2 | 3 | import android.view.View; 4 | import android.widget.Button; 5 | import android.widget.TextView; 6 | 7 | import com.wanjian.view.demo.R; 8 | import com.wanjian.view.demo.vh.GroupVH; 9 | 10 | /** 11 | * Created by wanjian on 2018/1/29. 12 | */ 13 | 14 | public class OffLineVH extends GroupVH { 15 | 16 | 17 | public TextView index; 18 | public TextView name; 19 | public TextView count; 20 | public Button refresh; 21 | 22 | public OffLineVH(View itemView) { 23 | super(itemView); 24 | index = itemView.findViewById(R.id.index); 25 | name = itemView.findViewById(R.id.name); 26 | count = itemView.findViewById(R.id.count); 27 | refresh = itemView.findViewById(R.id.refresh); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/wanjian/view/demo/vh/group/OnLineVH.java: -------------------------------------------------------------------------------- 1 | package com.wanjian.view.demo.vh.group; 2 | 3 | import android.view.View; 4 | import android.widget.Button; 5 | import android.widget.TextView; 6 | 7 | import com.wanjian.view.demo.R; 8 | import com.wanjian.view.demo.vh.GroupVH; 9 | 10 | /** 11 | * Created by wanjian on 2018/1/29. 12 | */ 13 | 14 | public class OnLineVH extends GroupVH { 15 | 16 | 17 | public TextView index; 18 | public TextView name; 19 | public TextView count; 20 | 21 | public Button refresh; 22 | 23 | public OnLineVH(View itemView) { 24 | super(itemView); 25 | index = itemView.findViewById(R.id.index); 26 | name = itemView.findViewById(R.id.name); 27 | count = itemView.findViewById(R.id.count); 28 | refresh = itemView.findViewById(R.id.refresh); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/h_divider_after_last.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/h_divider_before_first.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/h_divider_between_child.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/h_divider_between_group.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/h_divider_between_group_child.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/v_divider_after_last.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/v_divider_before_first.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/v_divider_between_child.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/v_divider_between_group.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/v_divider_between_group_child.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_add.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 |