├── README.md ├── build.gradle ├── commonadapter-sample ├── .gitignore ├── build.gradle ├── commonadapter-sample.iml ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── github │ │ └── zeng1990java │ │ └── commonadapter_sample │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── zeng1990java │ │ │ └── commonadapter_sample │ │ │ ├── App.java │ │ │ ├── HorizontalRecyclerViewActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── MultiTypeActivity.java │ │ │ ├── PicassoImageLoader.java │ │ │ ├── bean │ │ │ └── News.java │ │ │ ├── consts │ │ │ └── Consts.java │ │ │ ├── data │ │ │ └── NewDataSource.java │ │ │ └── widget │ │ │ └── CustomLoadMoreView.java │ └── res │ │ ├── drawable │ │ └── item_bg.xml │ │ ├── layout │ │ ├── activity_horizontal.xml │ │ ├── activity_main.xml │ │ ├── activity_multi_type.xml │ │ ├── custom_loading.xml │ │ ├── footer_view.xml │ │ ├── header_view.xml │ │ ├── item_hotizontail.xml │ │ ├── item_multiple_picture.xml │ │ ├── item_none_picture.xml │ │ ├── item_single_picture.xml │ │ └── item_view.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── github │ └── zeng1990java │ └── commonadapter_sample │ └── ExampleUnitTest.java ├── commonadapter ├── .gitignore ├── build.gradle ├── commonadapter.iml ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── github │ │ └── zeng1990java │ │ └── commonadapter │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── zeng1990java │ │ │ └── commonadapter │ │ │ ├── AdapterConfig.java │ │ │ ├── AdapterImageLoader.java │ │ │ ├── ArrayRecyclerAdapter.java │ │ │ ├── CommonRecyclerAdapter.java │ │ │ ├── DefaultLoadMoreView.java │ │ │ ├── LoadMoreView.java │ │ │ ├── ViewBinder.java │ │ │ └── ViewHolder.java │ └── res │ │ ├── layout │ │ └── loading_layout.xml │ │ └── values │ │ ├── ids.xml │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── github │ └── zeng1990java │ └── commonadapter │ └── ExampleUnitTest.java ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /README.md: -------------------------------------------------------------------------------- 1 | ## 特性 2 | 3 | * 封装数据集合添加删除等操作 4 | * 添加或删除Header和Footer 5 | * 全局的图片加载器 6 | * Item 的click和longClick事件 7 | * 多Item布局支持 8 | * 滑动到底部加载更多 9 | 10 | ## 添加到项目(JitPack.io) 11 | 12 | ```groovy 13 | allprojects { 14 | repositories { 15 | ... 16 | maven { url "https://jitpack.io" } 17 | } 18 | } 19 | 20 | dependencies { 21 | compile 'com.github.zeng1990java:CommonRecyclerAdapter:0.3.2' 22 | } 23 | ``` 24 | 25 | ## 使用示例 26 | 27 | * 配置默认的加载更多布局和图片加载器 28 | 29 | ```java 30 | public class App extends Application { 31 | @Override 32 | public void onCreate() { 33 | super.onCreate(); 34 | // 配置默认的加载更多布局和默认的图片加载器 35 | AdapterConfig.getInstance() 36 | .setLoadingLayoutId(R.layout.custom_loading) 37 | .setImageLoader(new PicassoImageLoader()); 38 | 39 | } 40 | } 41 | 42 | public class PicassoImageLoader implements AdapterImageLoader { 43 | @Override 44 | public void load(Context context, ImageView imageView, String imageUrl) { 45 | Picasso.with(context).load(imageUrl).into(imageView); 46 | } 47 | } 48 | ``` 49 | 50 | * 单Item布局使用示例 51 | 52 | ```java 53 | // 单布局使用 54 | mRecyclerView.setAdapter(mCommonRecyclerAdapter = new CommonRecyclerAdapter(this, R.layout.item_view, getDatas()) { 55 | @Override 56 | public void bindData(ViewHolder holder, String data, int position) { 57 | holder.viewBinder().setText(R.id.text, data + " position: "+position); 58 | } 59 | }); 60 | 61 | // 添加Header 62 | ViewBinder header1Binder = mCommonRecyclerAdapter.addHeaderView(R.layout.header_view); 63 | header1Binder.getView().setOnClickListener(new View.OnClickListener() { 64 | @Override 65 | public void onClick(View v) { 66 | toast("header click"); 67 | } 68 | }); 69 | // header 数据绑定 70 | header1Binder.setText(R.id.header_text, "Header 1"); 71 | 72 | // 73 | ViewBinder header2Binder = mCommonRecyclerAdapter.addHeaderView(R.layout.header_view); 74 | header2Binder.getView().setOnClickListener(new View.OnClickListener() { 75 | @Override 76 | public void onClick(View v) { 77 | // 移除header 78 | mCommonRecyclerAdapter.removeHeaderView(v); 79 | } 80 | }); 81 | 82 | // 添加footer 83 | ViewBinder footerBinder = mCommonRecyclerAdapter.addFooterView(R.layout.footer_view); 84 | footerBinder.getView().setOnClickListener(new View.OnClickListener() { 85 | @Override 86 | public void onClick(View v) { 87 | // 移除footer 88 | mCommonRecyclerAdapter.removeFooterView(v); 89 | } 90 | }); 91 | 92 | // 设置item点击事件 93 | mCommonRecyclerAdapter.setOnItemClickListener(new CommonRecyclerAdapter.OnItemClickListener() { 94 | @Override 95 | public void onItemClick(ViewHolder holder, int position) { 96 | MultiTypeActivity.start(MainActivity.this); 97 | } 98 | }); 99 | 100 | // 设置item长按事件 101 | mCommonRecyclerAdapter.setOnItemLongClickListener(new CommonRecyclerAdapter.OnItemLongClickListener() { 102 | @Override 103 | public boolean onItemLongClick(ViewHolder holder, int position) { 104 | mCommonRecyclerAdapter.set(position, "Item Long Click "+position); 105 | return true; 106 | } 107 | }); 108 | 109 | // 设置加载更多监听器 110 | mCommonRecyclerAdapter.setOnLoadMoreListener(new CommonRecyclerAdapter.OnLoadMoreListener() { 111 | @Override 112 | public void onLoadMore() { 113 | mHandler.postDelayed(new Runnable() { 114 | @Override 115 | public void run() { 116 | mCommonRecyclerAdapter.setIsHasLoadMore(false); 117 | mCommonRecyclerAdapter.addAll(getDatas()); 118 | } 119 | }, 5000); 120 | } 121 | }); 122 | 123 | // 设置加载跟多的布局 124 | // mCommonRecyclerAdapter.setLoadMoreLayoutId(R.layout.custom_loading); 125 | // 设置有加载更多 126 | mCommonRecyclerAdapter.setIsHasLoadMore(true); 127 | ``` 128 | 129 | * 多Item布局使用示例 130 | 131 | ```java 132 | private class NewsAdapter extends CommonRecyclerAdapter{ 133 | 134 | public NewsAdapter(@NonNull Context context) { 135 | super(context, 0); 136 | } 137 | 138 | @Override 139 | public int getItemLayoutResId(News data, int position) { 140 | int layoutResId = -1; 141 | switch (data.getNewsType()){ 142 | case News.TYPE_NONE_PICTURE: 143 | layoutResId = R.layout.item_none_picture; 144 | break; 145 | case News.TYPE_SINGLE_PICTURE: 146 | layoutResId = R.layout.item_single_picture; 147 | break; 148 | case News.TYPE_MULTIPLE_PICTURE: 149 | layoutResId = R.layout.item_multiple_picture; 150 | break; 151 | } 152 | return layoutResId; 153 | } 154 | 155 | @Override 156 | public void bindData(ViewHolder holder, News data, int position) { 157 | switch (data.getNewsType()){ 158 | case News.TYPE_NONE_PICTURE: 159 | holder.viewBinder().setText(R.id.item_none_picture_title, data.getTitle()) 160 | .setText(R.id.item_none_picture_author, 161 | String.format(Locale.CHINA, Consts.FORMAT_AUTHOR, data.getAuthor())) 162 | .setText(R.id.item_none_picture_date, 163 | Consts.DATE_FORMAT.format(new Date(data.getReleaseTime()))) 164 | .setText(R.id.item_none_picture_intro, data.getIntro()); 165 | break; 166 | case News.TYPE_SINGLE_PICTURE: 167 | holder.viewBinder().setText(R.id.item_single_picture_title, data.getTitle()) 168 | .setText(R.id.item_single_picture_author, 169 | String.format(Locale.CHINA, Consts.FORMAT_AUTHOR, data.getAuthor())) 170 | .setText(R.id.item_single_picture_date, 171 | Consts.DATE_FORMAT.format(new Date(data.getReleaseTime()))) 172 | .setImageUrl(R.id.item_single_picture_cover,data.getCoverUrl()); 173 | break; 174 | case News.TYPE_MULTIPLE_PICTURE: 175 | String[] urls = data.getCoverUrl().split(Consts.URL_SEPARATOR); 176 | holder.viewBinder().setText(R.id.item_multiple_picture_intro, data.getIntro()) 177 | .setImageUrl(R.id.item_multiple_picture_cover_left,urls[0]) 178 | .setImageUrl(R.id.item_multiple_picture_cover_right, urls[1]); 179 | break; 180 | } 181 | } 182 | } 183 | ``` 184 | 185 | ##感谢 186 | 187 | * [base-adapter-helper](https://github.com/JoanZapata/base-adapter-helper) 188 | * [CommonAdapter](https://github.com/qyxxjd/CommonAdapter) 189 | -------------------------------------------------------------------------------- /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 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.1.2' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | -------------------------------------------------------------------------------- /commonadapter-sample/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /commonadapter-sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "24.0.0" 6 | 7 | defaultConfig { 8 | applicationId "com.github.zeng1990java.commonadapter_sample" 9 | minSdkVersion 14 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.4.0' 26 | compile 'com.android.support:recyclerview-v7:23.4.0' 27 | compile 'com.squareup.picasso:picasso:2.5.2' 28 | compile project(':commonadapter') 29 | } 30 | -------------------------------------------------------------------------------- /commonadapter-sample/commonadapter-sample.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /commonadapter-sample/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/zxb/Downloads/android-sdk-macosx/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 | -------------------------------------------------------------------------------- /commonadapter-sample/src/androidTest/java/com/github/zeng1990java/commonadapter_sample/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.github.zeng1990java.commonadapter_sample; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /commonadapter-sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /commonadapter-sample/src/main/java/com/github/zeng1990java/commonadapter_sample/App.java: -------------------------------------------------------------------------------- 1 | package com.github.zeng1990java.commonadapter_sample; 2 | 3 | import android.app.Application; 4 | 5 | import com.github.zeng1990java.commonadapter.AdapterConfig; 6 | 7 | /** 8 | * $desc 9 | * 10 | * @author zxb 11 | * @date 16/7/17 上午10:14 12 | */ 13 | public class App extends Application { 14 | @Override 15 | public void onCreate() { 16 | super.onCreate(); 17 | // 配置默认的加载更多布局和默认的图片加载器 18 | AdapterConfig.getInstance() 19 | .setLoadingLayoutId(R.layout.custom_loading) 20 | .setImageLoader(new PicassoImageLoader()); 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /commonadapter-sample/src/main/java/com/github/zeng1990java/commonadapter_sample/HorizontalRecyclerViewActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.zeng1990java.commonadapter_sample; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | import android.support.annotation.Nullable; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.support.v7.widget.LinearLayoutManager; 10 | import android.support.v7.widget.RecyclerView; 11 | import android.widget.Toast; 12 | 13 | import com.github.zeng1990java.commonadapter.CommonRecyclerAdapter; 14 | import com.github.zeng1990java.commonadapter.ViewHolder; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | /** 20 | * $desc 21 | * 22 | * @author zxb 23 | * @date 16/9/16 下午8:43 24 | */ 25 | public class HorizontalRecyclerViewActivity extends AppCompatActivity { 26 | 27 | public static void start(Context context) { 28 | Intent starter = new Intent(context, HorizontalRecyclerViewActivity.class); 29 | context.startActivity(starter); 30 | } 31 | 32 | @Override 33 | protected void onCreate(@Nullable Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | setContentView(R.layout.activity_horizontal); 36 | 37 | RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view); 38 | 39 | recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); 40 | 41 | // recyclerView.setLayoutManager(new GridLayoutManager(this, 2, GridLayoutManager.HORIZONTAL, false)); 42 | 43 | final HorizontalAdapter adapter = new HorizontalAdapter(this); 44 | recyclerView.setAdapter(adapter); 45 | // 设置方向为水平 46 | adapter.setOrientation(CommonRecyclerAdapter.HORIZONTAL); 47 | 48 | adapter.addHeaderView(R.layout.item_hotizontail).setText(R.id.text, "Header"); 49 | 50 | adapter.addFooterView(R.layout.item_hotizontail).setText(R.id.text, "Footer"); 51 | 52 | adapter.addAll(getHorizontalListData()); 53 | 54 | 55 | adapter.setOnItemClickListener(new CommonRecyclerAdapter.OnItemClickListener() { 56 | @Override 57 | public void onItemClick(ViewHolder holder, int position) { 58 | Toast.makeText(HorizontalRecyclerViewActivity.this, adapter.getItem(position), Toast.LENGTH_SHORT).show(); 59 | } 60 | }); 61 | } 62 | 63 | static class HorizontalAdapter extends CommonRecyclerAdapter{ 64 | 65 | public HorizontalAdapter(@NonNull Context context) { 66 | super(context, R.layout.item_hotizontail); 67 | } 68 | 69 | @Override 70 | public void bindData(ViewHolder holder, String data, int position) { 71 | holder.viewBinder().setText(R.id.text, data); 72 | } 73 | } 74 | 75 | 76 | List getHorizontalListData(){ 77 | List datas = new ArrayList<>(); 78 | for (int i = 0; i < 20; i++) { 79 | datas.add("Item "+i); 80 | } 81 | return datas; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /commonadapter-sample/src/main/java/com/github/zeng1990java/commonadapter_sample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.zeng1990java.commonadapter_sample; 2 | 3 | import android.os.Bundle; 4 | import android.os.Handler; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.View; 9 | import android.widget.Toast; 10 | 11 | import com.github.zeng1990java.commonadapter.CommonRecyclerAdapter; 12 | import com.github.zeng1990java.commonadapter.ViewBinder; 13 | import com.github.zeng1990java.commonadapter.ViewHolder; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.Random; 18 | 19 | public class MainActivity extends AppCompatActivity { 20 | 21 | RecyclerView mRecyclerView; 22 | CommonRecyclerAdapter mCommonRecyclerAdapter; 23 | 24 | private Handler mHandler = new Handler(); 25 | 26 | @Override 27 | protected void onCreate(Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | setContentView(R.layout.activity_main); 30 | 31 | mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); 32 | 33 | mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); 34 | // mRecyclerView.setLayoutManager(new GridLayoutManager(this, 2)); 35 | // mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)); 36 | 37 | // 单布局使用 38 | mRecyclerView.setAdapter(mCommonRecyclerAdapter = new CommonRecyclerAdapter(this, R.layout.item_view, getDatas()) { 39 | @Override 40 | public void bindData(ViewHolder holder, String data, int position) { 41 | holder.viewBinder().setText(R.id.text, data + " position: "+position); 42 | } 43 | }); 44 | 45 | // 添加Header 46 | ViewBinder header1Binder = mCommonRecyclerAdapter.addHeaderView(R.layout.header_view); 47 | header1Binder.getView().setOnClickListener(new View.OnClickListener() { 48 | @Override 49 | public void onClick(View v) { 50 | toast("header click"); 51 | } 52 | }); 53 | // header 数据绑定 54 | header1Binder.setText(R.id.header_text, "Header 1"); 55 | 56 | // 57 | ViewBinder header2Binder = mCommonRecyclerAdapter.addHeaderView(R.layout.header_view); 58 | header2Binder.getView().setOnClickListener(new View.OnClickListener() { 59 | @Override 60 | public void onClick(View v) { 61 | // 移除header 62 | mCommonRecyclerAdapter.removeHeaderView(v); 63 | } 64 | }); 65 | 66 | // 添加footer 67 | ViewBinder footerBinder = mCommonRecyclerAdapter.addFooterView(R.layout.footer_view); 68 | footerBinder.getView().setOnClickListener(new View.OnClickListener() { 69 | @Override 70 | public void onClick(View v) { 71 | // 移除footer 72 | mCommonRecyclerAdapter.removeFooterView(v); 73 | } 74 | }); 75 | 76 | // 设置item点击事件 77 | mCommonRecyclerAdapter.setOnItemClickListener(new CommonRecyclerAdapter.OnItemClickListener() { 78 | @Override 79 | public void onItemClick(ViewHolder holder, int position) { 80 | MultiTypeActivity.start(MainActivity.this); 81 | } 82 | }); 83 | 84 | // 设置item长按事件 85 | mCommonRecyclerAdapter.setOnItemLongClickListener(new CommonRecyclerAdapter.OnItemLongClickListener() { 86 | @Override 87 | public boolean onItemLongClick(ViewHolder holder, int position) { 88 | mCommonRecyclerAdapter.set(position, "Item Long Click "+position); 89 | return true; 90 | } 91 | }); 92 | 93 | // 设置加载更多监听器 94 | mCommonRecyclerAdapter.setOnLoadMoreListener(new CommonRecyclerAdapter.OnLoadMoreListener() { 95 | @Override 96 | public void onLoadMore() { 97 | mHandler.postDelayed(new Runnable() { 98 | @Override 99 | public void run() { 100 | int random = new Random().nextInt(20); 101 | Toast.makeText(getApplicationContext(), "random: "+random, Toast.LENGTH_SHORT).show(); 102 | if (random < 10){ 103 | mCommonRecyclerAdapter.onLoadMoreError(); 104 | }else { 105 | mCommonRecyclerAdapter.setIsHasLoadMore(true); 106 | mCommonRecyclerAdapter.addAll(getDatas()); 107 | } 108 | 109 | } 110 | }, 2000); 111 | } 112 | }); 113 | 114 | // 设置加载跟多的布局 115 | // mCommonRecyclerAdapter.setLoadMoreLayoutId(R.layout.custom_loading); 116 | // 设置有加载更多 117 | mCommonRecyclerAdapter.setIsHasLoadMore(true); 118 | } 119 | 120 | private List getDatas(){ 121 | List datas = new ArrayList<>(); 122 | for (int i = 0; i < 30; i++) { 123 | datas.add("Item "+i); 124 | } 125 | 126 | return datas; 127 | } 128 | 129 | public void add(View view){ 130 | mCommonRecyclerAdapter.add("new add data "+new Random().nextInt(20)); 131 | } 132 | 133 | public void horizontal(View v){ 134 | HorizontalRecyclerViewActivity.start(this); 135 | } 136 | 137 | private void toast(String text){ 138 | Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /commonadapter-sample/src/main/java/com/github/zeng1990java/commonadapter_sample/MultiTypeActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.zeng1990java.commonadapter_sample; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.LinearLayoutManager; 9 | import android.support.v7.widget.RecyclerView; 10 | import android.widget.Toast; 11 | 12 | import com.github.zeng1990java.commonadapter.CommonRecyclerAdapter; 13 | import com.github.zeng1990java.commonadapter.ViewHolder; 14 | import com.github.zeng1990java.commonadapter_sample.bean.News; 15 | import com.github.zeng1990java.commonadapter_sample.consts.Consts; 16 | import com.github.zeng1990java.commonadapter_sample.data.NewDataSource; 17 | 18 | import java.util.Date; 19 | import java.util.Locale; 20 | 21 | public class MultiTypeActivity extends AppCompatActivity { 22 | 23 | public static void start(Context context) { 24 | Intent starter = new Intent(context, MultiTypeActivity.class); 25 | context.startActivity(starter); 26 | } 27 | 28 | RecyclerView mRecyclerView; 29 | NewsAdapter mNewsAdapter; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_multi_type); 35 | 36 | mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); 37 | mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); 38 | mRecyclerView.setAdapter(mNewsAdapter = new NewsAdapter(this)); 39 | 40 | mNewsAdapter.addAll(NewDataSource.getNewsList()); 41 | 42 | mNewsAdapter.setOnItemClickListener(new CommonRecyclerAdapter.OnItemClickListener() { 43 | @Override 44 | public void onItemClick(ViewHolder holder, int position) { 45 | News news = mNewsAdapter.getItem(position); 46 | Toast.makeText(MultiTypeActivity.this, news.getTitle(), Toast.LENGTH_SHORT).show(); 47 | } 48 | }); 49 | 50 | mNewsAdapter.addHeaderView(R.layout.header_view); 51 | } 52 | 53 | private class NewsAdapter extends CommonRecyclerAdapter{ 54 | 55 | public NewsAdapter(@NonNull Context context) { 56 | super(context, 0); 57 | } 58 | 59 | @Override 60 | public int getItemLayoutResId(News data, int position) { 61 | int layoutResId = -1; 62 | switch (data.getNewsType()){ 63 | case News.TYPE_NONE_PICTURE: 64 | layoutResId = R.layout.item_none_picture; 65 | break; 66 | case News.TYPE_SINGLE_PICTURE: 67 | layoutResId = R.layout.item_single_picture; 68 | break; 69 | case News.TYPE_MULTIPLE_PICTURE: 70 | layoutResId = R.layout.item_multiple_picture; 71 | break; 72 | } 73 | return layoutResId; 74 | } 75 | 76 | @Override 77 | public void bindData(ViewHolder holder, News data, int position) { 78 | switch (data.getNewsType()){ 79 | case News.TYPE_NONE_PICTURE: 80 | holder.viewBinder().setText(R.id.item_none_picture_title, data.getTitle()) 81 | .setText(R.id.item_none_picture_author, 82 | String.format(Locale.CHINA, Consts.FORMAT_AUTHOR, data.getAuthor())) 83 | .setText(R.id.item_none_picture_date, 84 | Consts.DATE_FORMAT.format(new Date(data.getReleaseTime()))) 85 | .setText(R.id.item_none_picture_intro, data.getIntro()); 86 | break; 87 | case News.TYPE_SINGLE_PICTURE: 88 | holder.viewBinder().setText(R.id.item_single_picture_title, data.getTitle()) 89 | .setText(R.id.item_single_picture_author, 90 | String.format(Locale.CHINA, Consts.FORMAT_AUTHOR, data.getAuthor())) 91 | .setText(R.id.item_single_picture_date, 92 | Consts.DATE_FORMAT.format(new Date(data.getReleaseTime()))) 93 | .setImageUrl(R.id.item_single_picture_cover,data.getCoverUrl()); 94 | break; 95 | case News.TYPE_MULTIPLE_PICTURE: 96 | String[] urls = data.getCoverUrl().split(Consts.URL_SEPARATOR); 97 | holder.viewBinder().setText(R.id.item_multiple_picture_intro, data.getIntro()) 98 | .setImageUrl(R.id.item_multiple_picture_cover_left,urls[0]) 99 | .setImageUrl(R.id.item_multiple_picture_cover_right, urls[1]); 100 | break; 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /commonadapter-sample/src/main/java/com/github/zeng1990java/commonadapter_sample/PicassoImageLoader.java: -------------------------------------------------------------------------------- 1 | package com.github.zeng1990java.commonadapter_sample; 2 | 3 | import android.content.Context; 4 | import android.widget.ImageView; 5 | 6 | import com.github.zeng1990java.commonadapter.AdapterImageLoader; 7 | import com.squareup.picasso.Picasso; 8 | 9 | /** 10 | * $desc 11 | * 12 | * @author zxb 13 | * @date 16/7/17 下午10:53 14 | */ 15 | public class PicassoImageLoader implements AdapterImageLoader { 16 | @Override 17 | public void load(Context context, ImageView imageView, String imageUrl) { 18 | Picasso.with(context).load(imageUrl).into(imageView); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /commonadapter-sample/src/main/java/com/github/zeng1990java/commonadapter_sample/bean/News.java: -------------------------------------------------------------------------------- 1 | package com.github.zeng1990java.commonadapter_sample.bean; 2 | 3 | /** 4 | * $desc 5 | * 6 | * @author zxb 7 | * @date 16/7/17 下午10:49 8 | */ 9 | public class News { 10 | 11 | /** 单图布局样式 */ 12 | public static final int TYPE_SINGLE_PICTURE = 0; 13 | /** 多图布局样式 */ 14 | public static final int TYPE_MULTIPLE_PICTURE = 1; 15 | /** 无图布局样式 */ 16 | public static final int TYPE_NONE_PICTURE = 2; 17 | 18 | private String title; 19 | private String intro; 20 | private String coverUrl; 21 | private String author; 22 | private long releaseTime; 23 | private int newsType; 24 | 25 | public News(){} 26 | 27 | public News(int newsType, String author, String title, String intro) { 28 | this(newsType,author,title,intro,""); 29 | } 30 | 31 | public News(int newsType, String author, String title, String intro, String coverUrl) { 32 | this.newsType = newsType; 33 | this.author = author; 34 | this.title = title; 35 | this.intro = intro; 36 | this.coverUrl = coverUrl; 37 | this.releaseTime = System.currentTimeMillis(); 38 | } 39 | 40 | public String getTitle() { 41 | return title; 42 | } 43 | 44 | public void setTitle(String title) { 45 | this.title = title; 46 | } 47 | 48 | public String getIntro() { 49 | return intro; 50 | } 51 | 52 | public void setIntro(String intro) { 53 | this.intro = intro; 54 | } 55 | 56 | public String getCoverUrl() { 57 | return coverUrl; 58 | } 59 | 60 | public void setCoverUrl(String coverUrl) { 61 | this.coverUrl = coverUrl; 62 | } 63 | 64 | public String getAuthor() { 65 | return author; 66 | } 67 | 68 | public void setAuthor(String author) { 69 | this.author = author; 70 | } 71 | 72 | public long getReleaseTime() { 73 | return releaseTime; 74 | } 75 | 76 | public void setReleaseTime(long releaseTime) { 77 | this.releaseTime = releaseTime; 78 | } 79 | 80 | public int getNewsType() { 81 | return newsType; 82 | } 83 | 84 | public void setNewsType(int newsType) { 85 | this.newsType = newsType; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /commonadapter-sample/src/main/java/com/github/zeng1990java/commonadapter_sample/consts/Consts.java: -------------------------------------------------------------------------------- 1 | package com.github.zeng1990java.commonadapter_sample.consts; 2 | 3 | import java.text.SimpleDateFormat; 4 | 5 | /** 6 | * $desc 7 | * 8 | * @author zxb 9 | * @date 16/7/17 下午10:51 10 | */ 11 | public class Consts { 12 | private Consts(){} 13 | 14 | public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm"); 15 | public static final String URL_SEPARATOR = ";"; 16 | public static final String FORMAT_AUTHOR = "报道人:%s"; 17 | } 18 | -------------------------------------------------------------------------------- /commonadapter-sample/src/main/java/com/github/zeng1990java/commonadapter_sample/data/NewDataSource.java: -------------------------------------------------------------------------------- 1 | package com.github.zeng1990java.commonadapter_sample.data; 2 | 3 | import com.github.zeng1990java.commonadapter_sample.bean.News; 4 | 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * $desc 9 | * 10 | * @author zxb 11 | * @date 16/7/17 下午10:50 12 | */ 13 | public class NewDataSource { 14 | private static final String AUTHOR = "续写经典"; 15 | private static ArrayList newsList; 16 | 17 | //测试数据 18 | public static ArrayList getNewsList(){ 19 | if(null==newsList || newsList.isEmpty()){ 20 | newsList = new ArrayList<>(); 21 | newsList.add(new News(News.TYPE_SINGLE_PICTURE,AUTHOR,"谷歌返华前兆?桥头堡Google Play降低门槛","北京时间1月26日上午消息,谷歌今日在Play Games中取消了强制使用Google+登录的要求,允许没有谷歌帐号的新用户全面使用这项服务。有相关评论称,此举或意味着谷歌返华又更近了一步。","http://n.sinaimg.cn/tech/transform/20160126/g8H_-fxnvhvu7058461.jpg")); 22 | newsList.add(new News(News.TYPE_NONE_PICTURE,AUTHOR,"河北工商局:三大运营商涉嫌不正当竞争","记者从河北省工商局获悉,中国移动河北分公司、中国联通河北分公司、中国电信河北分公司等电信运营商采取赠与学校领导、班主任、联系人老师话费的方式,向广大学生强行推销“校讯通”“家校通”“翼校通”等产品,涉嫌违反《中华人民共和国反不正当竞争法》。")); 23 | newsList.add(new News(News.TYPE_MULTIPLE_PICTURE,AUTHOR,"杭州零下9度 一夜寒风吹冻西湖","1月25日清晨,西湖雷峰塔景区冰封美景醉人,当日,受霸王级寒潮影响,杭州主城区出现最低-9.3℃气温,逼近1969年的历史极值,受此影响,杭州西湖部分水域出现严重结冰现象。","http://www.sinaimg.cn/dy/slidenews/1_img/2016_04/2841_656896_533796.jpg;http://www.sinaimg.cn/dy/slidenews/1_img/2016_04/2841_656904_171122.jpg")); 24 | newsList.add(new News(News.TYPE_SINGLE_PICTURE,AUTHOR,"创投机构回应上海政府风投补偿:返税意义更大","引力创投是落户上海的早期投资机构,其合伙人戴周颖在接受新浪科技采访时认为,上海市此举还是属于招商引资的一个办法。在此之前,上海市就有专门的政策和方案,通过引导基金的方式,让更多GP(基金管理合伙人)注入上海,并且基金须有一定比例投资上海。","http://n.sinaimg.cn/tech/transform/20160126/KR43-fxnuvxc1994221.jpg")); 25 | newsList.add(new News(News.TYPE_NONE_PICTURE,AUTHOR,"上海新规:天使投资有损失可获补偿 最高补六成","近日,上海市科学技术委员会、上海市财政局、上海市发改委联合发布《上海市天使投资风险补偿管理暂行办法》,提出对投资机构投资种子期、初创期科技型企业,最终回收的转让收入与退出前累计投入该企业的投资额之间的差额部分,给予以一定比例的财务补偿。")); 26 | newsList.add(new News(News.TYPE_SINGLE_PICTURE,AUTHOR,"我们为什么投资马斯克的超级高铁Hyperloop","对于天使投资而言,每一次投资就像一次豪赌。当Peter Thiel投资Facebook、Paul Graham投资Airbnb、Sherwin Pishevar投资Uber的时候,都被很多人看作是“疯子”。当然现在有无数的投资人为错过了投资机会懊悔不已,但在最初撒出大笔现金时,谁也说不准它会成长为独角兽,还是让投资人输得血本无归。","http://s.img.mix.sina.com.cn/auto/resize?size=560_0&img=http%3A%2F%2Fsinastorage.com%2Fstorage.csj.sina.com.cn%2F319f277142405b15c3c702b03c8af1cf.jpg")); 27 | newsList.add(new News(News.TYPE_MULTIPLE_PICTURE,AUTHOR,"2015电子信息制造业销售产值同比增长8.7%","1-12月,规模以上电子信息制造业内销产值同比增长17.3%,出口交货值同比下降0.1%。从内外资角度看,1-12月,内资企业的销售产值同比增长17.8%,港澳台投资企业销售产值同比增长8.3%,外商投资企业销售产值同比下降0.1%。","http://n.sinaimg.cn/tech/transform/20160125/onUR-fxnuvxe8392239.png;http://n.sinaimg.cn/tech/transform/20160125/Ll3P-fxnuvxe8392273.png")); 28 | newsList.add(new News(News.TYPE_NONE_PICTURE,AUTHOR,"微软反垄断案新突破 Win10或需剥离可信计算","半年多来,我们跟微软进行过数次谈判。我们希望微软可以按照我国法律法规实现本土化,但谈判至今还没有结果。”沈昌祥系此次微软网络安全审查的负责人,他笑称,“每一次都斗争激烈,我们要坚守网络安全主权,而微软也不止是一家商业公司,它的决策也需要通过美国本土的审批。")); 29 | newsList.add(new News(News.TYPE_NONE_PICTURE,AUTHOR,"高管集体离职致Twitter股价开盘跳水逾6%","新浪科技讯 北京时间1月26日早间消息,在5名重要高管离职后,Twitter股价周一开盘下跌逾6个百分点。此次离职的包括该公司工程副总裁亚历克斯·罗特尔(Alex Roettter)、产品副总裁凯文·维尔(Kevin Weil)、媒体主管凯蒂·斯坦顿(Katie Stanton)、人力资源副总裁布莱恩·施佩尔(Brian Schipper)和Vine主管詹森·托夫(Jason Toff)。")); 30 | newsList.add(new News(News.TYPE_SINGLE_PICTURE,AUTHOR,"动物弱肉强食惊心动魄捕食:雄狮遭水牛追赶","当地时间2015年2月4日,一头雄狮在一群水牛的追赶下居然也会落荒而逃。虽然被成为是森林之王,但这只明显更像是一只受到惊吓的小猫。一开始两头狮子在草地上休息,突然,水牛发现了敌人的身影,便一同扑上去追赶,狮子吓得立刻掉头逃走了。","http://www.sinaimg.cn/dy/slidenews/5_img/2016_04/453_74575_776168.jpg")); 31 | newsList.add(new News(News.TYPE_SINGLE_PICTURE,AUTHOR,"非洲变色龙捕食甲虫瞬间:伸出长舌头黏住吞下","摄影师托马斯•惠滕(Thomas Whetten)在纳米比亚西部的纳米布沙漠(Namib Desert)拍摄到一组纳马夸变色龙从后方捕食毫无防备的甲虫的照片。","http://www.sinaimg.cn/dy/slidenews/5_img/2016_04/453_74569_384735.jpg")); 32 | newsList.add(new News(News.TYPE_SINGLE_PICTURE,AUTHOR,"潜水员与大白鲨亲密接触上演惊魂时刻","近日,在墨西哥瓜达卢佩圣母岛海岸,一名潜水员通过向大白鲨投喂食物将其引诱至笼子边,将他的手臂伸出,轻轻抚摸了大白鲨的鼻子。这一惊魂时刻被摄影师记录了下来。","http://www.sinaimg.cn/dy/slidenews/5_img/2016_04/453_74552_646977.jpg")); 33 | newsList.add(new News(News.TYPE_MULTIPLE_PICTURE,AUTHOR,"网曝富士康郑州工厂发生火灾 现场黑烟滚滚","火灾发生地点位于新郑富士康02区,当时消防人员已经到位,随后大火被扑灭。目前尚不知道起火原因,人员伤亡情况也未公布,暂不清楚是否会对部分手机数码产品的供货造成影响。目前尚未有富士康方面的公开回应。","http://n.sinaimg.cn/translate/20160125/q0v5-fxnuwcr7470993.jpg;http://n.sinaimg.cn/translate/20160125/jMrS-fxnuwfi3015757.jpg")); 34 | newsList.add(new News(News.TYPE_MULTIPLE_PICTURE,AUTHOR,"“汪星人”偷偷溜进半程马拉松还混到名次","话说最近在美国阿拉巴马州的一个小镇发生了件神奇的事。Ludivine是只2岁半的猎犬,周六早晨她的主人照例放它出去溜达。万万没想到,在这户人家附近正举行一场半程马拉松,这狗一溜达就跑到了马拉松起点附近,默默和选手们一起","http://www.sinaimg.cn/dy/slidenews/1_img/2016_04/2841_656940_447365.jpg;http://www.sinaimg.cn/dy/slidenews/1_img/2016_04/2841_656941_891976.jpg")); 35 | newsList.add(new News(News.TYPE_NONE_PICTURE,AUTHOR,"清华控股将收购两家半导体制造公司","北京时间1月26日早间消息,清华控股董事长徐井宏本周在达沃斯世界经济论坛上表示,清华控股计划收购两家半导体制造公司。此举表明,中国计划进一步加强半导体制造技术。投行Stifel Nicolaus分析师阿隆·雷克斯(Aaron Rakers)表示:“获得政府支持的清华控股2016年将投资2000亿元人民币,用于并购活动。”")); 36 | newsList.add(new News(News.TYPE_NONE_PICTURE,AUTHOR,"马斯克:油价下跌正在冲击电动汽车市场","马斯克周一表示:“我认为,整个行业肯定受到了低油价的冲击。这从经济性上来说是合理的。”近期,油价下跌正在改变美国汽车市场的格局,皮卡和SUV等“油老虎”车型的销量去年出现增长。今年以来,油价的跌势仍在延续,而上周则创下12年以来最低纪录。")); 37 | newsList.add(new News(News.TYPE_NONE_PICTURE,AUTHOR,"圆通延吉店老板跑路 大量快件滞留","临近春节,又一家快递加盟公司停摆:圆通延吉公司老板被曝拖欠员工工资,疑似跑路,大量快件堆放在网点外,无人管理。去年“双11”至今,不仅是圆通,加盟制快递企业“四通一达”其余的申通、中通、百世汇通和韵达也均被媒体曝出部分加盟网点出现疑似停工、倒闭等情况。伴随着电商的红火,借势而盛的加盟制快递企业,为何在近期接连遭遇“寒潮”?快递企业又该如何加强管理和制度创新,提供更好的服务呢?")); 38 | } 39 | return newsList; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /commonadapter-sample/src/main/java/com/github/zeng1990java/commonadapter_sample/widget/CustomLoadMoreView.java: -------------------------------------------------------------------------------- 1 | package com.github.zeng1990java.commonadapter_sample.widget; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.FrameLayout; 6 | import android.widget.ProgressBar; 7 | import android.widget.TextView; 8 | 9 | import com.github.zeng1990java.commonadapter.LoadMoreView; 10 | 11 | /** 12 | * $desc 13 | * 14 | * @author zxb 15 | * @date 16/8/6 下午9:41 16 | */ 17 | public class CustomLoadMoreView extends FrameLayout implements LoadMoreView{ 18 | 19 | LoadState mLoadState = LoadState.IDLE; 20 | 21 | private TextView mLoadText; 22 | private ProgressBar mProgressBar; 23 | 24 | public CustomLoadMoreView(Context context, AttributeSet attrs) { 25 | super(context, attrs); 26 | } 27 | 28 | @Override 29 | protected void onFinishInflate() { 30 | super.onFinishInflate(); 31 | mLoadText = (TextView) findViewById(com.github.zeng1990java.commonadapter.R.id.loading_text); 32 | mProgressBar = (ProgressBar) findViewById(com.github.zeng1990java.commonadapter.R.id.loading_progress); 33 | } 34 | 35 | @Override 36 | public LoadState getLoadState() { 37 | return mLoadState; 38 | } 39 | 40 | @Override 41 | public void setLoadState(LoadState loadState) { 42 | mLoadState = loadState; 43 | if (mLoadState == LoadState.ERROR){ 44 | mLoadText.setText("自定义加载失败"); 45 | mProgressBar.setVisibility(GONE); 46 | }else { 47 | mLoadText.setText("自定义加载更多..."); 48 | mProgressBar.setVisibility(VISIBLE); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /commonadapter-sample/src/main/res/drawable/item_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /commonadapter-sample/src/main/res/layout/activity_horizontal.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 13 | -------------------------------------------------------------------------------- /commonadapter-sample/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 |