├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── findbugs-idea.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── CommonAdapter.iml ├── LICENSE ├── README.md ├── adapter ├── .gitignore ├── adapter.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── simple │ │ └── com │ │ └── commonadapter │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── simple │ └── commonadapter │ ├── ListViewAdapter.java │ ├── RecyclerAdapter.java │ └── viewholders │ ├── GodViewHolder.java │ ├── RecyclerViewHolder.java │ └── ViewHolderImpl.java ├── build.gradle ├── demo ├── .gitignore ├── build.gradle ├── demo.iml ├── libs │ └── universal-image-loader-1.9.5.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── simple │ │ └── com │ │ └── demo │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── simple │ │ │ └── com │ │ │ └── demo │ │ │ ├── ImageItem.java │ │ │ ├── Images.java │ │ │ ├── MainActivity.java │ │ │ ├── MultiImageActivity.java │ │ │ └── widgets │ │ │ └── MultiImageView.java │ └── res │ │ ├── drawable │ │ ├── big_smile.png │ │ ├── ic_launcher.png │ │ └── imageloading.9.png │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_multi.xml │ │ ├── content_main.xml │ │ ├── list_item_type_1.xml │ │ ├── list_item_type_2.xml │ │ └── multi_image_item.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 │ └── test │ └── java │ └── simple │ └── com │ └── demo │ └── ExampleUnitTest.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images └── adapter.gif └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | /captures 8 | # Built application files 9 | *.apk 10 | *.ap_ 11 | 12 | # Files for the Dalvik VM 13 | *.dex 14 | 15 | # Java class files 16 | *.class 17 | 18 | # Generated files 19 | bin/ 20 | gen/ 21 | 22 | # Gradle files 23 | .gradle/ 24 | build/ 25 | /*/build/ 26 | 27 | # Local configuration file (sdk path, etc) 28 | local.properties 29 | 30 | # Proguard folder generated by Eclipse 31 | proguard/ 32 | 33 | # Log Files 34 | *.log 35 | >>>>>>> origin/master 36 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | CommonAdapter -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/findbugs-idea.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 32 | 203 | 216 | 225 | 226 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | 1.8 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CommonAdapter.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 39 | 210 | 223 | 224 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Mr.Simple 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android Common Adapter 2 | 3 | > 该库用于简化AbsListView类型与RecyclerView的Adapter构建,在ListViewAdapter和RecyclerAdapter封装了固定的业务逻辑,使得用户只需要实现变化的部分即可,简化代码,避免重复的模板代码。 4 | > 5 | > 该库的接口参考了[base-adapter-helper](https://github.com/JoanZapata/base-adapter-helper),在此基础上添加了RecyclerView Adapter的支持。两种类型的Adapter之间通过桥接模式简化代码,参考[ViewHolderImpl](https://github.com/bboyfeiyu/commonadapter/blob/master/adapter/src/main/java/com/simple/commonadapter/viewholders/ViewHolderImpl.java)。 6 | 7 | ## 添加Gradle依赖 8 | 9 | 在项目的build.gradle中添加上如下依赖: 10 | 11 | ```xml 12 | 13 | dependencies { 14 | // 其他依赖 15 | 16 | // Common Adapter的依赖 17 | compile 'org.simple:adapter:1.0.1' 18 | } 19 | ``` 20 | 21 | ## 1、使用代码 22 | 23 | ```java 24 | /** 25 | * 初始化ListView 26 | */ 27 | private void initListView() { 28 | ListView listView = (ListView) findViewById(R.id.listview); 29 | final ListViewAdapter adapter = new ListViewAdapter(R.layout.list_item_type_1) { 30 | @Override 31 | protected void onBindData(GodViewHolder viewHolder, int position, String item) { 32 | 33 | viewHolder 34 | .setText(R.id.textview, item) // 设置文本内容 35 | .setImageResource(R.id.imageview, R.drawable.big_smile) ; // 设置图片资源 36 | } 37 | }; 38 | // 添加数据 39 | adapter.addItems(mockDatas()); 40 | listView.setAdapter(adapter); 41 | // 设置ListView的点击事件 42 | listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 43 | @Override 44 | public void onItemClick(AdapterView parent, View view, int position, long id) { 45 | Toast.makeText(MainActivity.this, "Click List : " + adapter.getItem(position), Toast.LENGTH_SHORT).show(); 46 | } 47 | }); 48 | } 49 | ``` 50 | 51 | 针对于AbsListView类族的组件需要使用ListViewAdapter类型的Adapter,泛型参数就是单个实体类的数据类型。在构造ListViewAdapter对象时覆写onBindData函数完成数据的绑定即可。GodViewHolder中包含了各类View属性的设置,具体请直接查看GodViewHolder中的setter函数。 52 | 53 | 对于RecyclerView则需要使用RecyclerAdapter,使用方式与ListViewAdapter类似,示例代码如下所示。 54 | 55 | ```java 56 | /** 57 | * 初始化RecyclerView 58 | */ 59 | private void initRecyclerView() { 60 | RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview); 61 | // 线性 62 | recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this)); 63 | 64 | // 初始化adapter 65 | final RecyclerAdapter adapter = new RecyclerAdapter(R.layout.list_item_type_1, mockDatas()) { 66 | @Override 67 | protected void onBindData(RecyclerViewHolder viewHolder, int position, String item) { 68 | viewHolder.setText(R.id.textview, item); 69 | ImageView imageView = viewHolder.findViewById(R.id.imageview); 70 | Glide 71 | .with(viewHolder.getContext()) 72 | .load("http://img4.duitang.com/uploads/blog/201402/19/20140219232639_Cda2j.thumb.600_0.jpeg") 73 | .into(imageView); 74 | } 75 | 76 | // 如果有多个布局,那么覆写getItemViewType与getItemLayout即可 77 | @Override 78 | public int getItemViewType(int position) { 79 | return position % 5 == 0 ? 2 : 1; 80 | } 81 | 82 | @Override 83 | protected int getItemLayout(int type) { 84 | if (type == 2) { 85 | return R.layout.list_item_type_2; 86 | } 87 | return R.layout.list_item_type_1; 88 | } 89 | }; 90 | 91 | // 设置RecyclerView的点击事件 92 | adapter.setOnItemClickListener(new RecyclerAdapter.OnItemClickListener() { 93 | @Override 94 | public void onItemClick(int position) { 95 | Toast.makeText(MainActivity.this, "Click Recycler : " 96 | + adapter.getItem(position), Toast.LENGTH_SHORT).show(); 97 | } 98 | }); 99 | recyclerView.setAdapter(adapter); 100 | } 101 | ``` 102 | 103 | 在使用Common Adapter时不需要担心数据源发生改变导致列表数据不更新的问题,因为Adapter基类中将数据集设置为final,所有的数据都会添加到该数据集中;在增加、减少数据时也不需要调用notifyDataSetChanged,只需要调用Adapter对应的的addItem或者remove函数即可。 104 | 105 | ## 2、效果 106 | 107 | ![](./images/adapter.gif) 108 | 109 | -------------------------------------------------------------------------------- /adapter/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /adapter/adapter.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 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 | 121 | 292 | 305 | 306 | -------------------------------------------------------------------------------- /adapter/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | apply plugin: 'com.github.dcendents.android-maven' 4 | apply plugin: 'com.jfrog.bintray' 5 | // This is the library version used when deploying the artifact 6 | 7 | 8 | // release command : ./gradlew bintrayUpload 9 | version = "1.0.1" 10 | 11 | android { 12 | compileSdkVersion 22 13 | buildToolsVersion "22.0.1" 14 | 15 | defaultConfig { 16 | minSdkVersion 10 17 | targetSdkVersion 22 18 | versionCode 2 19 | versionName "1.0.1" 20 | } 21 | buildTypes { 22 | release { 23 | minifyEnabled false 24 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 25 | } 26 | } 27 | } 28 | 29 | dependencies { 30 | compile fileTree(dir: 'libs', include: ['*.jar']) 31 | testCompile 'junit:junit:4.12' 32 | 33 | compile 'com.android.support:recyclerview-v7:+' 34 | } 35 | 36 | 37 | def siteUrl = 'https://github.com/bboyfeiyu/commonadapter' // 项目的主页 38 | def gitUrl = 'git@github.com:bboyfeiyu/commonadapter.git' // Git仓库的url 39 | group = "org.simple" // Maven Group ID for the artifact,一般填你唯一的包名 40 | install { 41 | repositories.mavenInstaller { 42 | // This generates POM.xml with proper parameters 43 | pom { 44 | project { 45 | packaging 'jar' 46 | // Add your description here 47 | name 'Android Common Adapter' //项目描述 48 | url siteUrl 49 | // Set your license 50 | licenses { 51 | license { 52 | name 'The Apache Software License, Version 2.0' 53 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 54 | } 55 | } 56 | developers { 57 | developer { 58 | id 'bboyfeiyu' //填写的一些基本信息 59 | name 'MrSimple' 60 | email 'bboyfeiyu@gmail.com' 61 | } 62 | } 63 | scm { 64 | connection gitUrl 65 | developerConnection gitUrl 66 | url siteUrl 67 | } 68 | } 69 | } 70 | } 71 | } 72 | task sourcesJar(type: Jar) { 73 | from android.sourceSets.main.java.srcDirs 74 | classifier = 'sources' 75 | } 76 | task javadoc(type: Javadoc) { 77 | source = android.sourceSets.main.java.srcDirs 78 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 79 | } 80 | task javadocJar(type: Jar, dependsOn: javadoc) { 81 | classifier = 'javadoc' 82 | from javadoc.destinationDir 83 | } 84 | artifacts { 85 | archives javadocJar 86 | archives sourcesJar 87 | } 88 | Properties properties = new Properties() 89 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) 90 | bintray { 91 | user = properties.getProperty("bintray.user") 92 | key = properties.getProperty("bintray.apikey") 93 | configurations = ['archives'] 94 | pkg { 95 | repo = "maven" 96 | name = "AndroidCommonAdapter" //发布到JCenter上的项目名字 97 | websiteUrl = siteUrl 98 | vcsUrl = gitUrl 99 | licenses = ["Apache-2.0"] 100 | publish = true 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /adapter/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 /Applications/dev/adt-bundle-mac-x86_64-20131030/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 | -------------------------------------------------------------------------------- /adapter/src/androidTest/java/simple/com/commonadapter/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package simple.com.commonadapter; 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 | } -------------------------------------------------------------------------------- /adapter/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/simple/commonadapter/ListViewAdapter.java: -------------------------------------------------------------------------------- 1 | 2 | package com.simple.commonadapter; 3 | 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.BaseAdapter; 7 | 8 | import com.simple.commonadapter.viewholders.GodViewHolder; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | 14 | /** 15 | * 适用于ListView的 通用 Adapter 16 | * 17 | * Created by mrsimple on 25/9/15. 18 | */ 19 | public abstract class ListViewAdapter extends BaseAdapter { 20 | /** 21 | * 数据集 22 | */ 23 | protected final List mDataSet = new ArrayList<>(); 24 | /** 25 | * Item Layout 26 | */ 27 | private int mItemLayoutId; 28 | 29 | /** 30 | * 31 | * @param layoutId 32 | */ 33 | public ListViewAdapter(int layoutId) { 34 | mItemLayoutId = layoutId; 35 | } 36 | 37 | public ListViewAdapter(int layoutId, List datas) { 38 | mItemLayoutId = layoutId; 39 | mDataSet.addAll(datas) ; 40 | } 41 | 42 | /** 43 | * @param item 44 | */ 45 | public void addItem(D item) { 46 | mDataSet.add(item); 47 | notifyDataSetChanged(); 48 | } 49 | 50 | /** 51 | * @param items 52 | */ 53 | public void addItems(List items) { 54 | mDataSet.addAll(items); 55 | notifyDataSetChanged(); 56 | } 57 | 58 | /** 59 | * @param item 60 | */ 61 | public void addItemToHead(D item) { 62 | mDataSet.add(0, item); 63 | notifyDataSetChanged(); 64 | } 65 | 66 | /** 67 | * @param items 68 | */ 69 | public void addItemsToHead(List items) { 70 | mDataSet.addAll(0, items); 71 | notifyDataSetChanged(); 72 | } 73 | 74 | /** 75 | * @param position 76 | */ 77 | public void remove(int position) { 78 | mDataSet.remove(position); 79 | notifyDataSetChanged(); 80 | } 81 | 82 | /** 83 | * @param item 84 | */ 85 | public void remove(D item) { 86 | mDataSet.remove(item); 87 | notifyDataSetChanged(); 88 | } 89 | 90 | /** 91 | * clear all data 92 | */ 93 | public void clear() { 94 | mDataSet.clear(); 95 | notifyDataSetChanged(); 96 | } 97 | 98 | /** 99 | * @return 100 | */ 101 | @Override 102 | public int getCount() { 103 | return mDataSet.size(); 104 | } 105 | 106 | /** 107 | * @param position 108 | * @return 109 | */ 110 | @Override 111 | public D getItem(int position) { 112 | return mDataSet.get(position); 113 | } 114 | 115 | /** 116 | * @param position 117 | * @return 118 | */ 119 | @Override 120 | public long getItemId(int position) { 121 | return position; 122 | } 123 | 124 | /** 125 | * 根据View Type返回布局资源 126 | * 127 | * @param type 128 | * @return 129 | */ 130 | protected int getItemLayout(int type) { 131 | return mItemLayoutId; 132 | } 133 | 134 | /** 135 | * 封装getView逻辑,将根据viewType获取布局资源、解析布局资源、创建ViewHolder等逻辑封装起来,简化使用流程 136 | * 137 | * @param position 138 | * @param convertView 139 | * @param parent 140 | * @return 141 | */ 142 | @Override 143 | public View getView(int position, View convertView, ViewGroup parent) { 144 | int viewType = getItemViewType( position ) ; 145 | GodViewHolder viewHolder = GodViewHolder.get(convertView, parent, getItemLayout(viewType)); 146 | // 绑定数据 147 | onBindData(viewHolder, position, getItem(position)); 148 | return viewHolder.getItemView(); 149 | } 150 | 151 | /** 152 | * 绑定数据到Item View上 153 | * 154 | * @param viewHolder 155 | * @param position 数据的位置 156 | * @param item 数据项 157 | */ 158 | protected abstract void onBindData(GodViewHolder viewHolder, int position, D item); 159 | 160 | } 161 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/simple/commonadapter/RecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.simple.commonadapter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import com.simple.commonadapter.viewholders.RecyclerViewHolder; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * 用于RecyclerView的Adapter 16 | * 17 | * Created by mrsimple on 25/9/15. 18 | */ 19 | public abstract class RecyclerAdapter 20 | extends RecyclerView.Adapter { 21 | /** 22 | * 数据集 23 | */ 24 | protected final List mDataSet = new ArrayList<>(); 25 | /** 26 | * 单击事件 27 | */ 28 | protected OnItemClickListener mOnItemClickListener; 29 | /** 30 | * Item Layout的资源id 31 | */ 32 | private int mItemLayoutId; 33 | 34 | /** 35 | * 36 | * @param layoutId 布局id 37 | */ 38 | public RecyclerAdapter(int layoutId) { 39 | mItemLayoutId = layoutId ; 40 | } 41 | 42 | /** 43 | * 44 | * @param layoutId 布局id 45 | * @param datas 数据集 46 | */ 47 | public RecyclerAdapter(int layoutId, List datas) { 48 | mItemLayoutId = layoutId ; 49 | addItems( datas ); 50 | } 51 | 52 | /** 53 | * 追加单个数据 54 | * 55 | * @param item 56 | */ 57 | public void addItem(D item) { 58 | mDataSet.add(item); 59 | notifyDataSetChanged(); 60 | } 61 | 62 | 63 | /** 64 | * 追加数据集 65 | * 66 | * @param items 67 | */ 68 | public void addItems(List items) { 69 | mDataSet.addAll(items); 70 | notifyDataSetChanged(); 71 | } 72 | 73 | /** 74 | * 添加单个数据到列表头部 75 | * 76 | * @param item 77 | */ 78 | public void addItemToHead(D item) { 79 | mDataSet.add(0, item); 80 | notifyDataSetChanged(); 81 | } 82 | 83 | /** 84 | * 添加数据集到列表头部 85 | * 86 | * @param items 87 | */ 88 | public void addItemsToHead(List items) { 89 | mDataSet.addAll(0, items); 90 | notifyDataSetChanged(); 91 | } 92 | 93 | /** 94 | * 移除某个数据 95 | * 96 | * @param position 97 | */ 98 | public void remove(int position) { 99 | mDataSet.remove(position); 100 | notifyDataSetChanged(); 101 | } 102 | 103 | /** 104 | * 移除某个数据项 105 | * 106 | * @param item 107 | */ 108 | public void remove(D item) { 109 | mDataSet.remove(item); 110 | notifyDataSetChanged(); 111 | } 112 | 113 | /** 114 | * clear all data 115 | */ 116 | public void clear() { 117 | mDataSet.clear(); 118 | notifyDataSetChanged(); 119 | } 120 | 121 | /** 122 | * 获取指定位置的数据项 123 | * 124 | * @param position 125 | * @return 126 | */ 127 | public D getItem(int position) { 128 | return mDataSet.get(position); 129 | } 130 | 131 | @Override 132 | public int getItemCount() { 133 | return mDataSet.size(); 134 | } 135 | 136 | @Override 137 | public void onBindViewHolder(RecyclerViewHolder holder, int position) { 138 | final D item = getItem(position); 139 | // 绑定数据 140 | onBindData(holder, position, item); 141 | // 设置单击事件 142 | setupItemClickListener(holder, position); 143 | } 144 | 145 | /** 146 | * 解析布局资源 147 | * 148 | * @param viewGroup 149 | * @param viewType 150 | * @return 151 | */ 152 | protected View inflateItemView(ViewGroup viewGroup, int viewType) { 153 | int itemLayout = getItemLayout(viewType); 154 | Context context = viewGroup.getContext() ; 155 | return LayoutInflater.from(context).inflate(itemLayout, 156 | viewGroup, false); 157 | } 158 | 159 | @Override 160 | public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 161 | return new RecyclerViewHolder(inflateItemView(parent, viewType)) ; 162 | } 163 | 164 | /** 165 | * 根据Type返回布局资源 166 | * 167 | * @param type 168 | * @return 169 | */ 170 | protected int getItemLayout(int type) { 171 | return mItemLayoutId ; 172 | } 173 | 174 | 175 | /** 176 | * 绑定数据到Item View上 177 | * 178 | * @param viewHolder 179 | * @param position 数据的位置 180 | * @param item 数据项 181 | */ 182 | protected abstract void onBindData(RecyclerViewHolder viewHolder, int position, D item); 183 | 184 | 185 | /** 186 | * @param viewHolder 187 | * @param position 188 | */ 189 | protected void setupItemClickListener(RecyclerViewHolder viewHolder, final int position) { 190 | viewHolder.itemView.setOnClickListener(new View.OnClickListener() { 191 | @Override 192 | public void onClick(View v) { 193 | if (mOnItemClickListener != null) { 194 | mOnItemClickListener.onItemClick(position); 195 | } 196 | } 197 | }); 198 | } 199 | 200 | /** 201 | * 设置点击事件 202 | * 203 | * @param listener 204 | */ 205 | public void setOnItemClickListener(OnItemClickListener listener) { 206 | this.mOnItemClickListener = listener; 207 | } 208 | 209 | 210 | /** 211 | * 点击事件Listener 212 | */ 213 | public static interface OnItemClickListener { 214 | void onItemClick(int position); 215 | } 216 | 217 | } 218 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/simple/commonadapter/viewholders/GodViewHolder.java: -------------------------------------------------------------------------------- 1 | package com.simple.commonadapter.viewholders; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.Context; 5 | import android.graphics.Bitmap; 6 | import android.graphics.drawable.Drawable; 7 | import android.net.Uri; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.AdapterView; 12 | 13 | /** 14 | * Created by mrsimple on 29/9/15. 15 | */ 16 | public class GodViewHolder { 17 | /** 18 | * ViewHolder实现类,桥接模式适配AbsListView与RecyclerView的二维变化 19 | */ 20 | ViewHolderImpl mHolderImpl ; 21 | 22 | 23 | /** 24 | * @param itemView 25 | */ 26 | GodViewHolder(View itemView) { 27 | mHolderImpl = new ViewHolderImpl( itemView ) ; 28 | } 29 | 30 | 31 | /** 32 | * @param viewId 33 | * @param 34 | * @return 35 | */ 36 | public T findViewById(int viewId) { 37 | return mHolderImpl.findViewById(viewId); 38 | } 39 | 40 | public Context getContext() { 41 | return mHolderImpl.mItemView.getContext() ; 42 | } 43 | 44 | /** 45 | * 获取GodViewHolder 46 | * 47 | * @param convertView 48 | * @param parent 49 | * @param layoutId 50 | * @return 51 | */ 52 | public static GodViewHolder get(View convertView, ViewGroup parent, int layoutId) { 53 | GodViewHolder viewHolder = null; 54 | if (convertView == null) { 55 | convertView = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false); 56 | viewHolder = new GodViewHolder(convertView); 57 | convertView.setTag(viewHolder); 58 | } else { 59 | viewHolder = (GodViewHolder) convertView.getTag(); 60 | } 61 | 62 | return viewHolder; 63 | } 64 | 65 | 66 | public View getItemView() { 67 | return mHolderImpl.getItemView(); 68 | } 69 | 70 | public GodViewHolder setText(int viewId, int stringId) { 71 | mHolderImpl.setText(viewId, stringId); 72 | return this; 73 | } 74 | 75 | public GodViewHolder setText(int viewId, String text) { 76 | mHolderImpl.setText(viewId, text); 77 | return this; 78 | } 79 | 80 | public GodViewHolder setTextColor(int viewId, int color) { 81 | mHolderImpl.setTextColor(viewId, color); 82 | return this; 83 | } 84 | 85 | /** 86 | * @param viewId 87 | * @param color 88 | */ 89 | public GodViewHolder setBackgroundColor(int viewId, int color) { 90 | mHolderImpl.setBackgroundColor(viewId, color); 91 | return this; 92 | } 93 | 94 | 95 | /** 96 | * @param viewId 97 | * @param resId 98 | */ 99 | public GodViewHolder setBackgroundResource(int viewId, int resId) { 100 | mHolderImpl.setBackgroundResource(viewId, resId); 101 | return this; 102 | } 103 | 104 | 105 | /** 106 | * @param viewId 107 | * @param drawable 108 | */ 109 | public GodViewHolder setBackgroundDrawable(int viewId, Drawable drawable) { 110 | mHolderImpl.setBackgroundDrawable(viewId, drawable); 111 | return this; 112 | } 113 | 114 | /** 115 | * @param viewId 116 | * @param drawable 117 | */ 118 | @TargetApi(16) 119 | public GodViewHolder setBackground(int viewId, Drawable drawable) { 120 | mHolderImpl.setBackground(viewId, drawable); 121 | return this; 122 | } 123 | 124 | 125 | public GodViewHolder setImageBitmap(int viewId, Bitmap bitmap) { 126 | mHolderImpl.setImageBitmap(viewId, bitmap); 127 | return this; 128 | } 129 | 130 | 131 | public GodViewHolder setImageResource(int viewId, int resId) { 132 | mHolderImpl.setImageResource(viewId, resId); 133 | return this; 134 | } 135 | 136 | public GodViewHolder setImageDrawable(int viewId, Drawable drawable) { 137 | mHolderImpl.setImageDrawable(viewId, drawable); 138 | return this; 139 | } 140 | 141 | 142 | public GodViewHolder setImageDrawable(int viewId, Uri uri) { 143 | mHolderImpl.setImageDrawable(viewId, uri); 144 | return this; 145 | } 146 | 147 | 148 | @TargetApi(16) 149 | public GodViewHolder setImageAlpha(int viewId, int alpha) { 150 | mHolderImpl.setImageAlpha(viewId, alpha); 151 | return this; 152 | } 153 | 154 | public GodViewHolder setChecked(int viewId, boolean checked) { 155 | mHolderImpl.setChecked(viewId, checked); 156 | return this; 157 | } 158 | 159 | 160 | public GodViewHolder setProgress(int viewId, int progress) { 161 | mHolderImpl.setProgress(viewId, progress); 162 | return this; 163 | } 164 | 165 | public GodViewHolder setProgress(int viewId, int progress, int max) { 166 | mHolderImpl.setProgress(viewId, progress, max); 167 | return this; 168 | } 169 | 170 | public GodViewHolder setMax(int viewId, int max) { 171 | mHolderImpl.setMax(viewId, max); 172 | return this; 173 | } 174 | 175 | public GodViewHolder setRating(int viewId, float rating) { 176 | mHolderImpl.setRating(viewId, rating); 177 | return this; 178 | } 179 | 180 | 181 | public GodViewHolder setRating(int viewId, float rating, int max) { 182 | mHolderImpl.setRating(viewId, rating, max); 183 | return this; 184 | } 185 | 186 | public GodViewHolder setVisibility(int viewId, int visible) { 187 | mHolderImpl.setVisibility(viewId, visible); 188 | return this; 189 | } 190 | 191 | public GodViewHolder setOnClickListener(int viewId, View.OnClickListener listener) { 192 | mHolderImpl.setOnClickListener(viewId, listener); 193 | return this; 194 | } 195 | 196 | public GodViewHolder setOnTouchListener(int viewId, View.OnTouchListener listener) { 197 | mHolderImpl.setOnTouchListener(viewId, listener); 198 | return this; 199 | } 200 | 201 | public GodViewHolder setOnLongClickListener(int viewId, View.OnLongClickListener listener) { 202 | mHolderImpl.setOnLongClickListener(viewId, listener); 203 | return this; 204 | } 205 | 206 | public GodViewHolder setOnItemClickListener(int viewId, AdapterView.OnItemClickListener listener) { 207 | mHolderImpl.setOnItemClickListener(viewId, listener); 208 | return this; 209 | } 210 | 211 | 212 | public GodViewHolder setOnItemLongClickListener(int viewId, AdapterView.OnItemLongClickListener listener) { 213 | mHolderImpl.setOnItemLongClickListener(viewId, listener); 214 | return this; 215 | } 216 | 217 | 218 | public GodViewHolder setOnItemSelectedClickListener(int viewId, AdapterView.OnItemSelectedListener listener) { 219 | mHolderImpl.setOnItemSelectedClickListener(viewId, listener); 220 | return this; 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/simple/commonadapter/viewholders/RecyclerViewHolder.java: -------------------------------------------------------------------------------- 1 | package com.simple.commonadapter.viewholders; 2 | import android.annotation.TargetApi; 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.drawable.Drawable; 6 | import android.net.Uri; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.View; 9 | import android.widget.AdapterView; 10 | 11 | /** 12 | * 适用于RecyclerView的ViewHolder 13 | * Created by mrsimple on 25/9/15. 14 | */ 15 | public class RecyclerViewHolder extends RecyclerView.ViewHolder { 16 | /** 17 | * ViewHolder实现类,桥接模式适配AbsListView与RecyclerView的二维变化 18 | */ 19 | ViewHolderImpl mHolderImpl ; 20 | 21 | /** 22 | * 23 | * @param itemView 24 | */ 25 | public RecyclerViewHolder(View itemView) { 26 | super(itemView); 27 | mHolderImpl = new ViewHolderImpl( itemView ) ; 28 | } 29 | 30 | public Context getContext() { 31 | return mHolderImpl.mItemView.getContext() ; 32 | } 33 | 34 | /** 35 | * @param viewId 36 | * @param 37 | * @return 38 | */ 39 | public T findViewById(int viewId) { 40 | return mHolderImpl.findViewById(viewId); 41 | } 42 | 43 | public View getItemView() { 44 | return mHolderImpl.getItemView(); 45 | } 46 | 47 | public RecyclerViewHolder setText(int viewId, int stringId) { 48 | mHolderImpl.setText(viewId, stringId); 49 | return this; 50 | } 51 | 52 | public RecyclerViewHolder setText(int viewId, String text) { 53 | mHolderImpl.setText(viewId, text); 54 | return this; 55 | } 56 | 57 | public RecyclerViewHolder setTextColor(int viewId, int color) { 58 | mHolderImpl.setTextColor(viewId, color); 59 | return this; 60 | } 61 | 62 | /** 63 | * @param viewId 64 | * @param color 65 | */ 66 | public RecyclerViewHolder setBackgroundColor(int viewId, int color) { 67 | mHolderImpl.setBackgroundColor(viewId, color); 68 | return this; 69 | } 70 | 71 | 72 | /** 73 | * @param viewId 74 | * @param resId 75 | */ 76 | public RecyclerViewHolder setBackgroundResource(int viewId, int resId) { 77 | mHolderImpl.setBackgroundResource(viewId, resId); 78 | return this; 79 | } 80 | 81 | 82 | /** 83 | * @param viewId 84 | * @param drawable 85 | */ 86 | public RecyclerViewHolder setBackgroundDrawable(int viewId, Drawable drawable) { 87 | mHolderImpl.setBackgroundDrawable(viewId, drawable); 88 | return this; 89 | } 90 | 91 | /** 92 | * @param viewId 93 | * @param drawable 94 | */ 95 | @TargetApi(16) 96 | public RecyclerViewHolder setBackground(int viewId, Drawable drawable) { 97 | mHolderImpl.setBackground(viewId, drawable); 98 | return this; 99 | } 100 | 101 | 102 | public RecyclerViewHolder setImageBitmap(int viewId, Bitmap bitmap) { 103 | mHolderImpl.setImageBitmap(viewId, bitmap); 104 | return this; 105 | } 106 | 107 | 108 | public RecyclerViewHolder setImageResource(int viewId, int resId) { 109 | mHolderImpl.setImageResource(viewId, resId); 110 | return this; 111 | } 112 | 113 | public RecyclerViewHolder setImageDrawable(int viewId, Drawable drawable) { 114 | mHolderImpl.setImageDrawable(viewId, drawable); 115 | return this; 116 | } 117 | 118 | 119 | public RecyclerViewHolder setImageDrawable(int viewId, Uri uri) { 120 | mHolderImpl.setImageDrawable(viewId, uri); 121 | return this; 122 | } 123 | 124 | 125 | @TargetApi(16) 126 | public RecyclerViewHolder setImageAlpha(int viewId, int alpha) { 127 | mHolderImpl.setImageAlpha(viewId, alpha); 128 | return this; 129 | } 130 | 131 | public RecyclerViewHolder setChecked(int viewId, boolean checked) { 132 | mHolderImpl.setChecked(viewId, checked); 133 | return this; 134 | } 135 | 136 | 137 | public RecyclerViewHolder setProgress(int viewId, int progress) { 138 | mHolderImpl.setProgress(viewId, progress); 139 | return this; 140 | } 141 | 142 | public RecyclerViewHolder setProgress(int viewId, int progress, int max) { 143 | mHolderImpl.setProgress(viewId, progress, max); 144 | return this; 145 | } 146 | 147 | public RecyclerViewHolder setMax(int viewId, int max) { 148 | mHolderImpl.setMax(viewId, max); 149 | return this; 150 | } 151 | 152 | public RecyclerViewHolder setRating(int viewId, float rating) { 153 | mHolderImpl.setRating(viewId, rating); 154 | return this; 155 | } 156 | 157 | public RecyclerViewHolder setVisibility(int viewId, int visible) { 158 | mHolderImpl.setVisibility(viewId, visible); 159 | return this; 160 | } 161 | 162 | 163 | public RecyclerViewHolder setRating(int viewId, float rating, int max) { 164 | mHolderImpl.setRating(viewId, rating, max); 165 | return this; 166 | } 167 | 168 | public RecyclerViewHolder setOnClickListener(int viewId, View.OnClickListener listener) { 169 | mHolderImpl.setOnClickListener(viewId, listener); 170 | return this; 171 | } 172 | 173 | public RecyclerViewHolder setOnTouchListener(int viewId, View.OnTouchListener listener) { 174 | mHolderImpl.setOnTouchListener(viewId, listener); 175 | return this; 176 | } 177 | 178 | 179 | public RecyclerViewHolder setOnLongClickListener(int viewId, View.OnLongClickListener listener) { 180 | mHolderImpl.setOnLongClickListener(viewId, listener); 181 | return this; 182 | } 183 | 184 | public RecyclerViewHolder setOnItemClickListener(int viewId, AdapterView.OnItemClickListener listener) { 185 | mHolderImpl.setOnItemClickListener(viewId, listener); 186 | return this; 187 | } 188 | 189 | 190 | public RecyclerViewHolder setOnItemLongClickListener(int viewId, AdapterView.OnItemLongClickListener listener) { 191 | mHolderImpl.setOnItemLongClickListener(viewId, listener); 192 | return this; 193 | } 194 | 195 | 196 | public RecyclerViewHolder setOnItemSelectedClickListener(int viewId, AdapterView.OnItemSelectedListener listener) { 197 | mHolderImpl.setOnItemSelectedClickListener(viewId, listener); 198 | return this; 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /adapter/src/main/java/com/simple/commonadapter/viewholders/ViewHolderImpl.java: -------------------------------------------------------------------------------- 1 | package com.simple.commonadapter.viewholders; 2 | 3 | import android.annotation.TargetApi; 4 | import android.graphics.Bitmap; 5 | import android.graphics.drawable.Drawable; 6 | import android.net.Uri; 7 | import android.util.SparseArray; 8 | import android.view.View; 9 | import android.widget.AdapterView; 10 | import android.widget.Checkable; 11 | import android.widget.ImageView; 12 | import android.widget.ProgressBar; 13 | import android.widget.RatingBar; 14 | import android.widget.TextView; 15 | 16 | /** 17 | * ViewHolder操作子视图的实现类 18 | * Created by mrsimple on 29/9/15. 19 | */ 20 | public class ViewHolderImpl { 21 | 22 | /** 23 | * 缓存子视图,key为view id, 值为View。 24 | */ 25 | private SparseArray mCahceViews = new SparseArray(); 26 | /** 27 | * Item View 28 | */ 29 | View mItemView; 30 | 31 | /** 32 | * @param itemView 33 | */ 34 | ViewHolderImpl(View itemView) { 35 | mItemView = itemView; 36 | } 37 | 38 | public View getItemView() { 39 | return mItemView; 40 | } 41 | 42 | /** 43 | * @param viewId 44 | * @param 45 | * @return 46 | */ 47 | public T findViewById(int viewId) { 48 | View target = mCahceViews.get(viewId); 49 | if (target == null) { 50 | target = mItemView.findViewById(viewId); 51 | mCahceViews.put(viewId, target); 52 | } 53 | return (T) target; 54 | } 55 | 56 | 57 | public void setText(int viewId, int stringId) { 58 | TextView textView = findViewById(viewId); 59 | textView.setText(stringId); 60 | } 61 | 62 | public void setText(int viewId, String text) { 63 | TextView textView = findViewById(viewId); 64 | textView.setText(text); 65 | } 66 | 67 | public void setTextColor(int viewId, int color) { 68 | TextView textView = findViewById(viewId); 69 | textView.setTextColor(color); 70 | } 71 | 72 | /** 73 | * @param viewId 74 | * @param color 75 | */ 76 | public void setBackgroundColor(int viewId, int color) { 77 | View target = findViewById(viewId); 78 | target.setBackgroundColor(color); 79 | 80 | } 81 | 82 | 83 | /** 84 | * @param viewId 85 | * @param resId 86 | */ 87 | public void setBackgroundResource(int viewId, int resId) { 88 | View target = findViewById(viewId); 89 | target.setBackgroundResource(resId); 90 | } 91 | 92 | 93 | /** 94 | * @param viewId 95 | * @param drawable 96 | */ 97 | public void setBackgroundDrawable(int viewId, Drawable drawable) { 98 | View target = findViewById(viewId); 99 | target.setBackgroundDrawable(drawable); 100 | } 101 | 102 | /** 103 | * @param viewId 104 | * @param drawable 105 | */ 106 | @TargetApi(16) 107 | public void setBackground(int viewId, Drawable drawable) { 108 | View target = findViewById(viewId); 109 | target.setBackground(drawable); 110 | } 111 | 112 | 113 | public void setImageBitmap(int viewId, Bitmap bitmap) { 114 | ImageView target = findViewById(viewId); 115 | target.setImageBitmap(bitmap); 116 | } 117 | 118 | 119 | public void setImageResource(int viewId, int resId) { 120 | ImageView target = findViewById(viewId); 121 | target.setImageResource(resId); 122 | } 123 | 124 | 125 | public void setImageDrawable(int viewId, Drawable drawable) { 126 | ImageView target = findViewById(viewId); 127 | target.setImageDrawable(drawable); 128 | } 129 | 130 | 131 | public void setImageDrawable(int viewId, Uri uri) { 132 | ImageView target = findViewById(viewId); 133 | target.setImageURI(uri); 134 | } 135 | 136 | 137 | @TargetApi(16) 138 | public void setImageAlpha(int viewId, int alpha) { 139 | ImageView target = findViewById(viewId); 140 | target.setImageAlpha(alpha); 141 | } 142 | 143 | public void setChecked(int viewId, boolean checked) { 144 | Checkable checkable = findViewById(viewId); 145 | checkable.setChecked(checked); 146 | } 147 | 148 | 149 | public void setProgress(int viewId, int progress) { 150 | ProgressBar view = findViewById(viewId); 151 | view.setProgress(progress); 152 | } 153 | 154 | public void setProgress(int viewId, int progress, int max) { 155 | ProgressBar view = findViewById(viewId); 156 | view.setMax(max); 157 | view.setProgress(progress); 158 | } 159 | 160 | public void setMax(int viewId, int max) { 161 | ProgressBar view = findViewById(viewId); 162 | view.setMax(max); 163 | } 164 | 165 | public void setRating(int viewId, float rating) { 166 | RatingBar view = findViewById(viewId); 167 | view.setRating(rating); 168 | } 169 | 170 | public void setVisibility(int viewId, int visible) { 171 | View view = findViewById(viewId); 172 | view.setVisibility(visible); 173 | } 174 | 175 | 176 | public void setRating(int viewId, float rating, int max) { 177 | RatingBar view = findViewById(viewId); 178 | view.setMax(max); 179 | view.setRating(rating); 180 | } 181 | 182 | public void setOnClickListener(int viewId, View.OnClickListener listener) { 183 | View view = findViewById(viewId); 184 | view.setOnClickListener(listener); 185 | 186 | } 187 | 188 | public void setOnTouchListener(int viewId, View.OnTouchListener listener) { 189 | View view = findViewById(viewId); 190 | view.setOnTouchListener(listener); 191 | } 192 | 193 | 194 | public void setOnLongClickListener(int viewId, View.OnLongClickListener listener) { 195 | View view = findViewById(viewId); 196 | view.setOnLongClickListener(listener); 197 | } 198 | 199 | public void setOnItemClickListener(int viewId, AdapterView.OnItemClickListener listener) { 200 | AdapterView view = findViewById(viewId); 201 | view.setOnItemClickListener(listener); 202 | } 203 | 204 | 205 | public void setOnItemLongClickListener(int viewId, AdapterView.OnItemLongClickListener listener) { 206 | AdapterView view = findViewById(viewId); 207 | view.setOnItemLongClickListener(listener); 208 | } 209 | 210 | 211 | public void setOnItemSelectedClickListener(int viewId, AdapterView.OnItemSelectedListener listener) { 212 | AdapterView view = findViewById(viewId); 213 | view.setOnItemSelectedListener(listener); 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /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:1.3.0' 9 | 10 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.0' 11 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' 12 | 13 | 14 | // NOTE: Do not place your application dependencies here; they belong 15 | // in the individual module build.gradle files 16 | } 17 | } 18 | 19 | allprojects { 20 | repositories { 21 | jcenter() 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } 28 | -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /demo/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "22.0.1" 6 | 7 | defaultConfig { 8 | applicationId "simple.com.demo" 9 | minSdkVersion 10 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 project(':adapter') 24 | compile fileTree(dir: 'libs', include: ['*.jar']) 25 | testCompile 'junit:junit:4.12' 26 | compile 'com.android.support:appcompat-v7:23.0.1' 27 | compile 'com.android.support:design:23.0.1' 28 | 29 | compile 'com.github.bumptech.glide:glide:3.6.1' 30 | 31 | compile files('libs/universal-image-loader-1.9.5.jar') 32 | 33 | // Common Adapter的依赖 34 | compile 'org.simple:adapter:1.0.1' 35 | } 36 | -------------------------------------------------------------------------------- /demo/demo.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 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 | 123 | 294 | 307 | 308 | -------------------------------------------------------------------------------- /demo/libs/universal-image-loader-1.9.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hehonghui/commonadapter/ba413357f7623351f53f426933e8af4bae036362/demo/libs/universal-image-loader-1.9.5.jar -------------------------------------------------------------------------------- /demo/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Applications/dev/adt-bundle-mac-x86_64-20131030/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /demo/src/androidTest/java/simple/com/demo/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package simple.com.demo; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /demo/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /demo/src/main/java/simple/com/demo/ImageItem.java: -------------------------------------------------------------------------------- 1 | package simple.com.demo; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Rect; 5 | 6 | /** 7 | * Created by mrsimple on 13/4/16. 8 | */ 9 | public class ImageItem { 10 | public String url = ""; 11 | public Rect rect = new Rect(); 12 | public Bitmap bitmap ; 13 | 14 | public int getWidth() { 15 | return rect.width() ; 16 | } 17 | 18 | public int getHeight() { 19 | return rect.height() ; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /demo/src/main/java/simple/com/demo/Images.java: -------------------------------------------------------------------------------- 1 | package simple.com.demo; 2 | 3 | /** 4 | * Created by mrsimple on 13/4/16. 5 | */ 6 | public class Images { 7 | 8 | public final static String[] imageThumbUrls = new String[] { 9 | "http://img.my.csdn.net/uploads/201407/26/1406383299_1976.jpg", 10 | "http://img.my.csdn.net/uploads/201407/26/1406383291_6518.jpg", 11 | "http://img.my.csdn.net/uploads/201407/26/1406383291_8239.jpg", 12 | "http://img.my.csdn.net/uploads/201407/26/1406383290_9329.jpg", 13 | "http://img.my.csdn.net/uploads/201407/26/1406383290_1042.jpg", 14 | "http://img.my.csdn.net/uploads/201407/26/1406383275_3977.jpg", 15 | "http://img.my.csdn.net/uploads/201407/26/1406383265_8550.jpg", 16 | "http://img.my.csdn.net/uploads/201407/26/1406383264_3954.jpg", 17 | "http://img.my.csdn.net/uploads/201407/26/1406383264_4787.jpg", 18 | "http://img.my.csdn.net/uploads/201407/26/1406383264_8243.jpg", 19 | "http://img.my.csdn.net/uploads/201407/26/1406383248_3693.jpg", 20 | "http://img.my.csdn.net/uploads/201407/26/1406383243_5120.jpg", 21 | "http://img.my.csdn.net/uploads/201407/26/1406383242_3127.jpg", 22 | "http://img.my.csdn.net/uploads/201407/26/1406383242_9576.jpg", 23 | "http://img.my.csdn.net/uploads/201407/26/1406383242_1721.jpg", 24 | "http://img.my.csdn.net/uploads/201407/26/1406383219_5806.jpg", 25 | "http://img.my.csdn.net/uploads/201407/26/1406383214_7794.jpg", 26 | "http://img.my.csdn.net/uploads/201407/26/1406383213_4418.jpg", 27 | "http://img.my.csdn.net/uploads/201407/26/1406383213_3557.jpg", 28 | "http://img.my.csdn.net/uploads/201407/26/1406383210_8779.jpg", 29 | "http://img.my.csdn.net/uploads/201407/26/1406383172_4577.jpg", 30 | "http://img.my.csdn.net/uploads/201407/26/1406383166_3407.jpg", 31 | "http://img.my.csdn.net/uploads/201407/26/1406383166_2224.jpg", 32 | "http://img.my.csdn.net/uploads/201407/26/1406383166_7301.jpg", 33 | "http://img.my.csdn.net/uploads/201407/26/1406383165_7197.jpg", 34 | "http://img.my.csdn.net/uploads/201407/26/1406383150_8410.jpg", 35 | "http://img.my.csdn.net/uploads/201407/26/1406383131_3736.jpg", 36 | "http://img.my.csdn.net/uploads/201407/26/1406383130_5094.jpg", 37 | "http://img.my.csdn.net/uploads/201407/26/1406383130_7393.jpg", 38 | "http://img.my.csdn.net/uploads/201407/26/1406383129_8813.jpg", 39 | "http://img.my.csdn.net/uploads/201407/26/1406383100_3554.jpg", 40 | "http://img.my.csdn.net/uploads/201407/26/1406383093_7894.jpg", 41 | "http://img.my.csdn.net/uploads/201407/26/1406383092_2432.jpg", 42 | "http://img.my.csdn.net/uploads/201407/26/1406383092_3071.jpg", 43 | "http://img.my.csdn.net/uploads/201407/26/1406383091_3119.jpg", 44 | "http://img.my.csdn.net/uploads/201407/26/1406383059_6589.jpg", 45 | "http://img.my.csdn.net/uploads/201407/26/1406383059_8814.jpg", 46 | "http://img.my.csdn.net/uploads/201407/26/1406383059_2237.jpg", 47 | "http://img.my.csdn.net/uploads/201407/26/1406383058_4330.jpg", 48 | "http://img.my.csdn.net/uploads/201407/26/1406383038_3602.jpg", 49 | "http://img.my.csdn.net/uploads/201407/26/1406382942_3079.jpg", 50 | "http://img.my.csdn.net/uploads/201407/26/1406382942_8125.jpg", 51 | "http://img.my.csdn.net/uploads/201407/26/1406382942_4881.jpg", 52 | "http://img.my.csdn.net/uploads/201407/26/1406382941_4559.jpg", 53 | "http://img.my.csdn.net/uploads/201407/26/1406382941_3845.jpg", 54 | "http://img.my.csdn.net/uploads/201407/26/1406382924_8955.jpg", 55 | "http://img.my.csdn.net/uploads/201407/26/1406382923_2141.jpg", 56 | "http://img.my.csdn.net/uploads/201407/26/1406382923_8437.jpg", 57 | "http://img.my.csdn.net/uploads/201407/26/1406382922_6166.jpg", 58 | "http://img.my.csdn.net/uploads/201407/26/1406382922_4843.jpg", 59 | "http://img.my.csdn.net/uploads/201407/26/1406382905_5804.jpg", 60 | "http://img.my.csdn.net/uploads/201407/26/1406382904_3362.jpg", 61 | "http://img.my.csdn.net/uploads/201407/26/1406382904_2312.jpg", 62 | "http://img.my.csdn.net/uploads/201407/26/1406382904_4960.jpg", 63 | "http://img.my.csdn.net/uploads/201407/26/1406382900_2418.jpg", 64 | "http://img.my.csdn.net/uploads/201407/26/1406382881_4490.jpg", 65 | "http://img.my.csdn.net/uploads/201407/26/1406382881_5935.jpg", 66 | "http://img.my.csdn.net/uploads/201407/26/1406382880_3865.jpg", 67 | "http://img.my.csdn.net/uploads/201407/26/1406382880_4662.jpg", 68 | "http://img.my.csdn.net/uploads/201407/26/1406382879_2553.jpg", 69 | "http://img.my.csdn.net/uploads/201407/26/1406382862_5375.jpg", 70 | "http://img.my.csdn.net/uploads/201407/26/1406382862_1748.jpg", 71 | "http://img.my.csdn.net/uploads/201407/26/1406382861_7618.jpg", 72 | "http://img.my.csdn.net/uploads/201407/26/1406382861_8606.jpg", 73 | "http://img.my.csdn.net/uploads/201407/26/1406382861_8949.jpg", 74 | "http://img.my.csdn.net/uploads/201407/26/1406382841_9821.jpg", 75 | "http://img.my.csdn.net/uploads/201407/26/1406382840_6603.jpg", 76 | "http://img.my.csdn.net/uploads/201407/26/1406382840_2405.jpg", 77 | "http://img.my.csdn.net/uploads/201407/26/1406382840_6354.jpg", 78 | "http://img.my.csdn.net/uploads/201407/26/1406382839_5779.jpg", 79 | "http://img.my.csdn.net/uploads/201407/26/1406382810_7578.jpg", 80 | "http://img.my.csdn.net/uploads/201407/26/1406382810_2436.jpg", 81 | "http://img.my.csdn.net/uploads/201407/26/1406382809_3883.jpg", 82 | "http://img.my.csdn.net/uploads/201407/26/1406382809_6269.jpg", 83 | "http://img.my.csdn.net/uploads/201407/26/1406382808_4179.jpg", 84 | "http://img.my.csdn.net/uploads/201407/26/1406382790_8326.jpg", 85 | "http://img.my.csdn.net/uploads/201407/26/1406382789_7174.jpg", 86 | "http://img.my.csdn.net/uploads/201407/26/1406382789_5170.jpg", 87 | "http://img.my.csdn.net/uploads/201407/26/1406382789_4118.jpg", 88 | "http://img.my.csdn.net/uploads/201407/26/1406382788_9532.jpg", 89 | "http://img.my.csdn.net/uploads/201407/26/1406382767_3184.jpg", 90 | "http://img.my.csdn.net/uploads/201407/26/1406382767_4772.jpg", 91 | "http://img.my.csdn.net/uploads/201407/26/1406382766_4924.jpg", 92 | "http://img.my.csdn.net/uploads/201407/26/1406382766_5762.jpg", 93 | "http://img.my.csdn.net/uploads/201407/26/1406382765_7341.jpg" 94 | }; 95 | } -------------------------------------------------------------------------------- /demo/src/main/java/simple/com/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package simple.com.demo; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.design.widget.FloatingActionButton; 6 | import android.support.design.widget.Snackbar; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.LinearLayoutManager; 9 | import android.support.v7.widget.RecyclerView; 10 | import android.support.v7.widget.Toolbar; 11 | import android.view.View; 12 | import android.widget.AdapterView; 13 | import android.widget.ImageView; 14 | import android.widget.ListView; 15 | import android.widget.Toast; 16 | 17 | import com.bumptech.glide.Glide; 18 | import com.simple.commonadapter.ListViewAdapter; 19 | import com.simple.commonadapter.RecyclerAdapter; 20 | import com.simple.commonadapter.viewholders.GodViewHolder; 21 | import com.simple.commonadapter.viewholders.RecyclerViewHolder; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | 27 | public class MainActivity extends AppCompatActivity { 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_main); 33 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 34 | setSupportActionBar(toolbar); 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, "Replace with your own action", Snackbar.LENGTH_LONG) 41 | .setAction("Action", null).show(); 42 | } 43 | }); 44 | 45 | initListView(); 46 | initRecyclerView(); 47 | 48 | startActivity(new Intent(this, MultiImageActivity.class)); 49 | } 50 | 51 | private List mockDatas() { 52 | List datas = new ArrayList<>(); 53 | for (int i = 0; i < 15; i++) { 54 | datas.add("user - " + i); 55 | } 56 | return datas; 57 | } 58 | 59 | 60 | /** 61 | * 初始化ListView 62 | */ 63 | private void initListView() { 64 | ListView listView = (ListView) findViewById(R.id.listview); 65 | final ListViewAdapter adapter = new ListViewAdapter(R.layout.list_item_type_1) { 66 | @Override 67 | protected void onBindData(GodViewHolder viewHolder, int position, String item) { 68 | 69 | viewHolder 70 | .setText(R.id.textview, item) // 设置文本内容 71 | .setImageResource(R.id.imageview, R.drawable.big_smile); // 设置图片资源 72 | } 73 | }; 74 | // 添加数据 75 | adapter.addItems(mockDatas()); 76 | listView.setAdapter(adapter); 77 | // 设置ListView的点击事件 78 | listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 79 | @Override 80 | public void onItemClick(AdapterView parent, View view, int position, long id) { 81 | Toast.makeText(MainActivity.this, "Click List : " + adapter.getItem(position), Toast.LENGTH_SHORT).show(); 82 | } 83 | }); 84 | } 85 | 86 | 87 | /** 88 | * 初始化RecyclerView 89 | */ 90 | private void initRecyclerView() { 91 | RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview); 92 | // 线性 93 | recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this)); 94 | 95 | // 初始化adapter 96 | final RecyclerAdapter adapter = new RecyclerAdapter(R.layout.list_item_type_1, mockDatas()) { 97 | @Override 98 | protected void onBindData(RecyclerViewHolder viewHolder, int position, String item) { 99 | viewHolder.setText(R.id.textview, item); 100 | ImageView imageView = viewHolder.findViewById(R.id.imageview); 101 | Glide 102 | .with(viewHolder.getContext()) 103 | .load("http://img4.duitang.com/uploads/blog/201402/19/20140219232639_Cda2j.thumb.600_0.jpeg") 104 | .into(imageView); 105 | } 106 | 107 | // 如果有多个布局,那么覆写getItemViewType与getItemLayout即可 108 | @Override 109 | public int getItemViewType(int position) { 110 | return position % 5 == 0 ? 2 : 1; 111 | } 112 | 113 | @Override 114 | protected int getItemLayout(int type) { 115 | if (type == 2) { 116 | return R.layout.list_item_type_2; 117 | } 118 | return R.layout.list_item_type_1; 119 | } 120 | }; 121 | 122 | // 设置RecyclerView的点击事件 123 | adapter.setOnItemClickListener(new RecyclerAdapter.OnItemClickListener() { 124 | @Override 125 | public void onItemClick(int position) { 126 | Toast.makeText(MainActivity.this, "Click Recycler : " 127 | + adapter.getItem(position), Toast.LENGTH_SHORT).show(); 128 | } 129 | }); 130 | recyclerView.setAdapter(adapter); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /demo/src/main/java/simple/com/demo/MultiImageActivity.java: -------------------------------------------------------------------------------- 1 | package simple.com.demo; 2 | 3 | import android.graphics.Bitmap; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.support.v7.widget.Toolbar; 9 | import android.widget.Toast; 10 | 11 | import com.nostra13.universalimageloader.core.DisplayImageOptions; 12 | import com.nostra13.universalimageloader.core.ImageLoader; 13 | import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; 14 | import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer; 15 | import com.nostra13.universalimageloader.core.download.BaseImageDownloader; 16 | import com.simple.commonadapter.RecyclerAdapter; 17 | import com.simple.commonadapter.viewholders.RecyclerViewHolder; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | import simple.com.demo.widgets.MultiImageView; 23 | 24 | 25 | public class MultiImageActivity extends AppCompatActivity { 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_multi); 31 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 32 | setSupportActionBar(toolbar); 33 | 34 | initRecyclerView(); 35 | configUniversalImageLoader(); 36 | } 37 | 38 | 39 | /** 40 | * 初始化UniversalImageLoader 41 | */ 42 | private void configUniversalImageLoader() { 43 | DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder() 44 | .cacheInMemory().cacheOnDisc() 45 | .bitmapConfig(Bitmap.Config.RGB_565) 46 | .displayer(new FadeInBitmapDisplayer(500)) 47 | .build(); 48 | 49 | ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this). 50 | diskCacheFileCount(500) 51 | .diskCacheSize(50 * 1024 * 1024). 52 | imageDownloader(new BaseImageDownloader(this, 10 * 1000, 20 * 1000)) 53 | .memoryCacheSize((int) Runtime.getRuntime().maxMemory() / 8) 54 | .defaultDisplayImageOptions(defaultOptions).build(); 55 | ImageLoader.getInstance().init(config); 56 | } 57 | 58 | 59 | List mImages; 60 | 61 | private List mockImages() { 62 | List datas = new ArrayList<>(); 63 | for (int i = 0; i < Images.imageThumbUrls.length / 3; i++) { 64 | ImageItem imageItem = new ImageItem(); 65 | imageItem.url = Images.imageThumbUrls[i]; 66 | datas.add(imageItem); 67 | } 68 | return datas; 69 | } 70 | 71 | /** 72 | * 初始化RecyclerView 73 | */ 74 | private void initRecyclerView() { 75 | RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview); 76 | // 线性 77 | recyclerView.setLayoutManager(new LinearLayoutManager(MultiImageActivity.this)); 78 | 79 | mImages = mockImages(); 80 | // 初始化adapter 81 | final RecyclerAdapter adapter = new RecyclerAdapter(R.layout.multi_image_item, mImages) { 82 | @Override 83 | protected void onBindData(RecyclerViewHolder viewHolder, int position, ImageItem item) { 84 | MultiImageView imageView = (MultiImageView) viewHolder.itemView; 85 | imageView.setImages(mImages.subList(position * 3, (position + 1) * 3)); 86 | imageView.setImageClickListener(new MultiImageView.OnImageClickListener() { 87 | @Override 88 | public void onClick(int position) { 89 | Toast.makeText(getApplicationContext(), "click image " + position, Toast.LENGTH_SHORT).show(); 90 | } 91 | }); 92 | } 93 | 94 | @Override 95 | protected int getItemLayout(int type) { 96 | return R.layout.multi_image_item; 97 | } 98 | }; 99 | 100 | // 设置RecyclerView的点击事件 101 | // adapter.setOnItemClickListener(new RecyclerAdapter.OnItemClickListener() { 102 | // @Override 103 | // public void onItemClick(int position) { 104 | // Toast.makeText(MultiImageActivity.this, "Click Recycler : " 105 | // + adapter.getItem(position), Toast.LENGTH_SHORT).show(); 106 | // } 107 | // }); 108 | recyclerView.setAdapter(adapter); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /demo/src/main/java/simple/com/demo/widgets/MultiImageView.java: -------------------------------------------------------------------------------- 1 | package simple.com.demo.widgets; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Canvas; 7 | import android.graphics.Matrix; 8 | import android.graphics.Paint; 9 | import android.text.TextUtils; 10 | import android.util.AttributeSet; 11 | import android.view.MotionEvent; 12 | import android.view.View; 13 | 14 | import com.nostra13.universalimageloader.core.ImageLoader; 15 | import com.nostra13.universalimageloader.core.assist.FailReason; 16 | import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | import simple.com.demo.ImageItem; 22 | import simple.com.demo.R; 23 | 24 | /** 25 | * 在一个View上绘制三张图片的View,将图片数据传递进来之后首先绘制Loading图,然后通过ImageLoader加载图片,加载完图片之后重绘对应的区域. 26 | *

