├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── src └── main │ ├── res │ ├── drawable-hdpi │ │ ├── e_key.png │ │ ├── web.png │ │ ├── helper.png │ │ ├── auto_lock.png │ │ ├── check_off.png │ │ ├── check_on.png │ │ ├── password.png │ │ ├── user_name.png │ │ ├── action_home.png │ │ ├── arrow_right.png │ │ ├── check_device.png │ │ ├── check_state.png │ │ ├── ic_launcher.png │ │ ├── smart_ticket.png │ │ ├── action_explore.png │ │ ├── action_notify.png │ │ ├── action_setting.png │ │ ├── delete_disable.png │ │ ├── delete_enable.png │ │ ├── personal_image.png │ │ ├── repair_manage.png │ │ ├── security_monitor.png │ │ └── work_instruction.png │ ├── values-w820dp │ │ └── dimens.xml │ ├── drawable-nodpi │ │ └── ic_launcher.png │ ├── drawable-xhdpi │ │ └── ic_launcher.png │ ├── drawable-xxhdpi │ │ └── ic_launcher.png │ ├── transition │ │ ├── activity_fade.xml │ │ └── activity_slide.xml │ ├── drawable │ │ ├── bg_action_badge_dark.xml │ │ ├── bg_item_menu.xml │ │ ├── bord_item_menu.xml │ │ ├── bg_setting_check.xml │ │ ├── bg_check_update.xml │ │ ├── action_notify_with_badge.xml │ │ └── action_notify_level.xml │ ├── anim │ │ ├── slide_left_in.xml │ │ ├── slide_left_out.xml │ │ ├── slide_right_in.xml │ │ └── slide_right_out.xml │ ├── color │ │ └── color_item_menu_desc.xml │ ├── values-v21 │ │ └── styles.xml │ ├── layout │ │ ├── fragment_list_view.xml │ │ ├── fragment_expandable_list_view.xml │ │ ├── fragment_recycler_view.xml │ │ ├── item.xml │ │ ├── item_child.xml │ │ └── activity_main.xml │ ├── menu │ │ └── main.xml │ └── values │ │ ├── dimens.xml │ │ ├── font_dimens.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ ├── java │ └── com │ │ └── pacific │ │ └── example │ │ ├── ExploreBean.java │ │ ├── adapter │ │ ├── DataIO.java │ │ ├── RecyclerAdapter.java │ │ ├── Adapter.java │ │ ├── ExpandableAdapter.java │ │ ├── RecyclerAdapterHelper.java │ │ ├── AdapterHelper.java │ │ ├── ExpandableAdapterHelper.java │ │ ├── BaseRecyclerAdapter.java │ │ ├── BaseAdapter.java │ │ ├── BaseExpandableAdapter.java │ │ └── BaseAdapterHelper.java │ │ ├── MenuBean.java │ │ ├── MainActivity.java │ │ ├── ListViewFragment.java │ │ ├── VerticalItemDecoration.java │ │ ├── HorizontalItemDecoration.java │ │ ├── RecyclerViewFragment.java │ │ ├── ExpandableListViewFragment.java │ │ └── FlexibleDecoration.java │ └── AndroidManifest.xml ├── .idea ├── runConfigurations.xml └── gradle.xml ├── proguard-rules.pro ├── .gitignore ├── gradlew.bat └── gradlew /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/e_key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/e_key.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/web.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/helper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/helper.png -------------------------------------------------------------------------------- /src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 64dp 3 | 4 | -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/auto_lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/auto_lock.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/check_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/check_off.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/check_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/check_on.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/password.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/password.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/user_name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/user_name.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/action_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/action_home.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/arrow_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/arrow_right.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/check_device.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/check_device.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/check_state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/check_state.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/smart_ticket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/smart_ticket.png -------------------------------------------------------------------------------- /src/main/res/drawable-nodpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-nodpi/ic_launcher.png -------------------------------------------------------------------------------- /src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/action_explore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/action_explore.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/action_notify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/action_notify.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/action_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/action_setting.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/delete_disable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/delete_disable.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/delete_enable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/delete_enable.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/personal_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/personal_image.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/repair_manage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/repair_manage.png -------------------------------------------------------------------------------- /src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/security_monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/security_monitor.png -------------------------------------------------------------------------------- /src/main/res/drawable-hdpi/work_instruction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lingarajsankaravelu/app/master/src/main/res/drawable-hdpi/work_instruction.png -------------------------------------------------------------------------------- /src/main/res/transition/activity_fade.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/main/res/transition/activity_slide.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/main/res/drawable/bg_action_badge_dark.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/res/anim/slide_left_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/res/anim/slide_left_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/res/anim/slide_right_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/res/anim/slide_right_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Oct 21 11:34:03 PDT 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip 7 | -------------------------------------------------------------------------------- /src/main/res/drawable/bg_item_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/res/color/color_item_menu_desc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/res/drawable/bord_item_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /src/main/res/drawable/bg_setting_check.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/res/drawable/bg_check_update.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/res/drawable/action_notify_with_badge.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/res/drawable/action_notify_level.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | -------------------------------------------------------------------------------- /src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /src/main/res/layout/fragment_list_view.xml: -------------------------------------------------------------------------------- 1 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/res/layout/fragment_expandable_list_view.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/ExploreBean.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example; 2 | 3 | public class ExploreBean { 4 | 5 | private int iconResId; 6 | private String name; 7 | private String description; 8 | 9 | public ExploreBean(int iconResId, String name, String description) { 10 | this.iconResId = iconResId; 11 | this.name = name; 12 | this.description = description; 13 | } 14 | 15 | public String getName() { 16 | return name; 17 | } 18 | 19 | public String getDescription() { 20 | return description; 21 | } 22 | 23 | public int getIconResId() { 24 | return iconResId; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\GoogleAndroid\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 | -------------------------------------------------------------------------------- /src/main/res/layout/fragment_recycler_view.xml: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/adapter/DataIO.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example.adapter; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | interface DataIO { 7 | 8 | void add(T elem); 9 | 10 | void addAt(int location, T elem); 11 | 12 | void addAll(List elem); 13 | 14 | void addAllAt(int location, List list); 15 | 16 | void remove(T elem); 17 | 18 | void remove(List list); 19 | 20 | void removeAt(int index); 21 | 22 | void clear(); 23 | 24 | void replace(T oldElem, T newElem); 25 | 26 | void replaceAt(int index, T elem); 27 | 28 | void replaceAll(List elem); 29 | 30 | ArrayList getAll(); 31 | 32 | T get(int position); 33 | 34 | int getSize(); 35 | 36 | boolean contains(T elem); 37 | } 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | /*/build/ 3 | 4 | # Local configuration file (sdk path, etc) 5 | local.properties 6 | 7 | # Gradle generated files 8 | .gradle/ 9 | 10 | # Signing files 11 | .signing/ 12 | 13 | # User-specific configurations 14 | .idea/libraries/ 15 | .idea/workspace.xml 16 | .idea/tasks.xml 17 | .idea/.name 18 | .idea/compiler.xml 19 | .idea/copyright/profiles_settings.xml 20 | .idea/encodings.xml 21 | .idea/misc.xml 22 | .idea/modules.xml 23 | .idea/scopes/scope_settings.xml 24 | .idea/vcs.xml 25 | *.iml 26 | 27 | # OS-specific files 28 | .DS_Store 29 | .DS_Store? 30 | ._* 31 | .Spotlight-V100 32 | .Trashes 33 | ehthumbs.db 34 | Thumbs.db 35 | 36 | app/app.iml 37 | app/.idea/workspace.xml 38 | 39 | build/intermediates/dex-cache/cache.xml 40 | 41 | build/intermediates/dex-cache/cache.xml 42 | 43 | build/intermediates/dex-cache/cache.xml 44 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/adapter/RecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView.ViewHolder; 5 | 6 | import java.util.List; 7 | 8 | public abstract class RecyclerAdapter extends BaseRecyclerAdapter { 9 | 10 | public RecyclerAdapter(Context context, int layoutResId) { 11 | super(context, layoutResId); 12 | } 13 | 14 | public RecyclerAdapter(Context context, int layoutResId, List data) { 15 | super(context, layoutResId, data); 16 | } 17 | 18 | @Override 19 | protected com.pacific.example.adapter.RecyclerAdapterHelper getAdapterHelper(ViewHolder viewHolder) { 20 | return com.pacific.example.adapter.RecyclerAdapterHelper.get(viewHolder); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/MenuBean.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example; 2 | 3 | import java.util.List; 4 | 5 | public class MenuBean { 6 | private int iconResId; 7 | private String description; 8 | private List exploreBeanList; 9 | 10 | public MenuBean(int iconResId, String description) { 11 | this.iconResId = iconResId; 12 | this.description = description; 13 | } 14 | 15 | public String getDescription() { 16 | return description; 17 | } 18 | 19 | public int getIconResId() { 20 | return iconResId; 21 | } 22 | 23 | public List getExploreBeanList() { 24 | return exploreBeanList; 25 | } 26 | 27 | public void setExploreBeanList(List exploreBeanList) { 28 | this.exploreBeanList = exploreBeanList; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 5 | 11 | 16 | 17 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | 16dp 4 | 16dp 5 | 180dp 6 | 16dp 7 | 8 | 1024dp 9 | 1024dp 10 | 6dp 11 | 8dp 12 | 0dp 13 | 14 | 20dp 15 | 12dp 16 | 12dp 17 | 4dp 18 | 1dp 19 | 6dp 20 | 20dp 21 | 6dp 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/res/values/font_dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12sp 4 | 14sp 5 | 16sp 6 | 18sp 7 | 20sp 8 | 22sp 9 | 24sp 10 | 26sp 11 | 28sp 12 | 30sp 13 | 32sp 14 | 34sp 15 | 36sp 16 | 38sp 17 | 40sp 18 | 42sp 19 | 44sp 20 | 46sp 21 | 48sp 22 | 50sp 23 | 52sp 24 | 54sp 25 | 56sp 26 | 58sp 27 | -------------------------------------------------------------------------------- /src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #C5CAE9 6 | #536DFE 7 | #212121 8 | #727272 9 | #FFFFFF 10 | #B6B6B6 11 | 12 | #ffD7CCC8 13 | #ffff4444 14 | #8BC34A 15 | 16 | #303F9F 17 | #ffD7CCC8 18 | #FFFFFF 19 | 20 | #1976D2 21 | #CDDC39 22 | #795548 23 | #8BC34A 24 | #7C4DFF 25 | #727272 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | PacificAdapter 3 | ListView 4 | notification 5 | about 6 | exit 7 | 8 | ListView 9 | ExpandableListView 10 | RecyclerView 11 | 12 | EventBus 13 | RxJava 14 | Dagger 15 | Volley 16 | Retrofit 17 | RxAndroid 18 | Android 19 | IOS 20 | Web 21 | Sort 22 | one more press to exit 23 | close 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/res/layout/item.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 18 | 19 | 22 | 23 | 30 | 31 | -------------------------------------------------------------------------------- /src/main/res/layout/item_child.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 18 | 19 | 22 | 23 | 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/adapter/Adapter.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example.adapter; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Using the provided RecycleAdapterHelper, your code is minimalist. 11 | * 12 | * @param The type of the items in the list. 13 | */ 14 | 15 | public abstract class Adapter extends BaseAdapter { 16 | 17 | /** 18 | * Create a Adapter. 19 | * 20 | * @param context The context. 21 | * @param layoutResId The layout resource id of each item. 22 | */ 23 | public Adapter(Context context, int layoutResId) { 24 | super(context, layoutResId); 25 | } 26 | 27 | /** 28 | * Same as Adapter#Adapter(Context,int) but with 29 | * some initialization data. 30 | * 31 | * @param context The context. 32 | * @param layoutResId The layout resource id of each item. 33 | * @param data A new list is created out of this one to avoid mutable list 34 | */ 35 | public Adapter(Context context, int layoutResId, List data) { 36 | super(context, layoutResId, data); 37 | } 38 | 39 | protected AdapterHelper getAdapterHelper(int position, View convertView, ViewGroup parent) { 40 | return AdapterHelper.get(context, convertView, parent, layoutResId, position); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/adapter/ExpandableAdapter.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example.adapter; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | 7 | import com.pacific.example.adapter.ExpandableAdapterHelper; 8 | 9 | import java.util.List; 10 | 11 | public abstract class ExpandableAdapter extends BaseExpandableAdapter { 12 | 13 | /** 14 | * Create a ExpandableAdapter. 15 | * 16 | * @param context The context. 17 | * @param groupLayoutResId The layout resource id of each group item. 18 | * @param childLayoutResId The layout resource id of each child item. 19 | */ 20 | public ExpandableAdapter(Context context, int groupLayoutResId, int childLayoutResId) { 21 | super(context, groupLayoutResId, childLayoutResId); 22 | } 23 | 24 | /** 25 | * Create a BaseExpandableAdapter. 26 | * 27 | * @param context The context. 28 | * @param groupLayoutResId The layout resource id of each group item. 29 | * @param childLayoutResId The layout resource id of each child item. 30 | * @param data A new list is created out of this one to avoid mutable list 31 | */ 32 | public ExpandableAdapter(Context context, int groupLayoutResId, int childLayoutResId, List data) { 33 | super(context, groupLayoutResId, childLayoutResId, data); 34 | } 35 | 36 | @Override 37 | protected ExpandableAdapterHelper getAdapterHelper(int groupPosition, int childPosition, View convertView, ViewGroup parent) { 38 | if (childPosition == -1) { 39 | return ExpandableAdapterHelper.get(context, convertView, parent, groupLayoutResId, groupPosition, childPosition); 40 | } 41 | return ExpandableAdapterHelper.get(context, convertView, parent, childLayoutResId, groupPosition, childPosition); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/adapter/RecyclerAdapterHelper.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example.adapter; 2 | 3 | import android.support.v7.widget.RecyclerView.ViewHolder; 4 | import android.util.SparseArray; 5 | import android.view.View; 6 | 7 | final public class RecyclerAdapterHelper extends BaseAdapterHelper { 8 | 9 | protected ViewHolder viewHolder; 10 | 11 | private RecyclerAdapterHelper(ViewHolder viewHolder) { 12 | this.viewHolder = viewHolder; 13 | this.views = new SparseArray<>(); 14 | } 15 | 16 | /** 17 | * This method is the only entry point to get a RecyclerAdapterHelper. 18 | * 19 | * @param viewHolder The viewHolder arg passed to the onBindViewHolder() method. 20 | * @return A RecyclerAdapterHelper instance. 21 | */ 22 | static RecyclerAdapterHelper get(ViewHolder viewHolder) { 23 | RecyclerAdapterHelper helper; 24 | if (viewHolder.itemView.getTag() == null) { 25 | helper = new RecyclerAdapterHelper(viewHolder); 26 | viewHolder.itemView.setTag(helper); 27 | } else { 28 | helper = (RecyclerAdapterHelper) viewHolder.itemView.getTag(); 29 | } 30 | return helper; 31 | } 32 | 33 | /** 34 | * Retrieve the itemView 35 | */ 36 | @Override 37 | public View getItemView() { 38 | return viewHolder.itemView; 39 | } 40 | 41 | public int getItemViewType() { 42 | return viewHolder.getItemViewType(); 43 | } 44 | 45 | public int getAdapterPosition() { 46 | return viewHolder.getAdapterPosition(); 47 | } 48 | 49 | public int getLayoutPosition() { 50 | return viewHolder.getLayoutPosition(); 51 | } 52 | 53 | public int getOldPosition() { 54 | return viewHolder.getOldPosition(); 55 | } 56 | 57 | public boolean isRecyclable() { 58 | return viewHolder.isRecyclable(); 59 | } 60 | 61 | public RecyclerAdapterHelper setIsRecyclable(boolean recyclable) { 62 | viewHolder.setIsRecyclable(recyclable); 63 | return this; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 17 | 25 | 26 | 35 | 36 | 37 | 42 | 43 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/adapter/AdapterHelper.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example.adapter; 2 | 3 | import android.content.Context; 4 | import android.util.SparseArray; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | /** 10 | * Usage 11 | *

12 | * return AdapterHelper.get(context, convertView, parent, R.layout.item) 13 | * .setText(R.id.tvName, contact.getName()) 14 | * .setText(R.id.tvEmails, contact.getEmails().toString()) 15 | * .setText(R.id.tvNumbers, contact.getNumbers().toString()) 16 | * .getView(); 17 | *

18 | */ 19 | 20 | final public class AdapterHelper extends BaseAdapterHelper { 21 | 22 | protected View convertView; 23 | protected int position = -1; 24 | 25 | private AdapterHelper(Context context, ViewGroup parent, int layoutId, int position) { 26 | this.position = position; 27 | this.views = new SparseArray(); 28 | this.convertView = LayoutInflater.from(context).inflate(layoutId, parent, false); 29 | this.convertView.setTag(this); 30 | } 31 | 32 | /** 33 | * This method is the only entry point to get a AdapterHelper. 34 | * 35 | * @param context The current context. 36 | * @param convertView The convertView arg passed to the getView() method. 37 | * @param parent The parent arg passed to the getView() method. 38 | * @param layoutId The item view layout resource. 39 | * @param position The adapter position. 40 | * @return A AdapterHelper instance. 41 | */ 42 | static AdapterHelper get(Context context, View convertView, ViewGroup parent, int layoutId, int position) { 43 | if (convertView == null) { 44 | return new AdapterHelper(context, parent, layoutId, position); 45 | } 46 | AdapterHelper helper = (AdapterHelper) convertView.getTag(); 47 | helper.position = position; 48 | return helper; 49 | } 50 | 51 | @Override 52 | public View getItemView() { 53 | return convertView; 54 | } 55 | 56 | /** 57 | * Retrieve the overall position of the data in the list. 58 | * 59 | * @throws IllegalArgumentException If the position hasn't been set at the construction of the this helper. 60 | */ 61 | public int getPosition() { 62 | return position; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/adapter/ExpandableAdapterHelper.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example.adapter; 2 | 3 | import android.content.Context; 4 | import android.util.SparseArray; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | /** 10 | * Usage 11 | *

12 | * return AdapterHelper.get(context, convertView, parent, R.layout.item) 13 | * .setText(R.id.tvName, contact.getName()) 14 | * .setText(R.id.tvEmails, contact.getEmails().toString()) 15 | * .setText(R.id.tvNumbers, contact.getNumbers().toString()) 16 | * .getView(); 17 | *

18 | */ 19 | final public class ExpandableAdapterHelper extends BaseAdapterHelper { 20 | 21 | protected View convertView; 22 | protected int groupPosition = -1; 23 | protected int childPosition = -1; 24 | 25 | private ExpandableAdapterHelper(Context context, ViewGroup parent, int layoutId, int groupPosition, int childPosition) { 26 | this.groupPosition = groupPosition; 27 | this.childPosition = childPosition; 28 | this.views = new SparseArray(); 29 | this.convertView = LayoutInflater.from(context).inflate(layoutId, parent, false); 30 | this.convertView.setTag(this); 31 | } 32 | 33 | /** 34 | * This method is the only entry point to get a AdapterHelper. 35 | * 36 | * @param context The current context. 37 | * @param convertView The convertView arg passed to the getView() method. 38 | * @param parent The parent arg passed to the getView() method. 39 | * @param layoutId The item view layout resource. 40 | * @return A AdapterHelper instance. 41 | */ 42 | static ExpandableAdapterHelper get(Context context, View convertView, ViewGroup parent, int layoutId, int groupPosition, int childPosition) { 43 | if (convertView == null) { 44 | return new ExpandableAdapterHelper(context, parent, layoutId, groupPosition, childPosition); 45 | } 46 | ExpandableAdapterHelper helper = (ExpandableAdapterHelper) convertView.getTag(); 47 | helper.groupPosition = groupPosition; 48 | helper.childPosition = childPosition; 49 | return helper; 50 | } 51 | 52 | @Override 53 | public View getItemView() { 54 | return convertView; 55 | } 56 | 57 | /** 58 | * Retrieve the overall position of the data in the list. 59 | * 60 | * @throws IllegalArgumentException If the position hasn't been set at the construction of the this helper. 61 | */ 62 | public int getGroupPosition() { 63 | return groupPosition; 64 | } 65 | 66 | public int getChildPosition() { 67 | return childPosition; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example; 2 | 3 | import android.support.design.widget.TabLayout; 4 | import android.support.v4.app.Fragment; 5 | import android.support.v4.app.FragmentManager; 6 | import android.support.v4.app.FragmentPagerAdapter; 7 | import android.support.v4.view.ViewPager; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.os.Bundle; 10 | import android.support.v7.widget.Toolbar; 11 | import android.view.View; 12 | 13 | public class MainActivity extends AppCompatActivity { 14 | private Toolbar toolbar; 15 | private TabLayout tabLayout; 16 | private ViewPager viewPager; 17 | private PagerAdapter pagerAdapter; 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_main); 23 | setSupportActionBar(toolbar); 24 | 25 | toolbar = retrieveView(R.id.toolbar); 26 | tabLayout = retrieveView(R.id.tab_layout); 27 | viewPager = retrieveView(R.id.view_pager); 28 | pagerAdapter = new PagerAdapter(getSupportFragmentManager(), 3); 29 | viewPager.setOffscreenPageLimit(3); 30 | viewPager.setAdapter(pagerAdapter); 31 | tabLayout.setupWithViewPager(viewPager); 32 | tabLayout.getTabAt(0).setIcon(R.drawable.action_home); 33 | tabLayout.getTabAt(1).setIcon(R.drawable.action_explore); 34 | tabLayout.getTabAt(2).setIcon(R.drawable.action_setting); 35 | tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { 36 | @Override 37 | public void onTabSelected(TabLayout.Tab tab) { 38 | switch (tab.getPosition()) { 39 | case 0: 40 | toolbar.setTitle(R.string.title_navigation_fragment); 41 | break; 42 | case 1: 43 | toolbar.setTitle(R.string.title_setting_fragment); 44 | break; 45 | default: 46 | toolbar.setTitle(R.string.title_explore_fragment); 47 | break; 48 | } 49 | viewPager.setCurrentItem(tab.getPosition()); 50 | } 51 | 52 | @Override 53 | public void onTabUnselected(TabLayout.Tab tab) { 54 | } 55 | 56 | @Override 57 | public void onTabReselected(TabLayout.Tab tab) { 58 | } 59 | }); 60 | viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout)); 61 | 62 | } 63 | 64 | protected V retrieveView(int viewId) { 65 | return (V) findViewById(viewId); 66 | } 67 | 68 | 69 | public static class PagerAdapter extends FragmentPagerAdapter { 70 | private int count; 71 | 72 | public PagerAdapter(FragmentManager fm, int count) { 73 | super(fm); 74 | this.count = count; 75 | } 76 | 77 | @Override 78 | public Fragment getItem(int position) { 79 | switch (position) { 80 | case 0: 81 | return ListViewFragment.newInstance(); 82 | case 1: 83 | return ExpandableListViewFragment.newInstance(); 84 | default: 85 | return RecyclerViewFragment.newInstance(); 86 | } 87 | } 88 | 89 | @Override 90 | public int getCount() { 91 | return count; 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/adapter/BaseRecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.support.v7.widget.RecyclerView.ViewHolder; 6 | import android.view.LayoutInflater; 7 | import android.view.ViewGroup; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * Abstraction class of a BaseAdapter in which you only need 14 | * to provide the convert() implementation.
15 | * Using the provided RecycleAdapterHelper, your code is minimalist. 16 | * 17 | * @param The type of the items in the list. 18 | */ 19 | abstract class BaseRecyclerAdapter extends RecyclerView.Adapter implements DataIO { 20 | 21 | protected final Context context; 22 | protected final LayoutInflater layoutInflater; 23 | protected final int layoutResId; 24 | protected final ArrayList data; 25 | 26 | public BaseRecyclerAdapter(Context context, int layoutResId) { 27 | this(context, layoutResId, null); 28 | } 29 | 30 | public BaseRecyclerAdapter(Context context, int layoutResId, List data) { 31 | this.context = context; 32 | this.layoutResId = layoutResId; 33 | this.layoutInflater = LayoutInflater.from(context); 34 | this.data = data == null ? new ArrayList() : new ArrayList<>(data); 35 | } 36 | 37 | 38 | @Override 39 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 40 | return new ViewHolder(layoutInflater.inflate(layoutResId, parent, false)) { 41 | }; 42 | } 43 | 44 | @Override 45 | public void onBindViewHolder(ViewHolder holder, int position) { 46 | H helper = getAdapterHelper(holder); 47 | T item = get(position); 48 | convert(helper, item); 49 | } 50 | 51 | @Override 52 | public int getItemCount() { 53 | return getSize(); 54 | } 55 | 56 | @Override 57 | public void add(T elem) { 58 | data.add(elem); 59 | notifyDataSetChanged(); 60 | } 61 | 62 | @Override 63 | public void addAt(int location, T elem) { 64 | data.add(location, elem); 65 | notifyDataSetChanged(); 66 | } 67 | 68 | @Override 69 | public void addAll(List elem) { 70 | data.addAll(elem); 71 | notifyDataSetChanged(); 72 | } 73 | 74 | @Override 75 | public void addAllAt(int location, List elements) { 76 | data.addAll(location, elements); 77 | notifyDataSetChanged(); 78 | } 79 | 80 | @Override 81 | public void remove(T elem) { 82 | data.remove(elem); 83 | notifyDataSetChanged(); 84 | } 85 | 86 | @Override 87 | public void removeAt(int index) { 88 | data.remove(index); 89 | notifyDataSetChanged(); 90 | } 91 | 92 | @Override 93 | public void remove(List list) { 94 | data.removeAll(list); 95 | notifyDataSetChanged(); 96 | } 97 | 98 | @Override 99 | public void clear() { 100 | if (data != null && data.size() > 0) { 101 | data.clear(); 102 | notifyDataSetChanged(); 103 | } 104 | } 105 | 106 | @Override 107 | public void replace(T oldElem, T newElem) { 108 | replaceAt(data.indexOf(oldElem), newElem); 109 | } 110 | 111 | @Override 112 | public void replaceAt(int index, T elem) { 113 | data.set(index, elem); 114 | notifyDataSetChanged(); 115 | } 116 | 117 | @Override 118 | public void replaceAll(List elem) { 119 | if (data.size() > 0) { 120 | data.clear(); 121 | } 122 | data.addAll(elem); 123 | notifyDataSetChanged(); 124 | } 125 | 126 | @Override 127 | public T get(int position) { 128 | if (position >= data.size()) 129 | return null; 130 | return data.get(position); 131 | } 132 | 133 | @Override 134 | public ArrayList getAll() { 135 | return data; 136 | } 137 | 138 | @Override 139 | public int getSize() { 140 | return data.size(); 141 | } 142 | 143 | @Override 144 | public boolean contains(T elem) { 145 | return data.contains(elem); 146 | } 147 | 148 | /** 149 | * Implement this method and use the helper to adapt the view to the given item. 150 | * 151 | * @param helper A fully initialized helper. 152 | * @param item The item that needs to be displayed. 153 | */ 154 | protected abstract void convert(H helper, T item); 155 | 156 | 157 | /** 158 | * You can override this method to use a custom RecycleAdapterHelper in order to fit your needs 159 | * 160 | * @param viewHolder The viewHolder that this view will eventually be attached to 161 | * @return An instance of RecycleAdapterHelper 162 | */ 163 | protected abstract H getAdapterHelper(ViewHolder viewHolder); 164 | } 165 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/ListViewFragment.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ListView; 11 | 12 | import com.pacific.example.adapter.Adapter; 13 | import com.pacific.example.adapter.AdapterHelper; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | public class ListViewFragment extends Fragment { 19 | 20 | private ListView listView; 21 | private Adapter adapter; 22 | 23 | public ListViewFragment() { 24 | } 25 | 26 | public static ListViewFragment newInstance() { 27 | ListViewFragment fragment = new ListViewFragment(); 28 | Bundle args = new Bundle(); 29 | fragment.setArguments(args); 30 | return fragment; 31 | } 32 | 33 | @Override 34 | public void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | 37 | adapter = new Adapter(getContext(), R.layout.item) { 38 | @Override 39 | protected void convert(final AdapterHelper helper, ExploreBean exploreBean) { 40 | helper.setImageResource(R.id.img_explore_icon, exploreBean.getIconResId()); 41 | final int position = helper.getPosition(); 42 | helper.setText(R.id.tv_explore_name, "____Index: " + String.valueOf(position)); 43 | helper.setText(R.id.tv_explore_desc, exploreBean.getDescription()); 44 | helper.getItemView().setOnClickListener(new View.OnClickListener() { 45 | @Override 46 | public void onClick(View v) { 47 | clickSnack(position); 48 | } 49 | }); 50 | } 51 | }; 52 | } 53 | 54 | @Override 55 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 56 | return inflater.inflate(R.layout.fragment_list_view, container, false); 57 | } 58 | 59 | @Override 60 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 61 | super.onViewCreated(view, savedInstanceState); 62 | listView = (ListView) view.findViewById(R.id.lv_list); 63 | listView.setAdapter(adapter); 64 | load(); 65 | } 66 | 67 | public void load() { 68 | List list = new ArrayList<>(); 69 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 70 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 71 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 72 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 73 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 74 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 75 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 76 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 77 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 78 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 79 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 80 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 81 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 82 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 83 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 84 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 85 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 86 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 87 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 88 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 89 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 90 | adapter.addAll(list); 91 | } 92 | 93 | public void clickSnack(int position) { 94 | Snackbar.make(listView, "click item " + String.valueOf(position), Snackbar.LENGTH_SHORT) 95 | .setAction(R.string.close, new View.OnClickListener() { 96 | @Override 97 | public void onClick(View v) { 98 | } 99 | }).show(); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/VerticalItemDecoration.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example; 2 | 3 | import android.content.Context; 4 | import android.graphics.Rect; 5 | import android.graphics.drawable.Drawable; 6 | import android.support.annotation.DimenRes; 7 | import android.support.v4.view.ViewCompat; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.view.View; 10 | 11 | public class VerticalItemDecoration extends FlexibleDecoration { 12 | 13 | private MarginProvider mMarginProvider; 14 | 15 | protected VerticalItemDecoration(Builder builder) { 16 | super(builder); 17 | mMarginProvider = builder.mMarginProvider; 18 | } 19 | 20 | @Override 21 | protected Rect getDividerBound(int position, RecyclerView parent, View child) { 22 | Rect bounds = new Rect(0, 0, 0, 0); 23 | int transitionX = (int) ViewCompat.getTranslationX(child); 24 | int transitionY = (int) ViewCompat.getTranslationY(child); 25 | RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); 26 | bounds.top = parent.getPaddingTop() + 27 | mMarginProvider.dividerTopMargin(position, parent) + transitionY; 28 | bounds.bottom = parent.getHeight() - parent.getPaddingBottom() - 29 | mMarginProvider.dividerBottomMargin(position, parent) + transitionY; 30 | 31 | int dividerSize = getDividerSize(position, parent); 32 | if (mDividerType == DividerType.DRAWABLE) { 33 | bounds.left = child.getRight() + params.leftMargin + transitionX; 34 | bounds.right = bounds.left + dividerSize; 35 | } else { 36 | bounds.left = child.getRight() + params.leftMargin + dividerSize / 2 + transitionX; 37 | bounds.right = bounds.left; 38 | } 39 | 40 | return bounds; 41 | } 42 | 43 | @Override 44 | protected void setItemOffsets(Rect outRect, int position, RecyclerView parent) { 45 | outRect.set(0, 0, getDividerSize(position, parent), 0); 46 | } 47 | 48 | private int getDividerSize(int position, RecyclerView parent) { 49 | if (mPaintProvider != null) { 50 | return (int) mPaintProvider.dividerPaint(position, parent).getStrokeWidth(); 51 | } else if (mSizeProvider != null) { 52 | return mSizeProvider.dividerSize(position, parent); 53 | } else if (mDrawableProvider != null) { 54 | Drawable drawable = mDrawableProvider.drawableProvider(position, parent); 55 | return drawable.getIntrinsicWidth(); 56 | } 57 | throw new RuntimeException("failed to get size"); 58 | } 59 | 60 | /** 61 | * Interface for controlling divider margin 62 | */ 63 | public interface MarginProvider { 64 | 65 | /** 66 | * Returns top margin of divider. 67 | * 68 | * @param position Divider position 69 | * @param parent RecyclerView 70 | * @return top margin 71 | */ 72 | int dividerTopMargin(int position, RecyclerView parent); 73 | 74 | /** 75 | * Returns bottom margin of divider. 76 | * 77 | * @param position Divider position 78 | * @param parent RecyclerView 79 | * @return bottom margin 80 | */ 81 | int dividerBottomMargin(int position, RecyclerView parent); 82 | } 83 | 84 | public static class Builder extends FlexibleDecoration.Builder { 85 | 86 | private MarginProvider mMarginProvider = new MarginProvider() { 87 | @Override 88 | public int dividerTopMargin(int position, RecyclerView parent) { 89 | return 0; 90 | } 91 | 92 | @Override 93 | public int dividerBottomMargin(int position, RecyclerView parent) { 94 | return 0; 95 | } 96 | }; 97 | 98 | public Builder(Context context) { 99 | super(context); 100 | } 101 | 102 | public Builder margin(final int topMargin, final int bottomMargin) { 103 | return marginProvider(new MarginProvider() { 104 | @Override 105 | public int dividerTopMargin(int position, RecyclerView parent) { 106 | return topMargin; 107 | } 108 | 109 | @Override 110 | public int dividerBottomMargin(int position, RecyclerView parent) { 111 | return bottomMargin; 112 | } 113 | }); 114 | } 115 | 116 | public Builder margin(int verticalMargin) { 117 | return margin(verticalMargin, verticalMargin); 118 | } 119 | 120 | public Builder marginResId(@DimenRes int topMarginId, @DimenRes int bottomMarginId) { 121 | return margin(mResources.getDimensionPixelSize(topMarginId), 122 | mResources.getDimensionPixelSize(bottomMarginId)); 123 | } 124 | 125 | public Builder marginResId(@DimenRes int verticalMarginId) { 126 | return marginResId(verticalMarginId, verticalMarginId); 127 | } 128 | 129 | public Builder marginProvider(MarginProvider provider) { 130 | mMarginProvider = provider; 131 | return this; 132 | } 133 | 134 | public VerticalItemDecoration build() { 135 | checkBuilderParams(); 136 | return new VerticalItemDecoration(this); 137 | } 138 | } 139 | } -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/HorizontalItemDecoration.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example; 2 | 3 | import android.content.Context; 4 | import android.graphics.Rect; 5 | import android.graphics.drawable.Drawable; 6 | import android.support.annotation.DimenRes; 7 | import android.support.v4.view.ViewCompat; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.view.View; 10 | 11 | public class HorizontalItemDecoration extends FlexibleDecoration { 12 | 13 | private MarginProvider mMarginProvider; 14 | 15 | protected HorizontalItemDecoration(Builder builder) { 16 | super(builder); 17 | mMarginProvider = builder.mMarginProvider; 18 | } 19 | 20 | @Override 21 | protected Rect getDividerBound(int position, RecyclerView parent, View child) { 22 | Rect bounds = new Rect(0, 0, 0, 0); 23 | int transitionX = (int) ViewCompat.getTranslationX(child); 24 | int transitionY = (int) ViewCompat.getTranslationY(child); 25 | RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); 26 | bounds.left = parent.getPaddingLeft() + 27 | mMarginProvider.dividerLeftMargin(position, parent) + transitionX; 28 | bounds.right = parent.getWidth() - parent.getPaddingRight() - 29 | mMarginProvider.dividerRightMargin(position, parent) + transitionX; 30 | 31 | int dividerSize = getDividerSize(position, parent); 32 | if (mDividerType == DividerType.DRAWABLE) { 33 | bounds.top = child.getBottom() + params.topMargin + transitionY; 34 | bounds.bottom = bounds.top + dividerSize; 35 | } else { 36 | bounds.top = child.getBottom() + params.topMargin + dividerSize / 2 + transitionY; 37 | bounds.bottom = bounds.top; 38 | } 39 | 40 | return bounds; 41 | } 42 | 43 | @Override 44 | protected void setItemOffsets(Rect outRect, int position, RecyclerView parent) { 45 | outRect.set(0, 0, 0, getDividerSize(position, parent)); 46 | } 47 | 48 | private int getDividerSize(int position, RecyclerView parent) { 49 | if (mPaintProvider != null) { 50 | return (int) mPaintProvider.dividerPaint(position, parent).getStrokeWidth(); 51 | } else if (mSizeProvider != null) { 52 | return mSizeProvider.dividerSize(position, parent); 53 | } else if (mDrawableProvider != null) { 54 | Drawable drawable = mDrawableProvider.drawableProvider(position, parent); 55 | return drawable.getIntrinsicHeight(); 56 | } 57 | throw new RuntimeException("failed to get size"); 58 | } 59 | 60 | /** 61 | * Interface for controlling divider margin 62 | */ 63 | public interface MarginProvider { 64 | 65 | /** 66 | * Returns left margin of divider. 67 | * 68 | * @param position Divider position 69 | * @param parent RecyclerView 70 | * @return left margin 71 | */ 72 | int dividerLeftMargin(int position, RecyclerView parent); 73 | 74 | /** 75 | * Returns right margin of divider. 76 | * 77 | * @param position Divider position 78 | * @param parent RecyclerView 79 | * @return right margin 80 | */ 81 | int dividerRightMargin(int position, RecyclerView parent); 82 | } 83 | 84 | public static class Builder extends FlexibleDecoration.Builder { 85 | 86 | private MarginProvider mMarginProvider = new MarginProvider() { 87 | @Override 88 | public int dividerLeftMargin(int position, RecyclerView parent) { 89 | return 0; 90 | } 91 | 92 | @Override 93 | public int dividerRightMargin(int position, RecyclerView parent) { 94 | return 0; 95 | } 96 | }; 97 | 98 | public Builder(Context context) { 99 | super(context); 100 | } 101 | 102 | public Builder margin(final int leftMargin, final int rightMargin) { 103 | return marginProvider(new MarginProvider() { 104 | @Override 105 | public int dividerLeftMargin(int position, RecyclerView parent) { 106 | return leftMargin; 107 | } 108 | 109 | @Override 110 | public int dividerRightMargin(int position, RecyclerView parent) { 111 | return rightMargin; 112 | } 113 | }); 114 | } 115 | 116 | public Builder margin(int horizontalMargin) { 117 | return margin(horizontalMargin, horizontalMargin); 118 | } 119 | 120 | public Builder marginResId(@DimenRes int leftMarginId, @DimenRes int rightMarginId) { 121 | return margin(mResources.getDimensionPixelSize(leftMarginId), 122 | mResources.getDimensionPixelSize(rightMarginId)); 123 | } 124 | 125 | public Builder marginResId(@DimenRes int horizontalMarginId) { 126 | return marginResId(horizontalMarginId, horizontalMarginId); 127 | } 128 | 129 | public Builder marginProvider(MarginProvider provider) { 130 | mMarginProvider = provider; 131 | return this; 132 | } 133 | 134 | public HorizontalItemDecoration build() { 135 | checkBuilderParams(); 136 | return new HorizontalItemDecoration(this); 137 | } 138 | } 139 | } -------------------------------------------------------------------------------- /src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 15 | 16 | 23 | 24 | 30 | 31 | 35 | 36 | 40 | 41 | 45 | 46 | 50 | 51 | 54 | 55 | 58 | 59 | 65 | 66 | 72 | 73 | 81 | 82 | 85 | 86 | 92 | 93 | 97 | 98 | 109 | 110 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/RecyclerViewFragment.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v7.widget.LinearLayoutManager; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | 13 | import com.pacific.example.adapter.RecyclerAdapterHelper; 14 | import com.pacific.example.adapter.RecyclerAdapter; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | 20 | public class RecyclerViewFragment extends Fragment { 21 | private RecyclerView recyclerView; 22 | private RecyclerAdapter adapter; 23 | 24 | public RecyclerViewFragment() { 25 | } 26 | 27 | public static RecyclerViewFragment newInstance() { 28 | RecyclerViewFragment fragment = new RecyclerViewFragment(); 29 | Bundle args = new Bundle(); 30 | fragment.setArguments(args); 31 | return fragment; 32 | } 33 | 34 | @Override 35 | public void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | 38 | adapter = new RecyclerAdapter(getContext(), R.layout.item) { 39 | @Override 40 | protected void convert(final RecyclerAdapterHelper helper, ExploreBean exploreBean) { 41 | helper.setImageResource(R.id.img_explore_icon, exploreBean.getIconResId()) 42 | .setText(R.id.tv_explore_desc, exploreBean.getDescription()) 43 | .getItemView().setOnClickListener(new View.OnClickListener() { 44 | @Override 45 | public void onClick(View v) { 46 | clickSnack(helper.getAdapterPosition()); 47 | } 48 | }); 49 | } 50 | }; 51 | } 52 | 53 | @Override 54 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 55 | return inflater.inflate(R.layout.fragment_recycler_view, container, false); 56 | } 57 | 58 | @Override 59 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 60 | super.onViewCreated(view, savedInstanceState); 61 | recyclerView = (RecyclerView) view.findViewById(R.id.rv_explore); 62 | recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false)); 63 | recyclerView.addItemDecoration(new HorizontalItemDecoration 64 | .Builder(getContext()) 65 | .sizeResId(R.dimen.height_explore_divider) 66 | .showLastDivider() 67 | .build()); 68 | recyclerView.setAdapter(adapter); 69 | load(); 70 | } 71 | 72 | public void clickSnack(int position) { 73 | Snackbar.make(recyclerView, "click item " + String.valueOf(position), Snackbar.LENGTH_SHORT) 74 | .setAction(R.string.close, new View.OnClickListener() { 75 | @Override 76 | public void onClick(View v) { 77 | } 78 | }).show(); 79 | } 80 | 81 | public void load() { 82 | List list = new ArrayList<>(); 83 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 84 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 85 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 86 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 87 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 88 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 89 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 90 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 91 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 92 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 93 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 94 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 95 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 96 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 97 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 98 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 99 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 100 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 101 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 102 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 103 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 104 | adapter.addAll(list); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/adapter/BaseAdapter.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example.adapter; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * Abstraction class of a BaseAdapter in which you only need to provide the 12 | * convert() implementation.
13 | * Using the provided RecycleAdapterHelper, your code is minimalist. 14 | * 15 | * @param The type of the items in the list. 16 | */ 17 | abstract class BaseAdapter extends android.widget.BaseAdapter implements DataIO { 18 | 19 | protected final Context context; 20 | protected final int layoutResId; 21 | protected final ArrayList data; 22 | 23 | /** 24 | * Create a Adapter. 25 | * 26 | * @param context The context. 27 | * @param layoutResId The layout resource id of each item. 28 | */ 29 | public BaseAdapter(Context context, int layoutResId) { 30 | this(context, layoutResId, null); 31 | } 32 | 33 | /** 34 | * Create a Adapter. 35 | * 36 | * @param context The context. 37 | * @param layoutResId The layout resource id of each item. 38 | * @param data A new list is created out of this one to avoid mutable list 39 | */ 40 | public BaseAdapter(Context context, int layoutResId, List data) { 41 | this.data = data == null ? new ArrayList() : new ArrayList<>(data); 42 | this.context = context; 43 | this.layoutResId = layoutResId; 44 | } 45 | 46 | @Override 47 | public int getCount() { 48 | return getSize(); 49 | } 50 | 51 | @Override 52 | public T getItem(int position) { 53 | return get(position); 54 | } 55 | 56 | @Override 57 | public long getItemId(int position) { 58 | return position; 59 | } 60 | 61 | @Override 62 | public View getView(int position, View convertView, ViewGroup parent) { 63 | H helper = getAdapterHelper(position, convertView, parent); 64 | T item = getItem(position); 65 | convert(helper, item); 66 | return helper.getItemView(); 67 | } 68 | 69 | @Override 70 | public boolean isEnabled(int position) { 71 | return position < data.size(); 72 | } 73 | 74 | @Override 75 | public void add(T elem) { 76 | data.add(elem); 77 | notifyDataSetChanged(); 78 | } 79 | 80 | @Override 81 | public void addAt(int location, T elem) { 82 | data.add(location, elem); 83 | notifyDataSetChanged(); 84 | } 85 | 86 | @Override 87 | public void addAll(List elem) { 88 | data.addAll(elem); 89 | notifyDataSetChanged(); 90 | } 91 | 92 | @Override 93 | public void addAllAt(int location, List elements) { 94 | data.addAll(location, elements); 95 | notifyDataSetChanged(); 96 | } 97 | 98 | @Override 99 | public void remove(T elem) { 100 | data.remove(elem); 101 | notifyDataSetChanged(); 102 | } 103 | 104 | @Override 105 | public void removeAt(int index) { 106 | data.remove(index); 107 | notifyDataSetChanged(); 108 | } 109 | 110 | @Override 111 | public void remove(List list) { 112 | data.removeAll(list); 113 | notifyDataSetChanged(); 114 | } 115 | 116 | @Override 117 | public void clear() { 118 | if (data != null && data.size() > 0) { 119 | data.clear(); 120 | notifyDataSetChanged(); 121 | } 122 | } 123 | 124 | @Override 125 | public void replace(T oldElem, T newElem) { 126 | replaceAt(data.indexOf(oldElem), newElem); 127 | } 128 | 129 | @Override 130 | public void replaceAt(int index, T elem) { 131 | data.set(index, elem); 132 | notifyDataSetChanged(); 133 | } 134 | 135 | @Override 136 | public void replaceAll(List elem) { 137 | if (data.size() > 0) { 138 | data.clear(); 139 | } 140 | data.addAll(elem); 141 | notifyDataSetChanged(); 142 | } 143 | 144 | @Override 145 | public T get(int position) { 146 | if (position >= data.size()) 147 | return null; 148 | return data.get(position); 149 | } 150 | 151 | @Override 152 | public ArrayList getAll() { 153 | return data; 154 | } 155 | 156 | @Override 157 | public int getSize() { 158 | return data.size(); 159 | } 160 | 161 | @Override 162 | public boolean contains(T elem) { 163 | return data.contains(elem); 164 | } 165 | 166 | /** 167 | * Implement this method and use the helper to adapt the view to the given 168 | * item. 169 | * 170 | * @param helper A fully initialized helper. 171 | * @param item The item that needs to be displayed. 172 | */ 173 | protected abstract void convert(H helper, T item); 174 | 175 | /** 176 | * You can override this method to use a custom RecycleAdapterHelper in order 177 | * to fit your needs 178 | * 179 | * @param position The position of the item within the adapter's data set of the 180 | * item whose view we want. 181 | * @param convertView The old view to reuse, if possible. Note: You should check 182 | * that this view is non-null and of an appropriate type before 183 | * using. If it is not possible to convert this view to display 184 | * the correct data, this method can create a new view. 185 | * Heterogeneous lists can specify their number of view types, so 186 | * that this View is always of the right type (see 187 | * {@link #getViewTypeCount()} and {@link #getItemViewType(int)} 188 | * ). 189 | * @param parent The parent that this view will eventually be attached to 190 | * @return An instance of RecycleAdapterHelper 191 | */ 192 | protected abstract H getAdapterHelper(int position, View convertView, ViewGroup parent); 193 | } 194 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/ExpandableListViewFragment.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ExpandableListView; 11 | 12 | import com.pacific.example.adapter.ExpandableAdapter; 13 | import com.pacific.example.adapter.ExpandableAdapterHelper; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | 19 | public class ExpandableListViewFragment extends Fragment { 20 | 21 | private ExpandableListView listView; 22 | private ExpandableAdapter adapter; 23 | 24 | public ExpandableListViewFragment() { 25 | } 26 | 27 | public static ExpandableListViewFragment newInstance() { 28 | ExpandableListViewFragment fragment = new ExpandableListViewFragment(); 29 | Bundle args = new Bundle(); 30 | fragment.setArguments(args); 31 | return fragment; 32 | } 33 | 34 | @Override 35 | public void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | 38 | adapter = new ExpandableAdapter(getContext(), R.layout.item, R.layout.item_child) { 39 | @Override 40 | protected List getChildren(int groupPosition) { 41 | return get(groupPosition).getExploreBeanList(); 42 | } 43 | 44 | @Override 45 | protected void convertGroupView(final boolean isExpanded, final ExpandableAdapterHelper helper, MenuBean item) { 46 | helper.setImageResource(R.id.img_explore_icon, item.getIconResId()) 47 | .setText(R.id.tv_explore_name, item.getDescription()) 48 | .getItemView().setOnClickListener(new View.OnClickListener() { 49 | @Override 50 | public void onClick(View v) { 51 | if (isExpanded) { 52 | listView.collapseGroup(helper.getGroupPosition()); 53 | } else { 54 | listView.expandGroup(helper.getGroupPosition()); 55 | } 56 | } 57 | }); 58 | } 59 | 60 | @Override 61 | protected void convertChildView(boolean isLastChild, final ExpandableAdapterHelper helper, ExploreBean item) { 62 | helper.setText(R.id.tv_explore_name, item.getDescription()) 63 | .getItemView().setOnClickListener(new View.OnClickListener() { 64 | @Override 65 | public void onClick(View v) { 66 | clickSnack(helper.getGroupPosition(), helper.getChildPosition()); 67 | } 68 | }); 69 | } 70 | }; 71 | } 72 | 73 | @Override 74 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 75 | return inflater.inflate(R.layout.fragment_expandable_list_view, container, false); 76 | } 77 | 78 | @Override 79 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 80 | super.onViewCreated(view, savedInstanceState); 81 | listView = (ExpandableListView) view.findViewById(R.id.elv_list); 82 | listView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { 83 | @Override 84 | public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) { 85 | return false; 86 | } 87 | }); 88 | listView.setAdapter(adapter); 89 | load(); 90 | } 91 | 92 | public void clickSnack(int g, int c) { 93 | String str = "click group " + String.valueOf(g) + " child " + String.valueOf(c); 94 | Snackbar.make(listView, str, Snackbar.LENGTH_SHORT) 95 | .setAction(R.string.close, new View.OnClickListener() { 96 | @Override 97 | public void onClick(View v) { 98 | } 99 | }).show(); 100 | } 101 | 102 | public void load() { 103 | List list0 = new ArrayList<>(); 104 | 105 | list0.add(new MenuBean(R.drawable.smart_ticket, getString(R.string.smart_ticket))); 106 | list0.add(new MenuBean(R.drawable.auto_lock, getString(R.string.auto_lock))); 107 | list0.add(new MenuBean(R.drawable.check_device, getString(R.string.check_device))); 108 | list0.add(new MenuBean(R.drawable.e_key, getString(R.string.e_key))); 109 | list0.add(new MenuBean(R.drawable.helper, getString(R.string.helper))); 110 | list0.add(new MenuBean(R.drawable.security_monitor, getString(R.string.security_monitor))); 111 | list0.add(new MenuBean(R.drawable.check_state, getString(R.string.check_state))); 112 | list0.add(new MenuBean(R.drawable.work_instruction, getString(R.string.work_instruction))); 113 | list0.add(new MenuBean(R.drawable.web, getString(R.string.web))); 114 | list0.add(new MenuBean(R.drawable.repair_manage, getString(R.string.repair_manage))); 115 | 116 | for (MenuBean menuBean : list0) { 117 | List list = new ArrayList<>(); 118 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 119 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 120 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 121 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 122 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 123 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 124 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 125 | list.add(new ExploreBean(R.drawable.web, "web work", "start:2016.01.01,end: 2016.02.01")); 126 | menuBean.setExploreBeanList(list); 127 | } 128 | 129 | adapter.addAll(list0); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/adapter/BaseExpandableAdapter.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example.adapter; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.BaseExpandableListAdapter; 7 | 8 | import com.pacific.example.adapter.ExpandableAdapterHelper; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | abstract class BaseExpandableAdapter extends BaseExpandableListAdapter implements DataIO { 14 | 15 | protected ArrayList data; 16 | protected Context context; 17 | protected final int groupLayoutResId; 18 | protected final int childLayoutResId; 19 | 20 | /** 21 | * Create a ExpandableAdapter 22 | * 23 | * @param context The context. 24 | * @param groupLayoutResId The layout resource id of each group item. 25 | * @param childLayoutResId The layout resource id of each child item. 26 | */ 27 | public BaseExpandableAdapter(Context context, int groupLayoutResId, int childLayoutResId) { 28 | this(context, groupLayoutResId, childLayoutResId, null); 29 | } 30 | 31 | /** 32 | * Create a ExpandableAdapter 33 | * 34 | * @param context The context. 35 | * @param groupLayoutResId The layout resource id of each group item. 36 | * @param childLayoutResId The layout resource id of each child item. 37 | * @param data A new list is created out of this one to avoid mutable list 38 | */ 39 | public BaseExpandableAdapter(Context context, int groupLayoutResId, int childLayoutResId, List data) { 40 | this.data = data == null ? new ArrayList() : new ArrayList<>(data); 41 | this.context = context; 42 | this.groupLayoutResId = groupLayoutResId; 43 | this.childLayoutResId = childLayoutResId; 44 | } 45 | 46 | @Override 47 | public void add(T elem) { 48 | data.add(elem); 49 | notifyDataSetChanged(); 50 | } 51 | 52 | @Override 53 | public void addAt(int location, T elem) { 54 | data.add(location, elem); 55 | notifyDataSetChanged(); 56 | } 57 | 58 | @Override 59 | public void addAll(List elem) { 60 | data.addAll(elem); 61 | notifyDataSetChanged(); 62 | } 63 | 64 | @Override 65 | public void addAllAt(int location, List elements) { 66 | data.addAll(location, elements); 67 | notifyDataSetChanged(); 68 | } 69 | 70 | @Override 71 | public void remove(T elem) { 72 | data.remove(elem); 73 | notifyDataSetChanged(); 74 | } 75 | 76 | @Override 77 | public void removeAt(int index) { 78 | data.remove(index); 79 | notifyDataSetChanged(); 80 | } 81 | 82 | @Override 83 | public void remove(List list) { 84 | data.removeAll(list); 85 | notifyDataSetChanged(); 86 | } 87 | 88 | @Override 89 | public void clear() { 90 | if (data != null && data.size() > 0) { 91 | data.clear(); 92 | notifyDataSetChanged(); 93 | } 94 | } 95 | 96 | @Override 97 | public void replace(T oldElem, T newElem) { 98 | replaceAt(data.indexOf(oldElem), newElem); 99 | } 100 | 101 | @Override 102 | public void replaceAt(int index, T elem) { 103 | data.set(index, elem); 104 | notifyDataSetChanged(); 105 | } 106 | 107 | @Override 108 | public void replaceAll(List elem) { 109 | if (data.size() > 0) { 110 | data.clear(); 111 | } 112 | data.addAll(elem); 113 | notifyDataSetChanged(); 114 | } 115 | 116 | @Override 117 | public T get(int position) { 118 | if (position >= data.size()) 119 | return null; 120 | return data.get(position); 121 | } 122 | 123 | @Override 124 | public ArrayList getAll() { 125 | return data; 126 | } 127 | 128 | @Override 129 | public int getSize() { 130 | return data.size(); 131 | } 132 | 133 | @Override 134 | public boolean contains(T elem) { 135 | return data.contains(elem); 136 | } 137 | 138 | @Override 139 | public int getGroupCount() { 140 | return getSize(); 141 | } 142 | 143 | @Override 144 | public int getChildrenCount(int groupPosition) { 145 | if (groupPosition < getGroupCount()) { 146 | List children = getChildren(groupPosition); 147 | if (children != null) { 148 | return children.size(); 149 | } else { 150 | return 0; 151 | } 152 | } 153 | return 0; 154 | } 155 | 156 | @Override 157 | public T getGroup(int groupPosition) { 158 | return get(groupPosition); 159 | } 160 | 161 | @Override 162 | public V getChild(int groupPosition, int childPosition) { 163 | if (groupPosition < getGroupCount() && childPosition < getChildrenCount(groupPosition)) { 164 | return getChildren(groupPosition).get(childPosition); 165 | } 166 | return null; 167 | } 168 | 169 | @Override 170 | public long getGroupId(int groupPosition) { 171 | return groupPosition; 172 | } 173 | 174 | @Override 175 | public long getChildId(int groupPosition, int childPosition) { 176 | if (groupPosition < getGroupCount()) { 177 | return childPosition; 178 | } 179 | return -1; 180 | } 181 | 182 | @Override 183 | public boolean hasStableIds() { 184 | return false; 185 | } 186 | 187 | @Override 188 | public boolean isChildSelectable(int groupPosition, int childPosition) { 189 | return true; 190 | } 191 | 192 | @Override 193 | public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { 194 | H help = getAdapterHelper(groupPosition, -1, convertView, parent); 195 | T groupItem = getGroup(groupPosition); 196 | convertGroupView(isExpanded, help, groupItem); 197 | return help.getItemView(); 198 | } 199 | 200 | @Override 201 | public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { 202 | H help = getAdapterHelper(groupPosition, childPosition, convertView, parent); 203 | V childItem = getChild(groupPosition, childPosition); 204 | convertChildView(isLastChild, help, childItem); 205 | return help.getItemView(); 206 | } 207 | 208 | 209 | protected abstract List getChildren(int groupPosition); 210 | 211 | /** 212 | * Implement this method and use the helper to adapt the view to the given 213 | * item. 214 | * 215 | * @param helper A fully initialized helper. 216 | * @param item The item that needs to be displayed. 217 | */ 218 | protected abstract void convertGroupView(boolean isExpanded, H helper, T item); 219 | 220 | protected abstract void convertChildView(boolean isLastChild, H helper, V item); 221 | 222 | /** 223 | * You can override this method to use a custom RecycleAdapterHelper in order 224 | * to fit your needs 225 | * 226 | * @param groupPosition the position of the group for which the View is 227 | * item whose view we want. 228 | * @param childPosition the position of the child (for which the View is 229 | * returned) within the group 230 | * @param convertView the old view to reuse, if possible.You should check 231 | * that this view is non-null and of an appropriate type before 232 | * using. If it is not possible to convert this view to display 233 | * the correct data, this method can create a new view. 234 | * @param parent The parent that this view will eventually be attached to 235 | * @return An instance of RecycleAdapterHelper 236 | */ 237 | protected abstract H getAdapterHelper(int groupPosition, int childPosition, View convertView, ViewGroup parent); 238 | } 239 | -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/FlexibleDecoration.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.content.res.TypedArray; 6 | import android.graphics.Canvas; 7 | import android.graphics.Paint; 8 | import android.graphics.Rect; 9 | import android.graphics.drawable.Drawable; 10 | import android.support.annotation.ColorRes; 11 | import android.support.annotation.DimenRes; 12 | import android.support.annotation.DrawableRes; 13 | import android.support.v4.view.ViewCompat; 14 | import android.support.v7.widget.RecyclerView; 15 | import android.view.View; 16 | 17 | public abstract class FlexibleDecoration extends RecyclerView.ItemDecoration { 18 | 19 | private static final int DEFAULT_SIZE = 2; 20 | private static final int[] ATTRS = new int[]{ 21 | android.R.attr.listDivider 22 | }; 23 | 24 | protected enum DividerType { 25 | DRAWABLE, PAINT, COLOR 26 | } 27 | 28 | protected DividerType mDividerType = DividerType.DRAWABLE; 29 | protected VisibilityProvider mVisibilityProvider; 30 | protected PaintProvider mPaintProvider; 31 | protected ColorProvider mColorProvider; 32 | protected DrawableProvider mDrawableProvider; 33 | protected SizeProvider mSizeProvider; 34 | protected boolean mShowLastDivider; 35 | private Paint mPaint; 36 | 37 | protected FlexibleDecoration(Builder builder) { 38 | if (builder.mPaintProvider != null) { 39 | mDividerType = DividerType.PAINT; 40 | mPaintProvider = builder.mPaintProvider; 41 | } else if (builder.mColorProvider != null) { 42 | mDividerType = DividerType.COLOR; 43 | mColorProvider = builder.mColorProvider; 44 | mPaint = new Paint(); 45 | setSizeProvider(builder); 46 | } else { 47 | mDividerType = DividerType.DRAWABLE; 48 | if (builder.mDrawableProvider == null) { 49 | TypedArray a = builder.mContext.obtainStyledAttributes(ATTRS); 50 | final Drawable divider = a.getDrawable(0); 51 | a.recycle(); 52 | mDrawableProvider = new DrawableProvider() { 53 | @Override 54 | public Drawable drawableProvider(int position, RecyclerView parent) { 55 | return divider; 56 | } 57 | }; 58 | } else { 59 | mDrawableProvider = builder.mDrawableProvider; 60 | } 61 | mSizeProvider = builder.mSizeProvider; 62 | } 63 | 64 | mVisibilityProvider = builder.mVisibilityProvider; 65 | mShowLastDivider = builder.mShowLastDivider; 66 | } 67 | 68 | private void setSizeProvider(Builder builder) { 69 | mSizeProvider = builder.mSizeProvider; 70 | if (mSizeProvider == null) { 71 | mSizeProvider = new SizeProvider() { 72 | @Override 73 | public int dividerSize(int position, RecyclerView parent) { 74 | return DEFAULT_SIZE; 75 | } 76 | }; 77 | } 78 | } 79 | 80 | @Override 81 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { 82 | int lastChildPosition = -1; 83 | int childCount = mShowLastDivider ? parent.getChildCount() : parent.getChildCount() - 1; 84 | for (int i = 0; i < childCount; i++) { 85 | View child = parent.getChildAt(i); 86 | int childPosition = parent.getChildAdapterPosition(child); 87 | 88 | if (childPosition < lastChildPosition) { 89 | // Avoid remaining divider when animation starts 90 | continue; 91 | } 92 | lastChildPosition = childPosition; 93 | 94 | if (ViewCompat.getAlpha(child) < 1) { 95 | // Avoid remaining divider when animation starts 96 | continue; 97 | } 98 | 99 | if (mVisibilityProvider.shouldHideDivider(childPosition, parent)) { 100 | continue; 101 | } 102 | 103 | Rect bounds = getDividerBound(childPosition, parent, child); 104 | switch (mDividerType) { 105 | case DRAWABLE: 106 | Drawable drawable = mDrawableProvider.drawableProvider(childPosition, parent); 107 | drawable.setBounds(bounds); 108 | drawable.draw(c); 109 | break; 110 | case PAINT: 111 | mPaint = mPaintProvider.dividerPaint(childPosition, parent); 112 | c.drawLine(bounds.left, bounds.top, bounds.right, bounds.bottom, mPaint); 113 | break; 114 | case COLOR: 115 | mPaint.setColor(mColorProvider.dividerColor(childPosition, parent)); 116 | mPaint.setStrokeWidth(mSizeProvider.dividerSize(childPosition, parent)); 117 | c.drawLine(bounds.left, bounds.top, bounds.right, bounds.bottom, mPaint); 118 | break; 119 | } 120 | } 121 | } 122 | 123 | @Override 124 | public void getItemOffsets(Rect rect, View v, RecyclerView parent, RecyclerView.State state) { 125 | int position = parent.getChildAdapterPosition(v); 126 | setItemOffsets(rect, position, parent); 127 | } 128 | 129 | protected abstract Rect getDividerBound(int position, RecyclerView parent, View child); 130 | 131 | protected abstract void setItemOffsets(Rect outRect, int position, RecyclerView parent); 132 | 133 | /** 134 | * Interface for controlling divider visibility 135 | */ 136 | public interface VisibilityProvider { 137 | 138 | /** 139 | * Returns true if divider should be hidden. 140 | * 141 | * @param position Divider position 142 | * @param parent RecyclerView 143 | * @return True if the divider at position should be hidden 144 | */ 145 | boolean shouldHideDivider(int position, RecyclerView parent); 146 | } 147 | 148 | /** 149 | * Interface for controlling paint instance for divider drawing 150 | */ 151 | public interface PaintProvider { 152 | 153 | /** 154 | * Returns {@link Paint} for divider 155 | * 156 | * @param position Divider position 157 | * @param parent RecyclerView 158 | * @return Paint instance 159 | */ 160 | Paint dividerPaint(int position, RecyclerView parent); 161 | } 162 | 163 | /** 164 | * Interface for controlling divider color 165 | */ 166 | public interface ColorProvider { 167 | 168 | /** 169 | * Returns {@link android.graphics.Color} value of divider 170 | * 171 | * @param position Divider position 172 | * @param parent RecyclerView 173 | * @return Color value 174 | */ 175 | int dividerColor(int position, RecyclerView parent); 176 | } 177 | 178 | /** 179 | * Interface for controlling drawable object for divider drawing 180 | */ 181 | public interface DrawableProvider { 182 | 183 | /** 184 | * Returns drawable instance for divider 185 | * 186 | * @param position Divider position 187 | * @param parent RecyclerView 188 | * @return Drawable instance 189 | */ 190 | Drawable drawableProvider(int position, RecyclerView parent); 191 | } 192 | 193 | /** 194 | * Interface for controlling divider size 195 | */ 196 | public interface SizeProvider { 197 | 198 | /** 199 | * Returns size value of divider. 200 | * Height for horizontal divider, width for vertical divider 201 | * 202 | * @param position Divider position 203 | * @param parent RecyclerView 204 | * @return Size of divider 205 | */ 206 | int dividerSize(int position, RecyclerView parent); 207 | } 208 | 209 | public static class Builder { 210 | 211 | private Context mContext; 212 | protected Resources mResources; 213 | private PaintProvider mPaintProvider; 214 | private ColorProvider mColorProvider; 215 | private DrawableProvider mDrawableProvider; 216 | private SizeProvider mSizeProvider; 217 | private VisibilityProvider mVisibilityProvider = new VisibilityProvider() { 218 | @Override 219 | public boolean shouldHideDivider(int position, RecyclerView parent) { 220 | return false; 221 | } 222 | }; 223 | private boolean mShowLastDivider = false; 224 | 225 | public Builder(Context context) { 226 | mContext = context; 227 | mResources = context.getResources(); 228 | } 229 | 230 | public T paint(final Paint paint) { 231 | return paintProvider(new PaintProvider() { 232 | @Override 233 | public Paint dividerPaint(int position, RecyclerView parent) { 234 | return paint; 235 | } 236 | }); 237 | } 238 | 239 | public T paintProvider(PaintProvider provider) { 240 | mPaintProvider = provider; 241 | return (T) this; 242 | } 243 | 244 | public T color(final int color) { 245 | return colorProvider(new ColorProvider() { 246 | @Override 247 | public int dividerColor(int position, RecyclerView parent) { 248 | return color; 249 | } 250 | }); 251 | } 252 | 253 | public T colorResId(@ColorRes int colorId) { 254 | return color(mResources.getColor(colorId)); 255 | } 256 | 257 | public T colorProvider(ColorProvider provider) { 258 | mColorProvider = provider; 259 | return (T) this; 260 | } 261 | 262 | public T drawable(@DrawableRes int id) { 263 | return drawable(mResources.getDrawable(id)); 264 | } 265 | 266 | public T drawable(final Drawable drawable) { 267 | return drawableProvider(new DrawableProvider() { 268 | @Override 269 | public Drawable drawableProvider(int position, RecyclerView parent) { 270 | return drawable; 271 | } 272 | }); 273 | } 274 | 275 | public T drawableProvider(DrawableProvider provider) { 276 | mDrawableProvider = provider; 277 | return (T) this; 278 | } 279 | 280 | public T size(final int size) { 281 | return sizeProvider(new SizeProvider() { 282 | @Override 283 | public int dividerSize(int position, RecyclerView parent) { 284 | return size; 285 | } 286 | }); 287 | } 288 | 289 | public T sizeResId(@DimenRes int sizeId) { 290 | return size(mResources.getDimensionPixelSize(sizeId)); 291 | } 292 | 293 | public T sizeProvider(SizeProvider provider) { 294 | mSizeProvider = provider; 295 | return (T) this; 296 | } 297 | 298 | public T visibilityProvider(VisibilityProvider provider) { 299 | mVisibilityProvider = provider; 300 | return (T) this; 301 | } 302 | 303 | public T showLastDivider() { 304 | mShowLastDivider = true; 305 | return (T) this; 306 | } 307 | 308 | protected void checkBuilderParams() { 309 | if (mPaintProvider != null) { 310 | if (mColorProvider != null) { 311 | throw new IllegalArgumentException( 312 | "Use setColor method of Paint class to specify line color. Do not provider ColorProvider if you set PaintProvider."); 313 | } 314 | if (mSizeProvider != null) { 315 | throw new IllegalArgumentException( 316 | "Use setStrokeWidth method of Paint class to specify line size. Do not provider SizeProvider if you set PaintProvider."); 317 | } 318 | } 319 | } 320 | } 321 | } -------------------------------------------------------------------------------- /src/main/java/com/pacific/example/adapter/BaseAdapterHelper.java: -------------------------------------------------------------------------------- 1 | package com.pacific.example.adapter; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Paint; 5 | import android.graphics.Typeface; 6 | import android.graphics.drawable.Drawable; 7 | import android.os.Build; 8 | import android.text.util.Linkify; 9 | import android.util.SparseArray; 10 | import android.view.View; 11 | import android.view.animation.AlphaAnimation; 12 | import android.widget.Adapter; 13 | import android.widget.AdapterView; 14 | import android.widget.Checkable; 15 | import android.widget.ImageView; 16 | import android.widget.ProgressBar; 17 | import android.widget.RatingBar; 18 | import android.widget.TextView; 19 | 20 | import com.bumptech.glide.Glide; 21 | 22 | abstract class BaseAdapterHelper { 23 | protected SparseArray views; 24 | /** 25 | * This method allows you to retrieve a view and perform custom 26 | * operations on it, not covered by the RecycleAdapterHelper.
27 | * If you think it's a common use case, please consider creating 28 | * a new issue at https://github.com/JoanZapata/base-adapter-helper/issues. 29 | * 30 | * @param viewId The id of the view you want to retrieve. 31 | */ 32 | public V getView(int viewId) { 33 | return retrieveView(viewId); 34 | } 35 | 36 | /** 37 | * Will set the text of a TextView. 38 | * 39 | * @param viewId The view id. 40 | * @param value The text to put in the text view. 41 | * @return The RecycleAdapterHelper for chaining. 42 | */ 43 | public T setText(int viewId, String value) { 44 | TextView view = retrieveView(viewId); 45 | view.setText(value); 46 | return (T) this; 47 | } 48 | 49 | /** 50 | * Will set the image of an ImageView from a resource id. 51 | * 52 | * @param viewId The view id. 53 | * @param imageResId The image resource id. 54 | * @return The RecycleAdapterHelper for chaining. 55 | */ 56 | public T setImageResource(int viewId, int imageResId) { 57 | ImageView view = retrieveView(viewId); 58 | view.setImageResource(imageResId); 59 | return (T) this; 60 | } 61 | 62 | /** 63 | * Will set background color of a view. 64 | * 65 | * @param viewId The view id. 66 | * @param color A color, not a resource id. 67 | * @return The RecycleAdapterHelper for chaining. 68 | */ 69 | public T setBackgroundColor(int viewId, int color) { 70 | View view = retrieveView(viewId); 71 | view.setBackgroundColor(color); 72 | return (T) this; 73 | } 74 | 75 | /** 76 | * Will set background of a view. 77 | * 78 | * @param viewId The view id. 79 | * @param backgroundRes A resource to use as a background. 80 | * @return The RecycleAdapterHelper for chaining. 81 | */ 82 | public T setBackgroundRes(int viewId, int backgroundRes) { 83 | View view = retrieveView(viewId); 84 | view.setBackgroundResource(backgroundRes); 85 | return (T) this; 86 | } 87 | 88 | /** 89 | * Will set text color of a TextView. 90 | * 91 | * @param viewId The view id. 92 | * @param textColor The text color (not a resource id). 93 | * @return The RecycleAdapterHelper for chaining. 94 | */ 95 | public T setTextColor(int viewId, int textColor) { 96 | TextView view = retrieveView(viewId); 97 | view.setTextColor(textColor); 98 | return (T) this; 99 | } 100 | 101 | /** 102 | * Will set text color of a TextView. 103 | * 104 | * @param viewId The view id. 105 | * @param textColorRes The text color resource id. 106 | * @return The RecycleAdapterHelper for chaining. 107 | */ 108 | public T setTextColorRes(int viewId, int textColorRes) { 109 | TextView view = retrieveView(viewId); 110 | view.setTextColor(getItemView().getContext().getResources().getColor(textColorRes)); 111 | return (T) this; 112 | } 113 | 114 | /** 115 | * Will set the image of an ImageView from a drawable. 116 | * 117 | * @param viewId The view id. 118 | * @param drawable The image drawable. 119 | * @return The RecycleAdapterHelper for chaining. 120 | */ 121 | public T setImageDrawable(int viewId, Drawable drawable) { 122 | ImageView view = retrieveView(viewId); 123 | view.setImageDrawable(drawable); 124 | return (T) this; 125 | } 126 | 127 | /** 128 | * Will download an image from a URL and put it in an ImageView.
129 | * It uses Square's Picasso library to download the image asynchronously and put the result into the ImageView.
130 | * Picasso manages recycling of views in a ListView.
131 | * If you need more control over the Picasso settings, use {RecycleAdapterHelper#setImageBuilder}. 132 | * 133 | * @param viewId The view id. 134 | * @param imageUrl The image URL. 135 | * @return The RecycleAdapterHelper for chaining. 136 | */ 137 | public T setImageUrl(int viewId, String imageUrl) { 138 | ImageView view = retrieveView(viewId); 139 | Glide.with(view.getContext()).load(imageUrl).into(view); 140 | return (T) this; 141 | } 142 | 143 | /** 144 | * Add an action to set the image of an image view. Can be called multiple times. 145 | */ 146 | public T setImageBitmap(int viewId, Bitmap bitmap) { 147 | ImageView view = retrieveView(viewId); 148 | view.setImageBitmap(bitmap); 149 | return (T) this; 150 | } 151 | 152 | /** 153 | * Add an action to set the alpha of a view. Can be called multiple times. 154 | * Alpha between 0-1. 155 | */ 156 | public T setAlpha(int viewId, float value) { 157 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 158 | retrieveView(viewId).setAlpha(value); 159 | } else { 160 | // Pre-honeycomb hack to set Alpha value 161 | AlphaAnimation alpha = new AlphaAnimation(value, value); 162 | alpha.setDuration(0); 163 | alpha.setFillAfter(true); 164 | retrieveView(viewId).startAnimation(alpha); 165 | } 166 | return (T) this; 167 | } 168 | 169 | /** 170 | * Set a view visibility to VISIBLE (true) or GONE (false). 171 | * 172 | * @param viewId The view id. 173 | * @param visible True for VISIBLE, false for GONE. 174 | * @return The RecycleAdapterHelper for chaining. 175 | */ 176 | public T setVisible(int viewId, boolean visible) { 177 | View view = retrieveView(viewId); 178 | view.setVisibility(visible ? View.VISIBLE : View.GONE); 179 | return (T) this; 180 | } 181 | 182 | /** 183 | * Add links into a TextView. 184 | * 185 | * @param viewId The id of the TextView to linkify. 186 | * @return The RecycleAdapterHelper for chaining. 187 | */ 188 | public T linkify(int viewId) { 189 | TextView view = retrieveView(viewId); 190 | Linkify.addLinks(view, Linkify.ALL); 191 | return (T) this; 192 | } 193 | 194 | /** 195 | * Apply the typeface to the given viewId, and enable subpixel rendering. 196 | */ 197 | public T setTypeface(int viewId, Typeface typeface) { 198 | TextView view = retrieveView(viewId); 199 | view.setTypeface(typeface); 200 | view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG); 201 | return (T) this; 202 | } 203 | 204 | /** 205 | * Apply the typeface to all the given viewIds, and enable subpixel rendering. 206 | */ 207 | public T setTypeface(Typeface typeface, int... viewIds) { 208 | for (int viewId : viewIds) { 209 | TextView view = retrieveView(viewId); 210 | view.setTypeface(typeface); 211 | view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG); 212 | } 213 | return (T) this; 214 | } 215 | 216 | /** 217 | * Sets the progress of a ProgressBar. 218 | * 219 | * @param viewId The view id. 220 | * @param progress The progress. 221 | * @return The RecycleAdapterHelper for chaining. 222 | */ 223 | public T setProgress(int viewId, int progress) { 224 | ProgressBar view = retrieveView(viewId); 225 | view.setProgress(progress); 226 | return (T) this; 227 | } 228 | 229 | /** 230 | * Sets the progress and max of a ProgressBar. 231 | * 232 | * @param viewId The view id. 233 | * @param progress The progress. 234 | * @param max The max value of a ProgressBar. 235 | * @return The RecycleAdapterHelper for chaining. 236 | */ 237 | public T setProgress(int viewId, int progress, int max) { 238 | ProgressBar view = retrieveView(viewId); 239 | view.setMax(max); 240 | view.setProgress(progress); 241 | return (T) this; 242 | } 243 | 244 | /** 245 | * Sets the range of a ProgressBar to 0...max. 246 | * 247 | * @param viewId The view id. 248 | * @param max The max value of a ProgressBar. 249 | * @return The RecycleAdapterHelper for chaining. 250 | */ 251 | public T setMax(int viewId, int max) { 252 | ProgressBar view = retrieveView(viewId); 253 | view.setMax(max); 254 | return (T) this; 255 | } 256 | 257 | /** 258 | * Sets the rating (the number of stars filled) of a RatingBar. 259 | * 260 | * @param viewId The view id. 261 | * @param rating The rating. 262 | * @return The RecycleAdapterHelper for chaining. 263 | */ 264 | public T setRating(int viewId, float rating) { 265 | RatingBar view = retrieveView(viewId); 266 | view.setRating(rating); 267 | return (T) this; 268 | } 269 | 270 | /** 271 | * Sets the rating (the number of stars filled) and max of a RatingBar. 272 | * 273 | * @param viewId The view id. 274 | * @param rating The rating. 275 | * @param max The range of the RatingBar to 0...max. 276 | * @return The RecycleAdapterHelper for chaining. 277 | */ 278 | public T setRating(int viewId, float rating, int max) { 279 | RatingBar view = retrieveView(viewId); 280 | view.setMax(max); 281 | view.setRating(rating); 282 | return (T) this; 283 | } 284 | 285 | /** 286 | * Sets the on click listener of the view. 287 | * 288 | * @param viewId The view id. 289 | * @param listener The on click listener; 290 | * @return The RecycleAdapterHelper for chaining. 291 | */ 292 | public T setOnClickListener(int viewId, View.OnClickListener listener) { 293 | View view = retrieveView(viewId); 294 | view.setOnClickListener(listener); 295 | return (T) this; 296 | } 297 | 298 | /** 299 | * Sets the on touch listener of the view. 300 | * 301 | * @param viewId The view id. 302 | * @param listener The on touch listener; 303 | * @return The RecycleAdapterHelper for chaining. 304 | */ 305 | public T setOnTouchListener(int viewId, View.OnTouchListener listener) { 306 | View view = retrieveView(viewId); 307 | view.setOnTouchListener(listener); 308 | return (T) this; 309 | } 310 | 311 | /** 312 | * Sets the on long click listener of the view. 313 | * 314 | * @param viewId The view id. 315 | * @param listener The on long click listener; 316 | * @return The RecycleAdapterHelper for chaining. 317 | */ 318 | public T setOnLongClickListener(int viewId, View.OnLongClickListener listener) { 319 | View view = retrieveView(viewId); 320 | view.setOnLongClickListener(listener); 321 | return (T) this; 322 | } 323 | 324 | /** 325 | * Sets the tag of the view. 326 | * 327 | * @param viewId The view id. 328 | * @param tag The tag; 329 | * @return The RecycleAdapterHelper for chaining. 330 | */ 331 | public T setTag(int viewId, Object tag) { 332 | View view = retrieveView(viewId); 333 | view.setTag(tag); 334 | return (T) this; 335 | } 336 | 337 | /** 338 | * Sets the tag of the view. 339 | * 340 | * @param viewId The view id. 341 | * @param key The key of tag; 342 | * @param tag The tag; 343 | * @return The RecycleAdapterHelper for chaining. 344 | */ 345 | public T setTag(int viewId, int key, Object tag) { 346 | View view = retrieveView(viewId); 347 | view.setTag(key, tag); 348 | return (T) this; 349 | } 350 | 351 | /** 352 | * Sets the checked status of a checkable. 353 | * 354 | * @param viewId The view id. 355 | * @param checked The checked status; 356 | * @return The RecycleAdapterHelper for chaining. 357 | */ 358 | public T setChecked(int viewId, boolean checked) { 359 | Checkable view = (Checkable) retrieveView(viewId); 360 | view.setChecked(checked); 361 | return (T) this; 362 | } 363 | 364 | /** 365 | * Sets the adapter of a adapter view. 366 | * 367 | * @param viewId The view id. 368 | * @param adapter The adapter; 369 | * @return The RecycleAdapterHelper for chaining. 370 | */ 371 | public T setAdapter(int viewId, Adapter adapter) { 372 | AdapterView view = retrieveView(viewId); 373 | view.setAdapter(adapter); 374 | return (T) this; 375 | } 376 | 377 | 378 | private V retrieveView(int viewId) { 379 | View view = views.get(viewId); 380 | if (view == null) { 381 | view = getItemView().findViewById(viewId); 382 | views.put(viewId, view); 383 | } 384 | return (V) view; 385 | } 386 | 387 | /** 388 | * Retrieve the itemView 389 | */ 390 | public abstract View getItemView(); 391 | } 392 | --------------------------------------------------------------------------------