├── .gitignore ├── README-zh-rCN.md ├── README.md ├── build.gradle ├── demo ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── org │ │ └── byteam │ │ └── superadapter │ │ └── demo │ │ ├── MainActivity.java │ │ ├── adapter │ │ ├── MultipleAdapter.java │ │ └── SingleAdapter.java │ │ ├── fragment │ │ ├── ListViewFragment.java │ │ └── RecyclerViewFragment.java │ │ └── model │ │ ├── DataUtils.java │ │ └── MockModel.java │ └── res │ ├── layout │ ├── activity_main.xml │ ├── fragment_listview.xml │ ├── fragment_recyclerview.xml │ ├── item_type1.xml │ └── item_type2.xml │ ├── menu │ └── menu_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-v21 │ └── styles.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── img └── qq_qun.png ├── settings.gradle └── superadapter ├── bintray.gradle ├── build.gradle ├── proguard-rules.pro └── src └── main ├── AndroidManifest.xml └── java └── org └── byteam └── superadapter ├── CRUD.java ├── ChainSetter.java ├── DefaultDiffCallback.java ├── ExtendViewHolder.java ├── IAnimation.java ├── IHeaderFooter.java ├── ILayoutManager.java ├── IMulItemViewType.java ├── IViewBindData.java ├── ListSupportAdapter.java ├── OnItemClickListener.java ├── OnItemLongClickListener.java ├── RecyclerSupportAdapter.java ├── SimpleMulItemViewType.java ├── SuperAdapter.java ├── SuperViewHolder.java └── animation ├── AlphaInAnimation.java ├── BaseAnimation.java ├── ScaleInAnimation.java ├── SlideInBottomAnimation.java ├── SlideInLeftAnimation.java └── SlideInRightAnimation.java /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .gradle 3 | local.properties 4 | .idea 5 | build 6 | *.iml -------------------------------------------------------------------------------- /README-zh-rCN.md: -------------------------------------------------------------------------------- 1 | ![Version](https://api.bintray.com/packages/chenenyu/maven/SuperAdapter/images/download.svg)![API](https://img.shields.io/badge/API-9%2B-orange.svg)![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-SuperAdapter-brightgreen.svg?style=flat) 2 | 3 | QQ群:271849001(新) 4 | 5 | ![QQ群二维码](img/qq_qun.png) 6 | # SuperAdapter 7 | *一个封装了BaseAdapter和RecyclerView.Adapter的简洁的Adapter。* 8 | 9 | **旨在减少Adapter冗余的代码。** 你不必再写ViewHolder以及其他必须覆写的方法,只需要实现`onBind()`方法就够了。 10 | 11 | ## Android Studio: 12 | 13 | 在module的build.gradle中: 14 | 15 | `compile 'org.byteam.superadapter:superadapter:最新版本号'` 16 | 17 | 当前最新版本号为:![Version](https://api.bintray.com/packages/chenenyu/maven/SuperAdapter/images/download.svg) 18 | 19 | ## Eclipse: 20 | 可以手动添加最新的[jar包](https://github.com/chenenyu/SuperAdapter/releases)到libs文件夹下,建议尽早迁移到Android Studio开发。 21 | ## 特性 22 | * 减少大量代码*3! 23 | * 支持Header和footer。 24 | * 支持item的点击事件。 25 | * 隐藏ViewHolder相关代码。 26 | * 一个SuperAdapter同时支持`BaseAdapter`和`RecyclerView.Adapter`。 27 | * 封装Adapter数据源变动操作。 28 | 29 | ## 如何使用 30 | 31 | 如果是个单布局的Adapter,可以简写为如下示例代码: 32 | 33 | ``` 34 | public class SingleAdapter extends SuperAdapter { 35 | public SingleAdapter(Context context, List list, int layoutResId) { 36 | super(context, list, layoutResId); 37 | } 38 | 39 | @Override 40 | public void onBind(SuperViewHolder holder, int viewType, int position, String item) { 41 | holder.setText(R.id.tv_name, item); 42 | } 43 | } 44 | ``` 45 | 46 | 然后在Activity(or Fragment)中调用: 47 | 48 | ``` 49 | mSingleAdapter = new RecyclerSingleAdapter(getContext(), names, R.layout.your_item); 50 | recyclerView.setAdapter(mSingleAdapter); 51 | ``` 52 | 如果是个多布局的Adapter,可以简写为如下示例代码: 53 | 54 | ``` 55 | public class MultipleAdapter extends SuperAdapter { 56 | public MultipleAdapter(Context context, List list, IMulItemViewType multiItemViewType) { 57 | super(context, list, multiItemViewType); 58 | } 59 | 60 | @Override 61 | public void onBind(SuperViewHolder holder, int viewType, int position, MockModel item) { 62 | switch (viewType) { 63 | case 0: 64 | holder.setText(R.id.tv_name, item.getName()); 65 | break; 66 | case 1: 67 | holder.setText(R.id.tv_name, item.getName()); 68 | holder.setImageResource(R.id.iv_portrait, R.mipmap.ic_launcher); 69 | holder.setText(R.id.tv_age, String.valueOf(item.getAge())); 70 | break; 71 | } 72 | } 73 | } 74 | ``` 75 | 76 | 然后调用(注意构造方法的参数与单布局的区别): 77 | 78 | ``` 79 | multiAdapter = new MultipleAdapter(getContext(), models, new IMulItemViewType() { 80 | @Override 81 | public int getItemViewType(int position, MockModel mockModel) { 82 | if (position % 2 == 0) { 83 | return 0; 84 | } 85 | return 1; 86 | } 87 | 88 | @Override 89 | public int getLayoutId(int viewType) { 90 | if (viewType == 0) { 91 | return R.layout.item_type1; 92 | } 93 | return R.layout.item_type2; 94 | } 95 | 96 | @Override 97 | public int getViewTypeCount() { 98 | return 2; 99 | } 100 | }); 101 | recyclerView.setAdapter(mMultiAdapter); 102 | ``` 103 | 104 | 如果不想在创建Adapter时提供IMulItemViewType接口,也可以在Adapter中重写`offerMultiItemViewType()`方法: 105 | 106 | ``` 107 | @Override 108 | protected IMulItemViewType offerMultiItemViewType() { 109 | return new IMulItemViewType() { 110 | @Override 111 | public int getViewTypeCount() { 112 | return 2; 113 | } 114 | 115 | @Override 116 | public int getItemViewType(int position, MockModel mockModel) { 117 | if (position % 2 == 0) { 118 | return 0; 119 | } 120 | return 1; 121 | } 122 | 123 | @Override 124 | public int getLayoutId(int viewType) { 125 | if (viewType == 0) { 126 | return R.layout.item_type1; 127 | } 128 | return R.layout.item_type2; 129 | } 130 | }; 131 | } 132 | ``` 133 | 134 | 然后在创建Adapter时提供`null`: 135 | `multiAdapter = new MultipleAdapter(getContext(), models, null);` 136 | 137 | 如果使用的是RecyclerView,在使用多布局时,还可以使用`SimpleMulItemViewType`类,因为`getViewTypeCount()`方法仅在使用ListView、GridView等控件时是必须的: 138 | 139 | ``` 140 | mAdapter = new MultipleAdapter(getContext(), models, new SimpleMulItemViewType() { 141 | @Override 142 | public int getItemViewType(int position, MockModel mockModel) { 143 | if (position % 2 == 0) { 144 | return 0; 145 | } 146 | return 1; 147 | } 148 | 149 | @Override 150 | public int getLayoutId(int viewType) { 151 | if (viewType == 0) { 152 | return R.layout.item_type1; 153 | } 154 | return R.layout.item_type2; 155 | } 156 | }); 157 | recyclerView.setAdapter(mAdapter); 158 | ``` 159 | 160 | 161 | **欢迎提交代码、bug以及讨论 : )** 162 | 163 | ## License 164 | 165 | ``` 166 | Copyright 2016-2018 byteam.org. 167 | 168 | Licensed under the Apache License, Version 2.0 (the "License"); 169 | you may not use this file except in compliance with the License. 170 | You may obtain a copy of the License at 171 | 172 | http://www.apache.org/licenses/LICENSE-2.0 173 | 174 | Unless required by applicable law or agreed to in writing, software 175 | distributed under the License is distributed on an "AS IS" BASIS, 176 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 177 | See the License for the specific language governing permissions and 178 | limitations under the License. 179 | ``` 180 | 181 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Version](https://api.bintray.com/packages/chenenyu/maven/SuperAdapter/images/download.svg) ![API](https://img.shields.io/badge/API-9%2B-orange.svg) ![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-SuperAdapter-brightgreen.svg?style=flat) 2 | 3 | ### [Chinese Version 中文版](http://www.jianshu.com/p/d6a76fd3ea5b) 4 | QQ群:271849001(新) 5 | 6 | ![QQ群二维码](img/qq_qun.png) 7 | # SuperAdapter 8 | *Adapter(ListAdapter, RecyclerView.Adapter) wrapper for android.* 9 | 10 | **Less code for redundant adapter.** You won't need to write ViewHolder, createView, setTag, getTag, and confuse how to setOnItemClickListener to RecyclerView, etc. The only thing you really need to do is that implement a method `onBind()`. 11 | 12 | ## Android Studio: 13 | 14 | In build.gradle: 15 | 16 | ````groovy 17 | compile 'com.android.support:recyclerview-v7:...' 18 | ... 19 | compile 'org.byteam.superadapter:superadapter:x.y.z' 20 | ```` 21 | 22 | Current latest version: ![Version](https://api.bintray.com/packages/chenenyu/maven/SuperAdapter/images/download.svg) 23 | 24 | ## Eclipse: 25 | Add [latest Jar](https://github.com/byteam/SuperAdapter/releases) to libs dir manually. 26 | 27 | ## Features 28 | * Less code! 29 | * Header and footer. 30 | * OnItemClickListener and OnItemLongClickListener. 31 | * Hide view holder. 32 | * Supports both `BaseAdapter` and `RecyclerView.Adapter`. 33 | * Wraps CRUD. 34 | * Loading animation supporting! 35 | 36 | ## How to use 37 | 38 | ### Simple adapter 39 | 40 | ``` 41 | public class SingleAdapter extends SuperAdapter { 42 | public SingleAdapter(Context context, List list, int layoutResId) { 43 | super(context, list, layoutResId); 44 | } 45 | 46 | @Override 47 | public void onBind(SuperViewHolder holder, int viewType, int position, String item) { 48 | holder.setText(R.id.tv_name, item); 49 | } 50 | } 51 | ``` 52 | 53 | Then: 54 | 55 | ``` 56 | mSingleAdapter = new RecyclerSingleAdapter(getContext(), names, R.layout.your_item); 57 | recyclerView.setAdapter(mSingleAdapter); 58 | ``` 59 | ### Multiple item types adapter 60 | 61 | ``` 62 | public class MultipleAdapter extends SuperAdapter { 63 | public MultipleAdapter(Context context, List list, IMulItemViewType multiItemViewType) { 64 | super(context, list, multiItemViewType); 65 | } 66 | 67 | @Override 68 | public void onBind(SuperViewHolder holder, int viewType, int position, MockModel item) { 69 | switch (viewType) { 70 | case 0: 71 | holder.setText(R.id.tv_name, item.getName()); 72 | break; 73 | case 1: 74 | holder.setText(R.id.tv_name, item.getName()); 75 | holder.setImageResource(R.id.iv_portrait, R.mipmap.ic_launcher); 76 | holder.setText(R.id.tv_age, String.valueOf(item.getAge())); 77 | break; 78 | } 79 | } 80 | } 81 | ``` 82 | 83 | Then: 84 | 85 | ``` 86 | multiAdapter = new MultipleAdapter(getContext(), models, new IMulItemViewType() { 87 | @Override 88 | public int getItemViewType(int position, MockModel mockModel) { 89 | if (position % 2 == 0) { 90 | return 0; 91 | } 92 | return 1; 93 | } 94 | 95 | @Override 96 | public int getLayoutId(int viewType) { 97 | if (viewType == 0) { 98 | return R.layout.item_type1; 99 | } 100 | return R.layout.item_type2; 101 | } 102 | 103 | @Override 104 | public int getViewTypeCount() { 105 | return 2; 106 | } 107 | }); 108 | recyclerView.setAdapter(mMultiAdapter); 109 | ``` 110 | 111 | If you don't want to offer `IMulItemViewType` when creating adapter, you can override `offerMultiItemViewType()` in adapter: 112 | 113 | ``` 114 | @Override 115 | protected IMulItemViewType offerMultiItemViewType() { 116 | return new IMulItemViewType() { 117 | @Override 118 | public int getViewTypeCount() { 119 | return 2; 120 | } 121 | 122 | @Override 123 | public int getItemViewType(int position, MockModel mockModel) { 124 | if (position % 2 == 0) { 125 | return 0; 126 | } 127 | return 1; 128 | } 129 | 130 | @Override 131 | public int getLayoutId(int viewType) { 132 | if (viewType == 0) { 133 | return R.layout.item_type1; 134 | } 135 | return R.layout.item_type2; 136 | } 137 | }; 138 | } 139 | ``` 140 | 141 | Then: 142 | `multiAdapter = new MultipleAdapter(getContext(), models, null);` 143 | If using `RecyclerView`, you can also use class `SimpleMulItemViewType`: 144 | 145 | ``` 146 | mAdapter = new MultipleAdapter(getContext(), models, new SimpleMulItemViewType() { 147 | @Override 148 | public int getItemViewType(int position, MockModel mockModel) { 149 | if (position % 2 == 0) { 150 | return 0; 151 | } 152 | return 1; 153 | } 154 | 155 | @Override 156 | public int getLayoutId(int viewType) { 157 | if (viewType == 0) { 158 | return R.layout.item_type1; 159 | } 160 | return R.layout.item_type2; 161 | } 162 | }); 163 | recyclerView.setAdapter(mAdapter); 164 | ``` 165 | 166 | ### Load animation: 167 | Open default animation: 168 | `adapter.enableLoadAnimation();` 169 | or 170 | `adapter.enableLoadAnimation(long duration, new SlideInBottomAnimation());` 171 | if you want to show animation when item shows each time: 172 | `adapter.setOnlyOnce(false);` 173 | Note that you can set custom animation by implementing **[BaseAnimation](superadapter/src/main/java/org/byteam/superadapter/animation/BaseAnimation.java)**. 174 | 175 | 176 | **Welcome to submit PRs and open issues! : )** 177 | 178 | ## License 179 | 180 | ``` 181 | Copyright 2016-2018 byteam.org. 182 | 183 | Licensed under the Apache License, Version 2.0 (the "License"); 184 | you may not use this file except in compliance with the License. 185 | You may obtain a copy of the License at 186 | 187 | http://www.apache.org/licenses/LICENSE-2.0 188 | 189 | Unless required by applicable law or agreed to in writing, software 190 | distributed under the License is distributed on an "AS IS" BASIS, 191 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 192 | See the License for the specific language governing permissions and 193 | limitations under the License. 194 | ``` 195 | 196 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | google() 6 | jcenter() 7 | } 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.0.0' 10 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' 11 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.0' 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | } 20 | } 21 | 22 | task clean(type: Delete) { 23 | delete rootProject.buildDir 24 | } 25 | -------------------------------------------------------------------------------- /demo/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | buildToolsVersion '26.0.3' 6 | 7 | defaultConfig { 8 | applicationId "org.byteam.superadapter.demo" 9 | minSdkVersion 14 10 | targetSdkVersion 26 11 | versionCode 1 12 | versionName "1.0.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(dir: 'libs', include: ['*.jar']) 24 | implementation project(':superadapter') 25 | implementation 'com.android.support:appcompat-v7:26.1.0' 26 | implementation 'com.android.support:design:26.1.0' 27 | implementation 'com.android.support:recyclerview-v7:26.1.0' 28 | } 29 | -------------------------------------------------------------------------------- /demo/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/Cheney/workspace/AndroidSDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /demo/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /demo/src/main/java/org/byteam/superadapter/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package org.byteam.superadapter.demo; 2 | 3 | import android.os.Bundle; 4 | import android.support.design.widget.FloatingActionButton; 5 | import android.support.design.widget.Snackbar; 6 | import android.support.design.widget.TabLayout; 7 | import android.support.v4.app.Fragment; 8 | import android.support.v4.app.FragmentManager; 9 | import android.support.v4.app.FragmentPagerAdapter; 10 | import android.support.v4.view.ViewPager; 11 | import android.support.v7.app.AppCompatActivity; 12 | import android.support.v7.widget.Toolbar; 13 | import android.view.View; 14 | 15 | import org.byteam.superadapter.demo.fragment.ListViewFragment; 16 | import org.byteam.superadapter.demo.fragment.RecyclerViewFragment; 17 | 18 | public class MainActivity extends AppCompatActivity { 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_main); 24 | 25 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 26 | setSupportActionBar(toolbar); 27 | 28 | SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); 29 | 30 | ViewPager mViewPager = (ViewPager) findViewById(R.id.container); 31 | mViewPager.setAdapter(mSectionsPagerAdapter); 32 | 33 | TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); 34 | tabLayout.setupWithViewPager(mViewPager); 35 | 36 | FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 37 | fab.setOnClickListener(new View.OnClickListener() { 38 | @Override 39 | public void onClick(View view) { 40 | Snackbar.make(view, "https://github.com/byteam/SuperAdapter", 41 | Snackbar.LENGTH_LONG) 42 | .setAction("Action", null).show(); 43 | } 44 | }); 45 | 46 | } 47 | 48 | /** 49 | * A {@link FragmentPagerAdapter} that returns a fragment corresponding to 50 | * one of the sections/tabs/pages. 51 | */ 52 | public class SectionsPagerAdapter extends FragmentPagerAdapter { 53 | 54 | public SectionsPagerAdapter(FragmentManager fm) { 55 | super(fm); 56 | } 57 | 58 | @Override 59 | public Fragment getItem(int position) { 60 | Fragment fragment = null; 61 | switch (position) { 62 | case 0: 63 | fragment = ListViewFragment.newInstance(1); 64 | break; 65 | case 1: 66 | fragment = ListViewFragment.newInstance(2); 67 | break; 68 | case 2: 69 | fragment = RecyclerViewFragment.newInstance(1); 70 | break; 71 | case 3: 72 | fragment = RecyclerViewFragment.newInstance(2); 73 | break; 74 | } 75 | return fragment; 76 | } 77 | 78 | @Override 79 | public int getCount() { 80 | return 4; 81 | } 82 | 83 | @Override 84 | public CharSequence getPageTitle(int position) { 85 | switch (position) { 86 | case 0: 87 | return "ListView(Single)"; 88 | case 1: 89 | return "ListView(Multi)"; 90 | case 2: 91 | return "RecyclerView(Single)"; 92 | case 3: 93 | return "RecyclerView(Multi)"; 94 | } 95 | return null; 96 | } 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /demo/src/main/java/org/byteam/superadapter/demo/adapter/MultipleAdapter.java: -------------------------------------------------------------------------------- 1 | package org.byteam.superadapter.demo.adapter; 2 | 3 | import android.content.Context; 4 | 5 | import org.byteam.superadapter.IMulItemViewType; 6 | import org.byteam.superadapter.SuperAdapter; 7 | import org.byteam.superadapter.SuperViewHolder; 8 | import org.byteam.superadapter.demo.R; 9 | import org.byteam.superadapter.demo.model.MockModel; 10 | 11 | import java.util.List; 12 | 13 | public class MultipleAdapter extends SuperAdapter { 14 | public MultipleAdapter(Context context, List list, IMulItemViewType multiItemViewType) { 15 | super(context, list, multiItemViewType); 16 | // enableLoadAnimation(500, new SlideInBottomAnimation()); 17 | } 18 | 19 | @Override 20 | public void onBind(SuperViewHolder holder, int viewType, int layoutPosition, MockModel item) { 21 | switch (viewType) { 22 | case 0: 23 | holder.setText(R.id.tv_name, item.getName()); 24 | break; 25 | case 1: 26 | holder.setText(R.id.tv_name, item.getName()); 27 | holder.setImageResource(R.id.iv_portrait, R.mipmap.ic_launcher); 28 | holder.setText(R.id.tv_age, String.valueOf(item.getAge())); 29 | break; 30 | } 31 | } 32 | 33 | @Override 34 | protected IMulItemViewType offerMultiItemViewType() { 35 | return new IMulItemViewType() { 36 | @Override 37 | public int getViewTypeCount() { 38 | return 2; 39 | } 40 | 41 | @Override 42 | public int getItemViewType(int position, MockModel mockModel) { 43 | if (position % 2 == 0) { 44 | return 0; 45 | } 46 | return 1; 47 | } 48 | 49 | @Override 50 | public int getLayoutId(int viewType) { 51 | if (viewType == 0) { 52 | return R.layout.item_type1; 53 | } 54 | return R.layout.item_type2; 55 | } 56 | }; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /demo/src/main/java/org/byteam/superadapter/demo/adapter/SingleAdapter.java: -------------------------------------------------------------------------------- 1 | package org.byteam.superadapter.demo.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.LayoutRes; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | import android.widget.Toast; 10 | 11 | import org.byteam.superadapter.SuperAdapter; 12 | import org.byteam.superadapter.SuperViewHolder; 13 | import org.byteam.superadapter.demo.R; 14 | 15 | import java.util.List; 16 | 17 | public class SingleAdapter extends SuperAdapter { 18 | public SingleAdapter(Context context, List list, @LayoutRes int layoutResId) { 19 | super(context, list, layoutResId); 20 | // enableLoadAnimation(500, new AlphaInAnimation()); 21 | // setOnlyOnce(false); 22 | } 23 | 24 | @Override 25 | public SuperViewHolder onCreate(View convertView, ViewGroup parent, int viewType) { 26 | // These code show how to add click listener to item view of ViewHolder. 27 | final SuperViewHolder holder = super.onCreate(convertView, parent, viewType); 28 | holder.itemView.setOnClickListener(new View.OnClickListener() { 29 | @Override 30 | public void onClick(View v) { 31 | Log.d("onClick", "" + holder.getAdapterPosition()); 32 | } 33 | }); 34 | holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { 35 | @Override 36 | public boolean onLongClick(View v) { 37 | Toast.makeText(getContext(), ((TextView) (holder.findViewById(R.id.tv_name))).getText(), Toast.LENGTH_SHORT).show(); 38 | return true; 39 | } 40 | }); 41 | return holder; 42 | } 43 | 44 | @Override 45 | public void onBind(final SuperViewHolder holder, int viewType, final int layoutPosition, String item) { 46 | holder.setText(R.id.tv_name, item); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /demo/src/main/java/org/byteam/superadapter/demo/fragment/ListViewFragment.java: -------------------------------------------------------------------------------- 1 | package org.byteam.superadapter.demo.fragment; 2 | 3 | import android.graphics.Color; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.Menu; 9 | import android.view.MenuInflater; 10 | import android.view.MenuItem; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.ListView; 14 | import android.widget.TextView; 15 | import android.widget.Toast; 16 | 17 | import org.byteam.superadapter.SuperAdapter; 18 | import org.byteam.superadapter.demo.R; 19 | import org.byteam.superadapter.demo.adapter.MultipleAdapter; 20 | import org.byteam.superadapter.demo.adapter.SingleAdapter; 21 | import org.byteam.superadapter.demo.model.DataUtils; 22 | 23 | import java.util.ArrayList; 24 | import java.util.Arrays; 25 | import java.util.List; 26 | 27 | /** 28 | * Fragment contains ListView. 29 | * Created by Cheney on 15/12/19. 30 | */ 31 | public class ListViewFragment extends Fragment { 32 | private static final String TYPE = "type"; 33 | private int mType; 34 | 35 | private TextView header, footer; 36 | private ListView mListView; 37 | private SuperAdapter mAdapter; 38 | private List mData; 39 | 40 | public static ListViewFragment newInstance(int type) { 41 | ListViewFragment fragment = new ListViewFragment(); 42 | Bundle bundle = new Bundle(); 43 | bundle.putInt(TYPE, type); 44 | fragment.setArguments(bundle); 45 | return fragment; 46 | } 47 | 48 | @Override 49 | public void onCreate(Bundle savedInstanceState) { 50 | super.onCreate(savedInstanceState); 51 | if (getArguments() != null) { 52 | mType = getArguments().getInt(TYPE, 1); 53 | if (mType == 1) { 54 | setHasOptionsMenu(true); 55 | } 56 | } 57 | } 58 | 59 | @Override 60 | public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 61 | inflater.inflate(R.menu.menu_main, menu); 62 | } 63 | 64 | @Override 65 | public boolean onOptionsItemSelected(MenuItem item) { 66 | int id = item.getItemId(); 67 | switch (id) { 68 | case R.id.action_add_header: 69 | if (!mAdapter.hasHeaderView()) { 70 | mAdapter.addHeaderView(header); 71 | mListView.scrollTo(0, 0); 72 | } 73 | return true; 74 | case R.id.action_remove_header: 75 | if (mAdapter.hasHeaderView()) 76 | mAdapter.removeHeaderView(); 77 | return true; 78 | case R.id.action_add_footer: 79 | if (!mAdapter.hasFooterView()) 80 | mAdapter.addFooterView(footer); 81 | return true; 82 | case R.id.action_remove_footer: 83 | if (mAdapter.hasFooterView()) 84 | mAdapter.removeFooterView(); 85 | return true; 86 | case R.id.action_insert_data: 87 | if (mType == 1) { 88 | mData.add(0, Arrays.asList(DataUtils.names).get(0)); 89 | mAdapter.notifyDataSetHasChanged(); 90 | // mAdapter.add(0, Arrays.asList(DataUtils.names).get(0)); 91 | } else if (mType == 2) { 92 | mAdapter.add(0, DataUtils.generateData().get(0)); 93 | } 94 | return true; 95 | case R.id.action_addAll_data: 96 | if (mType == 1) { 97 | mAdapter.addAll(Arrays.asList(DataUtils.names)); 98 | } else if (mType == 2) { 99 | mAdapter.addAll(DataUtils.generateData()); 100 | } 101 | return true; 102 | case R.id.action_replaceAll_data: 103 | if (mType == 1) { 104 | Toast.makeText(getContext(), "偷个懒", Toast.LENGTH_SHORT).show(); 105 | } else if (mType == 2) { 106 | mAdapter.replaceAll(DataUtils.generateData()); 107 | } 108 | return true; 109 | case R.id.action_clear_data: 110 | mAdapter.clear(); 111 | return true; 112 | } 113 | return super.onOptionsItemSelected(item); 114 | } 115 | 116 | @Nullable 117 | @Override 118 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 119 | View view = inflater.inflate(R.layout.fragment_listview, container, false); 120 | mListView = (ListView) view; 121 | header = new TextView(getContext()); 122 | header.setBackgroundColor(Color.YELLOW); 123 | header.setText("header"); 124 | footer = new TextView(getContext()); 125 | footer.setBackgroundColor(Color.BLUE); 126 | footer.setText("footer"); 127 | if (mType == 1) { 128 | mData = new ArrayList<>(Arrays.asList(DataUtils.names)); 129 | mAdapter = new SingleAdapter(getContext(), mData, R.layout.item_type1); 130 | mListView.setAdapter(mAdapter); 131 | } else if (mType == 2) { 132 | // multiAdapter = new MultipleAdapter(getContext(), DataUtils.generateData(), new IMulItemViewType() { 133 | // @Override 134 | // public int getItemViewType(int position, MockModel mockModel) { 135 | // if (position % 2 == 0) { 136 | // return 0; 137 | // } 138 | // return 1; 139 | // } 140 | // 141 | // @Override 142 | // public int getLayoutId(int viewType) { 143 | // if (viewType == 0) { 144 | // return R.layout.item_type1; 145 | // } 146 | // return R.layout.item_type2; 147 | // } 148 | // 149 | // @Override 150 | // public int getViewTypeCount() { 151 | // return 2; 152 | // } 153 | // }); 154 | mAdapter = new MultipleAdapter(getContext(), DataUtils.generateData(), null); 155 | mListView.setAdapter(mAdapter); 156 | } 157 | return view; 158 | } 159 | 160 | } 161 | -------------------------------------------------------------------------------- /demo/src/main/java/org/byteam/superadapter/demo/fragment/RecyclerViewFragment.java: -------------------------------------------------------------------------------- 1 | package org.byteam.superadapter.demo.fragment; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v7.widget.LinearLayoutManager; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.support.v7.widget.StaggeredGridLayoutManager; 10 | import android.util.Log; 11 | import android.view.LayoutInflater; 12 | import android.view.Menu; 13 | import android.view.MenuInflater; 14 | import android.view.MenuItem; 15 | import android.view.View; 16 | import android.view.ViewGroup; 17 | import android.widget.TextView; 18 | 19 | import org.byteam.superadapter.DefaultDiffCallback; 20 | import org.byteam.superadapter.OnItemClickListener; 21 | import org.byteam.superadapter.SimpleMulItemViewType; 22 | import org.byteam.superadapter.SuperAdapter; 23 | import org.byteam.superadapter.demo.R; 24 | import org.byteam.superadapter.demo.adapter.MultipleAdapter; 25 | import org.byteam.superadapter.demo.adapter.SingleAdapter; 26 | import org.byteam.superadapter.demo.model.DataUtils; 27 | import org.byteam.superadapter.demo.model.MockModel; 28 | 29 | import java.util.ArrayList; 30 | import java.util.Arrays; 31 | 32 | import static org.byteam.superadapter.demo.model.DataUtils.generateData; 33 | 34 | /** 35 | * Fragment contains RecyclerView. 36 | * Created by Cheney on 15/12/19. 37 | */ 38 | public class RecyclerViewFragment extends Fragment { 39 | 40 | private int mType; 41 | private static final String TYPE = "type"; 42 | 43 | private RecyclerView recyclerView; 44 | 45 | private SuperAdapter mAdapter; 46 | 47 | private TextView header, footer; 48 | 49 | public static RecyclerViewFragment newInstance(int type) { 50 | RecyclerViewFragment fragment = new RecyclerViewFragment(); 51 | Bundle args = new Bundle(); 52 | args.putInt(TYPE, type); 53 | fragment.setArguments(args); 54 | return fragment; 55 | } 56 | 57 | @Override 58 | public void onCreate(Bundle savedInstanceState) { 59 | super.onCreate(savedInstanceState); 60 | setHasOptionsMenu(true); 61 | if (getArguments() != null) { 62 | mType = getArguments().getInt(TYPE, 1); 63 | } 64 | } 65 | 66 | @Override 67 | public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 68 | inflater.inflate(R.menu.menu_main, menu); 69 | } 70 | 71 | @Override 72 | public boolean onOptionsItemSelected(MenuItem item) { 73 | int id = item.getItemId(); 74 | switch (id) { 75 | case R.id.action_add_header: 76 | if (!mAdapter.hasHeaderView()) { 77 | mAdapter.addHeaderView(header); 78 | recyclerView.scrollToPosition(0); 79 | } 80 | return true; 81 | case R.id.action_remove_header: 82 | if (mAdapter.hasHeaderView()) 83 | mAdapter.removeHeaderView(); 84 | return true; 85 | case R.id.action_add_footer: 86 | if (!mAdapter.hasFooterView()) 87 | mAdapter.addFooterView(footer); 88 | return true; 89 | case R.id.action_remove_footer: 90 | if (mAdapter.hasFooterView()) 91 | mAdapter.removeFooterView(); 92 | return true; 93 | case R.id.action_insert_data: 94 | if (mType == 2) { 95 | mAdapter.add(0, generateData().get(0)); 96 | } else { 97 | mAdapter.add(0, Arrays.asList(DataUtils.names).get(0)); 98 | } 99 | return true; 100 | case R.id.action_addAll_data: 101 | if (mType == 2) { 102 | mAdapter.addAll(generateData()); 103 | } else { 104 | mAdapter.addAll(new ArrayList<>(Arrays.asList(DataUtils.names))); 105 | } 106 | return true; 107 | case R.id.action_replaceAll_data: 108 | if (mAdapter != null && mType == 2) { 109 | mAdapter.replaceAll(generateData()); 110 | } 111 | return true; 112 | case R.id.action_diff: 113 | if (mAdapter != null && mType == 2) { 114 | DefaultDiffCallback callback = new DefaultDiffCallback( 115 | mAdapter.getData(), DataUtils.generateData()) { 116 | @Override 117 | public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { 118 | // If your items have unique ids, this method should check their id equality. 119 | return true; 120 | } 121 | 122 | @Override 123 | public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { 124 | MockModel oldModel = getOldList().get(oldItemPosition); 125 | MockModel newModel = getNewList().get(newItemPosition); 126 | 127 | return oldModel.getName().equals(newModel.getName()) && 128 | oldModel.getAge() == newModel.getAge(); 129 | } 130 | }; 131 | mAdapter.diff(callback); 132 | } 133 | return true; 134 | case R.id.action_clear_data: 135 | mAdapter.clear(); 136 | return true; 137 | } 138 | return super.onOptionsItemSelected(item); 139 | } 140 | 141 | @Override 142 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 143 | Bundle savedInstanceState) { 144 | View view = inflater.inflate(R.layout.fragment_recyclerview, container, false); 145 | header = new TextView(getContext()); 146 | header.setBackgroundColor(Color.YELLOW); 147 | header.setText("header"); 148 | footer = new TextView(getContext()); 149 | footer.setBackgroundColor(Color.BLUE); 150 | footer.setText("footer"); 151 | // Set the adapter 152 | if (view instanceof RecyclerView) { 153 | Context context = view.getContext(); 154 | recyclerView = (RecyclerView) view; 155 | recyclerView.setLayoutManager(new LinearLayoutManager(context)); 156 | if (mType == 1) { 157 | mAdapter = new SingleAdapter(getContext(), new ArrayList<>(Arrays.asList(DataUtils.names)), R.layout.item_type1); 158 | mAdapter.setOnItemClickListener(new OnItemClickListener() { 159 | @Override 160 | public void onItemClick(View itemView, int viewType, int position) { 161 | Log.d("onItemClick", "" + position); 162 | } 163 | }); 164 | recyclerView.setAdapter(mAdapter); 165 | } else if (mType == 2) { 166 | recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)); 167 | mAdapter = new MultipleAdapter(getContext(), generateData(), 168 | new SimpleMulItemViewType() { 169 | @Override 170 | public int getItemViewType(int position, MockModel mockModel) { 171 | if (position % 2 == 0) { 172 | return 0; 173 | } 174 | return 1; 175 | } 176 | 177 | @Override 178 | public int getLayoutId(int viewType) { 179 | if (viewType == 0) { 180 | return R.layout.item_type1; 181 | } 182 | return R.layout.item_type2; 183 | } 184 | }); 185 | recyclerView.setAdapter(mAdapter); 186 | } 187 | } 188 | return view; 189 | } 190 | 191 | } 192 | -------------------------------------------------------------------------------- /demo/src/main/java/org/byteam/superadapter/demo/model/DataUtils.java: -------------------------------------------------------------------------------- 1 | package org.byteam.superadapter.demo.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | *

8 | * Generate random data. 9 | *

10 | * Created by Chen on 2016/5/23. 11 | */ 12 | public final class DataUtils { 13 | public static String[] names = {"John", "Michelle", "Amy", "Kim", "Mary", "David", "Sunny", 14 | "James", "Maria", "Betty", "Brian", "Candy", "Charles", "Vicky", "James"}; 15 | 16 | public static List generateData() { 17 | List models = new ArrayList<>(); 18 | for (int i = 0; i < getRandom(5, 15); i++) { 19 | models.add(new MockModel(names[getRandom(0, names.length - 1)], getRandom(1, 30))); 20 | } 21 | return models; 22 | } 23 | 24 | private static int getRandom(int min, int max) { 25 | return min + (int) (Math.random() * (max - min + 1)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /demo/src/main/java/org/byteam/superadapter/demo/model/MockModel.java: -------------------------------------------------------------------------------- 1 | package org.byteam.superadapter.demo.model; 2 | 3 | public class MockModel { 4 | private String name; 5 | private int age; 6 | 7 | public MockModel(String name, int age) { 8 | this.name = name; 9 | this.age = age; 10 | } 11 | 12 | public String getName() { 13 | return name; 14 | } 15 | 16 | public void setName(String name) { 17 | this.name = name; 18 | } 19 | 20 | public int getAge() { 21 | return age; 22 | } 23 | 24 | public void setAge(int age) { 25 | this.age = age; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 18 | 19 | 26 | 27 | 28 | 29 | 33 | 34 | 35 | 36 | 41 | 42 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/fragment_listview.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/fragment_recyclerview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/item_type1.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/item_type2.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 18 | 19 | 25 | 26 | 32 | 33 | -------------------------------------------------------------------------------- /demo/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 9 | 13 | 17 | 21 | 25 | 29 | 33 | 37 | 41 | 42 | -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byteam/SuperAdapter/eccb299a6b769742802c60a0b532317a35846941/demo/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byteam/SuperAdapter/eccb299a6b769742802c60a0b532317a35846941/demo/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byteam/SuperAdapter/eccb299a6b769742802c60a0b532317a35846941/demo/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byteam/SuperAdapter/eccb299a6b769742802c60a0b532317a35846941/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byteam/SuperAdapter/eccb299a6b769742802c60a0b532317a35846941/demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /demo/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /demo/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /demo/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 16dp 6 | 8dp 7 | 16dp 8 | 9 | -------------------------------------------------------------------------------- /demo/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SuperAdapter 3 | Settings 4 | Hello World from section: %1$d 5 | 6 | -------------------------------------------------------------------------------- /demo/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 14 |