27 | * Created by mrsimple on 13/4/16. 28 | */ 29 | public class MultiImageView extends View { 30 | /** 31 | * 图片集合 32 | */ 33 | private List mImages = new ArrayList<>(); 34 | /** 35 | * loadding中的图片 36 | */ 37 | private Bitmap mLoadingBmp; 38 | /** 39 | * 单张图片的宽度 40 | */ 41 | private int mSingleImageWidth; 42 | /** 43 | * 视图的高度 44 | */ 45 | private int mViewHeight; 46 | /** 47 | * 图片矩阵对象,用于对图片进行缩放 48 | */ 49 | private Matrix mDrawMatrix = new Matrix(); 50 | /** 51 | * 图片之间的水平间距 52 | */ 53 | private int mHorizontalSpacing = 10; 54 | private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 55 | private int pLeft; 56 | private int pTop; 57 | private OnImageClickListener mImageClickListener; 58 | static BitmapFactory.Options sOptions = new BitmapFactory.Options(); 59 | 60 | 61 | public MultiImageView(Context context) { 62 | this(context, null); 63 | } 64 | 65 | public MultiImageView(Context context, AttributeSet attrs) { 66 | this(context, attrs, 0); 67 | } 68 | 69 | public MultiImageView(Context context, AttributeSet attrs, int defStyleAttr) { 70 | super(context, attrs, defStyleAttr); 71 | sOptions.inPreferredConfig = Bitmap.Config.RGB_565; 72 | mLoadingBmp = BitmapFactory.decodeResource(getResources(), R.drawable.imageloading, sOptions); 73 | mHorizontalSpacing = convertToPx(3); 74 | pLeft = getPaddingLeft(); 75 | pTop = getPaddingTop(); 76 | } 77 | 78 | 79 | /** 80 | * 设置图片之间的水平间距 81 | * 82 | * @param dp 单位为dp 83 | */ 84 | public void setHorizontalSpacing(int dp) { 85 | mHorizontalSpacing = convertToPx(dp); 86 | } 87 | 88 | /** 89 | * 设置图片集 90 | * 91 | * @param images 92 | */ 93 | public void setImages(List images) { 94 | if (images.size() < 3) { 95 | return; 96 | } 97 | mImages.clear(); 98 | this.mImages.addAll(images); 99 | loadImagesAsync(); 100 | } 101 | 102 | /** 103 | * 异步加载图片 104 | */ 105 | private void loadImagesAsync() { 106 | for (int i = 0; i < mImages.size(); i++) { 107 | final ImageItem item = mImages.get(i); 108 | item.bitmap = mLoadingBmp; 109 | ImageLoader.getInstance().loadImage(item.url, new ImageLoadingListener() { 110 | @Override 111 | public void onLoadingStarted(String s, View view) { 112 | 113 | } 114 | 115 | @Override 116 | public void onLoadingFailed(String s, View view, FailReason failReason) { 117 | 118 | } 119 | 120 | @Override 121 | public void onLoadingComplete(String s, View view, Bitmap bitmap) { 122 | // 判断该View是否被复用,避免图片显示错乱 123 | if (!TextUtils.isEmpty(s) && s.equals(item.url)) { 124 | item.bitmap = bitmap; 125 | invalidate(item.rect); 126 | } 127 | } 128 | 129 | @Override 130 | public void onLoadingCancelled(String s, View view) { 131 | 132 | } 133 | }); 134 | } 135 | invalidate(); 136 | } 137 | 138 | @Override 139 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 140 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 141 | // 用来显示三章图片的完整区域 142 | int totalWidth = (getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - mHorizontalSpacing * 3); 143 | mSingleImageWidth = totalWidth / 3; 144 | mViewHeight = getMeasuredHeight(); 145 | // 每张图片的位置以及宽高 146 | for (int i = 0; i < mImages.size(); i++) { 147 | final ImageItem item = mImages.get(i); 148 | // 设置该图绘制的位置, 这里的240为图片的宽度 149 | item.rect.set(pLeft + i * 240, pTop, 150 | pLeft + 240 * (i + 1), pTop + mViewHeight); 151 | // 计算变换矩阵 152 | calculateMartrx(item); 153 | } 154 | } 155 | 156 | /** 157 | * 缩放图片 , 使用的模式参考 ImageView的center crop 158 | * 159 | * @param image 160 | */ 161 | private void calculateMartrx(ImageItem image) { 162 | float scale; 163 | float dx = 0, dy = 0; 164 | int dwidth = image.getWidth(); 165 | int dheight = image.getHeight(); 166 | int vwidth = mSingleImageWidth; 167 | int vheight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); 168 | 169 | if (dwidth * vheight > vwidth * dheight) { 170 | scale = (float) vheight / (float) dheight; 171 | dx = (vwidth - dwidth * scale) * 0.5f; 172 | } else { 173 | scale = (float) vwidth / (float) dwidth; 174 | dy = (vheight - dheight * scale) * 0.5f; 175 | } 176 | 177 | mDrawMatrix.setScale(scale, scale); 178 | mDrawMatrix.postTranslate(Math.round(dx), Math.round(dy)); 179 | } 180 | 181 | @Override 182 | protected void onDraw(Canvas canvas) { 183 | for (int i = 0; i < mImages.size(); i++) { 184 | final ImageItem item = mImages.get(i); 185 | // 绘制图片 186 | int saveCount = canvas.getSaveCount(); 187 | canvas.save(); 188 | canvas.translate(pLeft, pTop); 189 | if (mDrawMatrix != null) { 190 | canvas.concat(mDrawMatrix); 191 | } 192 | // 绘制三张图片 193 | canvas.drawBitmap(item.bitmap, 194 | item.rect.left + i * mHorizontalSpacing, item.rect.top, mPaint); 195 | canvas.restoreToCount(saveCount); 196 | } 197 | } 198 | 199 | /** 200 | * 设置loading 图片 201 | * 202 | * @param res 203 | */ 204 | public void setLoadingBitmapResource(int res) { 205 | if (this.mLoadingBmp != null 206 | && !mLoadingBmp.isRecycled()) { 207 | mLoadingBmp.recycle(); 208 | mLoadingBmp = null; 209 | } 210 | this.mLoadingBmp = BitmapFactory.decodeResource(getResources(), res, sOptions); 211 | invalidate(); 212 | } 213 | 214 | public void setImageClickListener(OnImageClickListener listener) { 215 | this.mImageClickListener = listener; 216 | } 217 | 218 | @Override 219 | public boolean onTouchEvent(MotionEvent event) { 220 | if (event.getAction() == MotionEvent.ACTION_UP) { 221 | handleClickImageEvent(event); 222 | } 223 | return super.onTouchEvent(event); 224 | } 225 | 226 | /** 227 | * 通过点击的x坐标位置判断点击的是第几张图,然后回调给调用者 228 | * 229 | * @param event 230 | */ 231 | private void handleClickImageEvent(MotionEvent event) { 232 | // 获取点击的位置 233 | int clickIndex = (int) event.getX() / mSingleImageWidth; 234 | if (mImageClickListener != null && clickIndex < mImages.size()) { 235 | mImageClickListener.onClick(clickIndex); 236 | } 237 | } 238 | 239 | public int convertToPx(int dp) { 240 | final float scale = getResources().getDisplayMetrics().density; 241 | return (int) (dp * scale + 0.5f); 242 | } 243 | 244 | /** 245 | * 图片点击Listener 246 | */ 247 | public static interface OnImageClickListener { 248 | public void onClick(int position); 249 | } 250 | } 251 | -------------------------------------------------------------------------------- /demo/src/main/res/drawable/big_smile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hehonghui/commonadapter/ba413357f7623351f53f426933e8af4bae036362/demo/src/main/res/drawable/big_smile.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hehonghui/commonadapter/ba413357f7623351f53f426933e8af4bae036362/demo/src/main/res/drawable/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable/imageloading.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hehonghui/commonadapter/ba413357f7623351f53f426933e8af4bae036362/demo/src/main/res/drawable/imageloading.9.png -------------------------------------------------------------------------------- /demo/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/activity_multi.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 16 | 17 | 24 | 25 | 26 | 27 | 34 | 35 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 22 | 23 | 29 | 30 | 35 | 36 | 43 | 44 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/list_item_type_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 15 | 22 | 23 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/list_item_type_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 18 | 27 | 28 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/multi_image_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | -------------------------------------------------------------------------------- /demo/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 |

5 | 9 | 10 | -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hehonghui/commonadapter/ba413357f7623351f53f426933e8af4bae036362/demo/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hehonghui/commonadapter/ba413357f7623351f53f426933e8af4bae036362/demo/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hehonghui/commonadapter/ba413357f7623351f53f426933e8af4bae036362/demo/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hehonghui/commonadapter/ba413357f7623351f53f426933e8af4bae036362/demo/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hehonghui/commonadapter/ba413357f7623351f53f426933e8af4bae036362/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 | 180dp 6 | 16dp 7 | 8 | -------------------------------------------------------------------------------- /demo/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Demo 3 | Settings 4 | 5 | -------------------------------------------------------------------------------- /demo/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 14 |