├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── goyourfly │ │ └── multiselectadapter │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── goyourfly │ │ │ └── multiselectadapter │ │ │ ├── DemoAdapter.kt │ │ │ ├── DemoSectionAdapter.kt │ │ │ ├── MainActivity.kt │ │ │ ├── MoreActivity.kt │ │ │ ├── RecyclerActivity.kt │ │ │ └── more │ │ │ ├── Demo1Activity.kt │ │ │ ├── Demo2Activity.kt │ │ │ ├── Demo3Activity.kt │ │ │ ├── Demo4Activity.kt │ │ │ ├── Demo5Activity.kt │ │ │ ├── Demo6Activity.java │ │ │ └── Demo7Activity.kt │ └── res │ │ ├── drawable │ │ └── ic_star_border_black_24dp.xml │ │ ├── layout │ │ ├── activity_base_recycler_adapter_helper.xml │ │ ├── activity_main.xml │ │ ├── activity_more.xml │ │ ├── activity_recycler.xml │ │ ├── custom_control.xml │ │ ├── item_email.xml │ │ └── item_section.xml │ │ ├── menu │ │ ├── menu_main.xml │ │ └── menu_select.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── goyourfly │ └── multiselectadapter │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── goyourfly │ │ └── multiple │ │ └── adapter │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── goyourfly │ │ │ └── multiple │ │ │ └── adapter │ │ │ ├── MultipleAdapter.kt │ │ │ ├── MultipleSelect.kt │ │ │ ├── SelectState.kt │ │ │ ├── SimpleStateChangeListener.kt │ │ │ ├── StateChangeListener.kt │ │ │ ├── ViewState.kt │ │ │ ├── menu │ │ │ ├── CustomMenuBar.kt │ │ │ ├── MenuBar.kt │ │ │ ├── MenuController.kt │ │ │ ├── SimpleDeleteMenuBar.kt │ │ │ ├── SimpleDeleteSelectAllMenuBar.kt │ │ │ ├── SimpleDoneAndDeleteMenuBar.kt │ │ │ └── SimpleDoneMenuBar.kt │ │ │ └── viewholder │ │ │ ├── AnimationInterface.kt │ │ │ ├── BaseViewHolder.kt │ │ │ ├── DecorateFactory.kt │ │ │ ├── EventObserverView.kt │ │ │ ├── color │ │ │ ├── ColorFactory.kt │ │ │ └── ColorViewHolder.kt │ │ │ ├── drawable │ │ │ ├── DrawableFactory.kt │ │ │ └── DrawableViewHolder.kt │ │ │ └── view │ │ │ ├── CheckBoxFactory.kt │ │ │ ├── CustomViewFactory.kt │ │ │ ├── CustomViewHolder.kt │ │ │ └── RadioBtnFactory.kt │ └── res │ │ ├── drawable │ │ ├── ic_arrow_back_black_24dp.xml │ │ ├── ic_check_box_black_24dp.xml │ │ ├── ic_check_box_outline_blank_black_24dp.xml │ │ ├── ic_delete_black_24dp.xml │ │ ├── ic_done_black_24dp.xml │ │ ├── ic_radio_button_checked_black_24dp.xml │ │ ├── ic_radio_button_unchecked_black_24dp.xml │ │ └── ic_select_all_black_24dp.xml │ │ ├── menu │ │ ├── menu_multiple_select_delete.xml │ │ ├── menu_multiple_select_done.xml │ │ ├── menu_multiple_select_done_delete.xml │ │ └── menu_multiple_select_done_delete_all.xml │ │ └── values │ │ ├── colors.xml │ │ ├── ids.xml │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── goyourfly │ └── multiple │ └── adapter │ └── ExampleUnitTest.java ├── screenshot ├── Demo0.png ├── Demo1.png ├── Demo2.png ├── Demo3.png ├── Demo4.png ├── Demo5.png ├── Demo6.png ├── MenuBar.png ├── MultiSelectAdapter.png ├── NormalItemView.png ├── SelectItemView.png └── Sequence.png ├── settings.gradle └── 一行实现RecyclerView的多选模式.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | /.idea/ 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MultiSelectAdapter 2 | 3 | MultiSelectAdapter是一个为RecyclerView设计的Adapter,它可以在不修改你原有Adapter的前提下让你的RecycleView支持多选和批量操作 4 | 5 | ## Demo 6 | 7 | 8 | 9 | 14 | 15 | 20 |
Demo0 10 | Demo1 11 | Demo2 12 | Demo3 13 |
Demo0 16 | Demo4 17 | Demo5 18 | Demo6 19 |
21 | 22 | ## Compile 23 | [![](https://jitpack.io/v/goyourfly/MultiSelectAdapter.svg)](https://jitpack.io/#goyourfly/MultiSelectAdapter) 24 | 25 | Step 1. Add it in your root build.gradle at the end of repositories: 26 | 27 | ```` 28 | allprojects { 29 | repositories { 30 | ... 31 | maven { url 'https://jitpack.io' } 32 | } 33 | } 34 | ```` 35 | 36 | Step 2. Add the dependency 37 | 38 | ```` 39 | dependencies { 40 | compile 'com.github.goyourfly:MultiSelectAdapter:lastVersion' 41 | } 42 | ```` 43 | 44 | 45 | ## Usage 46 | 47 | ````java 48 | MultipleAdapter adapter = MultipleSelect 49 | .with(Activity) 50 | .adapter(YourAdapter) 51 | .ignoreViewType(ItemViewType) 52 | .linkList(YourAdapter.list) 53 | .stateChangeListener(StateChangeListener) 54 | .decorateFactory(? extends DecorateFactory) 55 | .customMenu(? extends MenuBar) 56 | .build(); 57 | ```` 58 | 59 | | 方法名 | 形参 | 是否必须 | 说明 | 60 | |:-----|:-----|:-----|:-----| 61 | | with | Activity | 是 | 显示RecycleView的Activity | 62 | | adapter | RecyclerView.Adapter | 是 | 你的Adapter | 63 | | ignoreViewType | Integer[] | 否 | 需要忽略的Item类型,比如Section,Header,Footer等 | 64 | | linkList | List | 否 | 绑定你的Adapter的地址,这样在调用MultipleAdapter.delete()接口的时候就会自动删除数据 | 65 | | stateChangeListener | StateChangeListener | 否 | 选择模式时候的一些消息回调 | 66 | | decorateFactory | ? extends DecorateFactory | 否 | 选择模式时Item的样式创建类,可以自定义,具体样式参考上面Demo,底下会详细介绍 | 67 | | customMenu | ? extends MenuBar | 否 | 选择模式的Menu,默认提供几种方式,可以简单的自定义和完全的自定义 | 68 | 69 | ### StateChangeListener 70 | 71 | ````kotlin 72 | /** 73 | * Kotlin 74 | * 一些操作的回调 75 | */ 76 | open class SimpleStateChangeListener:StateChangeListener{ 77 | override fun onSelectMode() { 78 | 79 | } 80 | 81 | override fun onSelect(position: Int, selectNum: Int) { 82 | 83 | } 84 | 85 | override fun onUnSelect(position: Int, selectNum: Int) { 86 | 87 | } 88 | 89 | override fun onDone(array: ArrayList) { 90 | 91 | } 92 | 93 | override fun onDelete(array: ArrayList) { 94 | 95 | } 96 | 97 | override fun onCancel() { 98 | 99 | } 100 | 101 | } 102 | ```` 103 | 104 | ### DecorateFactory 105 | 106 | DecorateFactory定义了在多选模式下Item的样式,如下第一个是正常模式的显示状态,第二个是多选模式下的显示样式(其中的一种样式) 107 | 108 | RadioButtonStyle 109 | RadioButtonStyle 110 | 111 | 目前内置四种样式的DecorateFactory,分别是 112 | 113 | | 类名 | 构造方法参数 | 说明 | Demo | 114 | |:-----|:-----|:------|:-----| 115 | | RadioBtnFactory | color:Int(RadioBtn颜色), duration:Long(动画时长), gravity:Int(位置,Gravity.LEFT,Gravity.RIGHT) | 在Item外面的左侧或者右侧显示RadioButton |RadioButtonStyle| 116 | | CheckBoxFactory | color:Int(颜色), duration:Long(动画时长), gravity:Int(位置,Gravity),marginDp:Int,边距 | 在Item内部的左侧或者右侧显示RadioButton, |CheckBoxStyle| 117 | | ColorFactory | targetViewId:Int(改变颜色的View ID),defaultColor:Int,普通状态下的颜色,selectColor:Int选中状态下的颜色 | 选中和未选中的时候,修改某一个View的背景色 |ColorStyle | 118 | | DrawableFactory | | | | 119 | 120 | ##### 当然,你也可以实现自己的风格如下: 121 | 122 | ````kotlin 123 | class YourCustomFactory(val color: Int = Color.RED, 124 | val gravity: Int = Gravity.RIGHT, 125 | val marginDp:Int = 8) : CustomViewFactory() { 126 | // 显示时候的动画,如果不加动画,则直接将selectView置为View.VISIBLE 127 | override fun onShowAnimation(itemView: View, selectView: View) { 128 | selectView.visibility = View.VISIBLE 129 | } 130 | 131 | // 隐藏时候的动画,如果不加动画,则直接将selectView置为View.GONE 132 | override fun onHideAnimation(itemView: View, selectView: View) { 133 | selectView.visibility = View.GONE 134 | } 135 | 136 | // 创建选中时显示的View 137 | override fun onCreateSelectView(context:Context): View { 138 | val imageView = ImageView(context) 139 | imageView.setImageResource(R.drawable.ic_check_box_black_24dp) 140 | imageView.setColorFilter(color) 141 | return imageView 142 | } 143 | // 创建未选中时的View 144 | override fun onCreateNormalView(context:Context): View { 145 | val imageView = ImageView(context) 146 | imageView.setColorFilter(color) 147 | imageView.setImageResource(R.drawable.ic_check_box_outline_blank_black_24dp) 148 | return imageView 149 | } 150 | 151 | // 创建View的容器,该容器包含了用户的ItemView和你定义的选中时的View 152 | override fun onCreateRootView(context:Context): ViewGroup { 153 | return FrameLayout(context) 154 | } 155 | 156 | // 设置ItemView和SelectView的位置关系 157 | // ItemView:用户创建的ItemView 158 | // SelectView:选中状态View 159 | override fun onBindSelectView(root: ViewGroup, itemView: View, selectView: View) { 160 | root.removeAllViews() 161 | root.addView(itemView) 162 | val params = FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT) 163 | params.gravity = gravity 164 | params.leftMargin = marginDp.toPx(root.context) 165 | params.topMargin = marginDp.toPx(root.context) 166 | params.rightMargin = marginDp.toPx(root.context) 167 | params.bottomMargin = marginDp.toPx(root.context) 168 | root.addView(selectView, params) 169 | } 170 | 171 | } 172 | 173 | ```` 174 | 175 | ### MenuBar 176 | 177 | MenuBar 178 | 179 | 内置四种MenuBar的样式,具体样式请看Demo 180 | 181 | - SimpleDeleteMenuBar 182 | - SimpleDoneMenuBar 183 | - SimpleDoneAndDeleteMenuBar 184 | - SimpleDeleteSelectAllMenuBar 185 | 186 | 你也可以通过继承CustomMenuBar来实现一个自己的MenuBar: 187 | 188 | ````kotlin 189 | class MyMenuBar(activity:Activity,menuId:Int,color:Int) 190 | :CustomMenuBar(activity,menuId,color,Gravity.TOP){ 191 | 192 | override fun onUpdateTitle(selectCount: Int, total: Int) { 193 | toolbar.title = "选中:$selectCount 总共:$total" 194 | } 195 | 196 | override fun onMenuItemClick(menuItem: MenuItem, controller: MenuController) { 197 | //TODO 这里处理点击事件 198 | } 199 | } 200 | ```` 201 | 202 | #### 详细的使用可以看这里:[Code](./app/src/main/java/com/goyourfly/multiselectadapter/) -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | android { 6 | compileSdkVersion 25 7 | buildToolsVersion "25.0.3" 8 | defaultConfig { 9 | applicationId "com.goyourfly.multiselectadapter.app" 10 | minSdkVersion 15 11 | targetSdkVersion 25 12 | versionCode 1 13 | versionName "1.0" 14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } 23 | 24 | dependencies { 25 | compile fileTree(dir: 'libs', include: ['*.jar']) 26 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 27 | exclude group: 'com.android.support', module: 'support-annotations' 28 | }) 29 | compile project(':library') 30 | compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" 31 | compile 'com.android.support:appcompat-v7:25.3.1' 32 | testCompile 'junit:junit:4.12' 33 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 34 | compile 'com.android.support:recyclerview-v7:25.3.1' 35 | compile 'com.jakewharton:butterknife:8.5.1' 36 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1' 37 | compile 'com.android.support:design:25.3.1' 38 | compile 'com.android.support:recyclerview-v7:25.3.1' 39 | compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.24' 40 | } 41 | -------------------------------------------------------------------------------- /app/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/gaoyufei/Dev/sdks/android_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 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/goyourfly/multiselectadapter/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.goyourfly.multiselectadapter 2 | 3 | import android.support.test.InstrumentationRegistry 4 | import android.support.test.runner.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumentation test, which will execute on an Android device. 13 | * 14 | * @see [Testing documentation](http://d.android.com/tools/testing) 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | @Throws(Exception::class) 20 | fun useAppContext() { 21 | // Context of the app under test. 22 | val appContext = InstrumentationRegistry.getTargetContext() 23 | assertEquals("com.goyourfly.multiselectadapter", appContext.packageName) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/goyourfly/multiselectadapter/DemoAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.goyourfly.multiselectadapter 2 | 3 | import android.support.v7.widget.RecyclerView 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.widget.TextView 8 | import android.widget.Toast 9 | 10 | /** 11 | * Created by gaoyufei on 2017/6/8. 12 | */ 13 | class DemoAdapter : RecyclerView.Adapter() { 14 | 15 | val list = arrayListOf() 16 | 17 | init { 18 | for (i in 0..100) { 19 | addItem("i:$i") 20 | } 21 | } 22 | 23 | fun addItem(str: String) { 24 | list.add(str) 25 | } 26 | 27 | fun removeItem(position: Int) { 28 | list.removeAt(position) 29 | } 30 | 31 | override fun onBindViewHolder(p0: MyViewHolder?, p1: Int) { 32 | val holder = p0 as MyViewHolder 33 | holder.position.text = list[p1] 34 | } 35 | 36 | override fun onCreateViewHolder(p0: ViewGroup, p1: Int): MyViewHolder { 37 | return MyViewHolder(LayoutInflater.from(p0.context).inflate(R.layout.item_email, p0, false)) 38 | } 39 | 40 | 41 | override fun getItemCount(): Int { 42 | return list.size 43 | } 44 | 45 | class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) { 46 | val position: TextView by lazy { 47 | view.findViewById(R.id.position) as TextView 48 | } 49 | 50 | init { 51 | view.setOnClickListener { 52 | Toast.makeText(view.context, "Hello", Toast.LENGTH_SHORT).show() 53 | } 54 | view.findViewById(R.id.image_star) 55 | .setOnClickListener { 56 | Toast.makeText(view.context, "Star", Toast.LENGTH_SHORT).show() 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/goyourfly/multiselectadapter/DemoSectionAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.goyourfly.multiselectadapter 2 | 3 | import android.support.v7.widget.RecyclerView 4 | import android.util.Log 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import android.widget.TextView 9 | import android.widget.Toast 10 | 11 | /** 12 | * Created by gaoyufei on 2017/6/8. 13 | */ 14 | class DemoSectionAdapter : RecyclerView.Adapter() { 15 | val TYPE_SECTION = 1 16 | val TYPE_CONTENT = 2 17 | 18 | val list = mutableListOf() 19 | 20 | init { 21 | for (i in 0..100) { 22 | addItem(Data("index:$i",if(i % 10 == 0) TYPE_SECTION else TYPE_CONTENT)) 23 | } 24 | } 25 | 26 | fun addItem(data: Data) { 27 | list.add(data) 28 | } 29 | 30 | fun removeItem(position: Int) { 31 | list.removeAt(position) 32 | } 33 | 34 | override fun onBindViewHolder(p0: RecyclerView.ViewHolder?, p1: Int) { 35 | if (getItemViewType(p1) == TYPE_CONTENT) { 36 | val holder = p0 as MyViewHolder 37 | holder.position.text = list[p1].str 38 | } 39 | } 40 | 41 | override fun onCreateViewHolder(p0: ViewGroup, p1: Int): RecyclerView.ViewHolder { 42 | if(p1 == TYPE_SECTION){ 43 | return SectionViewHolder(LayoutInflater.from(p0.context).inflate(R.layout.item_section, p0, false)) 44 | }else{ 45 | return MyViewHolder(LayoutInflater.from(p0.context).inflate(R.layout.item_email, p0, false)) 46 | } 47 | } 48 | 49 | override fun getItemId(position: Int): Long { 50 | return position.toLong() 51 | } 52 | 53 | override fun getItemViewType(position: Int): Int { 54 | return list[position].type 55 | } 56 | 57 | 58 | data class Data(val str: String,val type:Int) 59 | 60 | override fun getItemCount(): Int { 61 | return list.size 62 | } 63 | 64 | class SectionViewHolder(view: View) : RecyclerView.ViewHolder(view) 65 | 66 | 67 | class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) { 68 | val position: TextView by lazy { 69 | view.findViewById(R.id.position) as TextView 70 | } 71 | 72 | init { 73 | view.setOnClickListener { 74 | Toast.makeText(view.context, "Hello", Toast.LENGTH_SHORT).show() 75 | } 76 | view.findViewById(R.id.image_star) 77 | .setOnClickListener { 78 | Toast.makeText(view.context, "Star", Toast.LENGTH_SHORT).show() 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/goyourfly/multiselectadapter/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.goyourfly.multiselectadapter 2 | 3 | import android.content.Intent 4 | import android.support.v7.app.AppCompatActivity 5 | import android.os.Bundle 6 | import android.support.v7.widget.DividerItemDecoration 7 | import android.support.v7.widget.LinearLayoutManager 8 | import android.support.v7.widget.RecyclerView 9 | import android.view.Gravity 10 | import android.view.Menu 11 | import android.view.MenuItem 12 | import com.goyourfly.multiple.adapter.MultipleAdapter 13 | import com.goyourfly.multiple.adapter.MultipleSelect 14 | import com.goyourfly.multiple.adapter.menu.SimpleDeleteSelectAllMenuBar 15 | import com.goyourfly.multiple.adapter.viewholder.color.ColorFactory 16 | import com.goyourfly.multiple.adapter.viewholder.view.CheckBoxFactory 17 | import com.goyourfly.multiple.adapter.viewholder.view.RadioBtnFactory 18 | 19 | class MainActivity : AppCompatActivity() { 20 | val recycler: RecyclerView by lazy { findViewById(R.id.recycler) as RecyclerView } 21 | val demoAdapter = DemoSectionAdapter() 22 | override fun onCreate(savedInstanceState: Bundle?) { 23 | super.onCreate(savedInstanceState) 24 | setContentView(R.layout.activity_main) 25 | 26 | recycler.layoutManager = LinearLayoutManager(this) 27 | recycler.addItemDecoration(DividerItemDecoration(this, RecyclerView.VERTICAL)) 28 | 29 | recycler.adapter = MultipleSelect 30 | .with(this) 31 | .adapter(demoAdapter) 32 | .decorateFactory(ColorFactory()) 33 | .linkList(demoAdapter.list) 34 | .ignoreViewType(arrayOf(demoAdapter.TYPE_SECTION)) 35 | .customMenu(SimpleDeleteSelectAllMenuBar(this, resources.getColor(R.color.colorPrimary))) 36 | .build() 37 | } 38 | 39 | override fun onCreateOptionsMenu(menu: Menu?): Boolean { 40 | menuInflater.inflate(R.menu.menu_main, menu) 41 | return super.onCreateOptionsMenu(menu) 42 | } 43 | 44 | override fun onOptionsItemSelected(item: MenuItem): Boolean { 45 | when (item.itemId) { 46 | R.id.action_radio_btn_left -> { 47 | recycler.adapter = MultipleSelect 48 | .with(this) 49 | .adapter(demoAdapter) 50 | .decorateFactory(RadioBtnFactory()) 51 | .ignoreViewType(arrayOf(demoAdapter.TYPE_SECTION)) 52 | .linkList(demoAdapter.list) 53 | .customMenu(SimpleDeleteSelectAllMenuBar(this, resources.getColor(R.color.colorPrimary))) 54 | .build() 55 | } 56 | R.id.action_radio_btn_right -> { 57 | recycler.adapter = MultipleSelect 58 | .with(this) 59 | .adapter(demoAdapter) 60 | .decorateFactory(RadioBtnFactory(Gravity.RIGHT)) 61 | .ignoreViewType(arrayOf(demoAdapter.TYPE_SECTION)) 62 | .linkList(demoAdapter.list) 63 | .customMenu(SimpleDeleteSelectAllMenuBar(this, resources.getColor(R.color.colorPrimary))) 64 | .build() 65 | } 66 | R.id.action_check_box -> { 67 | recycler.adapter = MultipleSelect 68 | .with(this) 69 | .adapter(demoAdapter) 70 | .decorateFactory(CheckBoxFactory(color = resources.getColor(R.color.colorPrimary))) 71 | .ignoreViewType(arrayOf(demoAdapter.TYPE_SECTION)) 72 | .linkList(demoAdapter.list) 73 | .customMenu(SimpleDeleteSelectAllMenuBar(this, resources.getColor(R.color.colorPrimary))) 74 | .build() 75 | } 76 | R.id.action_background_color -> { 77 | recycler.adapter = MultipleSelect 78 | .with(this) 79 | .adapter(demoAdapter) 80 | .decorateFactory(ColorFactory()) 81 | .ignoreViewType(arrayOf(demoAdapter.TYPE_SECTION)) 82 | .linkList(demoAdapter.list) 83 | .customMenu(SimpleDeleteSelectAllMenuBar(this, resources.getColor(R.color.colorPrimary))) 84 | .build() 85 | } 86 | R.id.action_more -> { 87 | startActivity(Intent(this,MoreActivity::class.java)) 88 | } 89 | } 90 | return super.onOptionsItemSelected(item) 91 | } 92 | 93 | override fun onBackPressed() { 94 | if(!(recycler.adapter as MultipleAdapter).cancel()){ 95 | super.onBackPressed() 96 | } 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /app/src/main/java/com/goyourfly/multiselectadapter/MoreActivity.kt: -------------------------------------------------------------------------------- 1 | package com.goyourfly.multiselectadapter 2 | 3 | import android.content.Intent 4 | import android.support.v7.app.AppCompatActivity 5 | import android.os.Bundle 6 | import com.goyourfly.multiselectadapter.more.* 7 | 8 | class MoreActivity : AppCompatActivity() { 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | setContentView(R.layout.activity_more) 12 | 13 | 14 | 15 | findViewById(R.id.demo_1).setOnClickListener { 16 | startActivity(Intent(it.context, Demo1Activity::class.java)) 17 | } 18 | 19 | findViewById(R.id.demo_2).setOnClickListener { 20 | startActivity(Intent(it.context, Demo2Activity::class.java)) 21 | } 22 | findViewById(R.id.demo_3).setOnClickListener { 23 | startActivity(Intent(it.context, Demo3Activity::class.java)) 24 | } 25 | 26 | findViewById(R.id.demo_4).setOnClickListener { 27 | startActivity(Intent(it.context, Demo4Activity::class.java)) 28 | } 29 | 30 | findViewById(R.id.demo_5).setOnClickListener { 31 | startActivity(Intent(it.context, Demo5Activity::class.java)) 32 | } 33 | findViewById(R.id.demo_6).setOnClickListener { 34 | startActivity(Intent(it.context, Demo6Activity::class.java)) 35 | } 36 | findViewById(R.id.demo_7).setOnClickListener { 37 | startActivity(Intent(it.context, Demo7Activity::class.java)) 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/goyourfly/multiselectadapter/RecyclerActivity.kt: -------------------------------------------------------------------------------- 1 | package com.goyourfly.multiselectadapter 2 | 3 | import android.os.Bundle 4 | import android.support.v7.app.AppCompatActivity 5 | import android.support.v7.widget.DividerItemDecoration 6 | import android.support.v7.widget.LinearLayoutManager 7 | import android.support.v7.widget.RecyclerView 8 | 9 | open class RecyclerActivity : AppCompatActivity() { 10 | val recycler: RecyclerView by lazy { findViewById(R.id.recycler) as RecyclerView } 11 | override fun onCreate(savedInstanceState: Bundle?) { 12 | super.onCreate(savedInstanceState) 13 | setContentView(R.layout.activity_recycler) 14 | recycler.layoutManager = LinearLayoutManager(this) 15 | recycler.addItemDecoration(DividerItemDecoration(this,RecyclerView.VERTICAL)) 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/goyourfly/multiselectadapter/more/Demo1Activity.kt: -------------------------------------------------------------------------------- 1 | package com.goyourfly.multiselectadapter.more 2 | 3 | import android.os.Bundle 4 | import android.view.Gravity 5 | import com.goyourfly.multiple.adapter.MultipleSelect 6 | import com.goyourfly.multiple.adapter.SimpleStateChangeListener 7 | import com.goyourfly.multiple.adapter.viewholder.view.RadioBtnFactory 8 | import com.goyourfly.multiselectadapter.DemoSectionAdapter 9 | import com.goyourfly.multiselectadapter.RecyclerActivity 10 | 11 | class Demo1Activity : RecyclerActivity() { 12 | val stateChangeListener = SimpleStateChangeListener() 13 | val demoAdapter = DemoSectionAdapter() 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | super.onCreate(savedInstanceState) 16 | 17 | recycler.adapter = MultipleSelect.with(this) 18 | .adapter(demoAdapter) 19 | .decorateFactory(RadioBtnFactory(Gravity.RIGHT)) 20 | .ignoreViewType(arrayOf(1)) 21 | .linkList(demoAdapter.list) 22 | .stateChangeListener(stateChangeListener) 23 | .build() 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/goyourfly/multiselectadapter/more/Demo2Activity.kt: -------------------------------------------------------------------------------- 1 | package com.goyourfly.multiselectadapter.more 2 | 3 | import android.os.Bundle 4 | import android.view.Gravity 5 | import com.goyourfly.multiple.adapter.* 6 | import com.goyourfly.multiple.adapter.viewholder.view.CheckBoxFactory 7 | import com.goyourfly.multiple.adapter.menu.SimpleDeleteMenuBar 8 | import com.goyourfly.multiselectadapter.R 9 | 10 | class Demo2Activity : com.goyourfly.multiselectadapter.RecyclerActivity() { 11 | val stateChangeListener = com.goyourfly.multiple.adapter.SimpleStateChangeListener() 12 | 13 | override fun onCreate(savedInstanceState: android.os.Bundle?) { 14 | super.onCreate(savedInstanceState) 15 | 16 | val adapter = com.goyourfly.multiselectadapter.DemoSectionAdapter() 17 | recycler.adapter = com.goyourfly.multiple.adapter.MultipleSelect.with(this) 18 | .adapter(adapter) 19 | .decorateFactory(CheckBoxFactory(Gravity.RIGHT)) 20 | .customMenu(com.goyourfly.multiple.adapter.menu.SimpleDeleteMenuBar(this, resources.getColor(R.color.colorAccent), Gravity.BOTTOM)) 21 | .linkList(adapter.list) 22 | .ignoreViewType(arrayOf(1)) 23 | .stateChangeListener(stateChangeListener) 24 | .build() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/goyourfly/multiselectadapter/more/Demo3Activity.kt: -------------------------------------------------------------------------------- 1 | package com.goyourfly.multiselectadapter.more 2 | 3 | import android.os.Bundle 4 | import com.goyourfly.multiple.adapter.MultipleSelect 5 | import com.goyourfly.multiple.adapter.menu.SimpleDeleteSelectAllMenuBar 6 | import com.goyourfly.multiple.adapter.viewholder.color.ColorFactory 7 | import com.goyourfly.multiselectadapter.DemoAdapter 8 | import com.goyourfly.multiselectadapter.R 9 | import com.goyourfly.multiselectadapter.RecyclerActivity 10 | 11 | class Demo3Activity : RecyclerActivity() { 12 | override fun onCreate(savedInstanceState: Bundle?) { 13 | super.onCreate(savedInstanceState) 14 | 15 | val demoAdapter = DemoAdapter() 16 | recycler.adapter = MultipleSelect.with(this) 17 | .adapter(demoAdapter) 18 | .decorateFactory(ColorFactory()) 19 | .linkList(demoAdapter.list) 20 | .customMenu(SimpleDeleteSelectAllMenuBar(this, resources.getColor(R.color.colorPrimary))) 21 | .build() 22 | 23 | } 24 | 25 | fun String.log(){ 26 | android.util.Log.d("Demo3Activity",this) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/goyourfly/multiselectadapter/more/Demo4Activity.kt: -------------------------------------------------------------------------------- 1 | package com.goyourfly.multiselectadapter.more 2 | 3 | import android.app.Activity 4 | import android.os.Bundle 5 | import android.util.Log 6 | import android.view.Gravity 7 | import android.view.View 8 | import android.widget.TextView 9 | import com.goyourfly.multiple.adapter.MultipleSelect 10 | import com.goyourfly.multiple.adapter.viewholder.view.RadioBtnFactory 11 | import com.goyourfly.multiple.adapter.menu.MenuBar 12 | import com.goyourfly.multiselectadapter.DemoAdapter 13 | import com.goyourfly.multiselectadapter.R 14 | import com.goyourfly.multiselectadapter.RecyclerActivity 15 | import java.util.* 16 | 17 | class Demo4Activity : RecyclerActivity() { 18 | var adapter = DemoAdapter() 19 | override fun onCreate(savedInstanceState: Bundle?) { 20 | super.onCreate(savedInstanceState) 21 | 22 | recycler.adapter = MultipleSelect.with(this) 23 | .adapter(adapter) 24 | .decorateFactory(RadioBtnFactory()) 25 | .customMenu(CustomMenuBar(this, adapter)) 26 | .build() 27 | 28 | } 29 | 30 | 31 | class CustomMenuBar(activity: Activity, val adapter: DemoAdapter) : MenuBar(activity, Gravity.TOP) { 32 | override fun onUpdateTitle(selectCount: Int, total: Int) { 33 | title?.setText("当前选中:$selectCount 条数据") 34 | } 35 | 36 | var title: TextView? = null 37 | var confirm: View? = null 38 | var cancel: View? = null 39 | var delete: View? = null 40 | override fun getContentView(): View { 41 | val view = View.inflate(activity, R.layout.custom_control, null) 42 | title = view.findViewById(R.id.title) as TextView 43 | confirm = view.findViewById(R.id.confirm) 44 | cancel = view.findViewById(R.id.cancel) 45 | delete = view.findViewById(R.id.delete) 46 | 47 | confirm?.setOnClickListener { controler?.done() } 48 | cancel?.setOnClickListener { controler?.cancel() } 49 | delete?.setOnClickListener { 50 | val select = controler?.getSelect() 51 | Collections.reverse(select) 52 | "select:$select".log() 53 | for (index in select!!) { 54 | "removeItem:$index".log() 55 | adapter.removeItem(index) 56 | } 57 | controler?.done() 58 | } 59 | return view; 60 | } 61 | 62 | fun String.log() { 63 | Log.d("Demo3Activity", this) 64 | } 65 | } 66 | 67 | fun String.log() { 68 | Log.d("Demo3Activity", this) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/goyourfly/multiselectadapter/more/Demo5Activity.kt: -------------------------------------------------------------------------------- 1 | package com.goyourfly.multiselectadapter.more 2 | 3 | import android.app.Activity 4 | import android.os.Bundle 5 | import android.view.MenuItem 6 | import com.goyourfly.multiple.adapter.MultipleSelect 7 | import com.goyourfly.multiple.adapter.viewholder.color.ColorFactory 8 | import com.goyourfly.multiple.adapter.menu.CustomMenuBar 9 | import com.goyourfly.multiple.adapter.menu.MenuController 10 | import com.goyourfly.multiselectadapter.DemoAdapter 11 | import com.goyourfly.multiselectadapter.R 12 | import com.goyourfly.multiselectadapter.RecyclerActivity 13 | 14 | class Demo5Activity : RecyclerActivity() { 15 | override fun onCreate(savedInstanceState: Bundle?) { 16 | super.onCreate(savedInstanceState) 17 | 18 | recycler.adapter = MultipleSelect.with(this) 19 | .adapter(DemoAdapter()) 20 | .decorateFactory(ColorFactory()) 21 | .customMenu(MyMenuBar(this, R.menu.menu_select, resources.getColor(R.color.colorPrimary))) 22 | .build() 23 | 24 | } 25 | 26 | class MyMenuBar(activity: Activity, menuId:Int, color:Int) 27 | : CustomMenuBar(activity,menuId,color, android.view.Gravity.TOP){ 28 | override fun onMenuItemClick(menuItem: MenuItem, controller: MenuController) { 29 | android.util.Log.d("Demo5Activity","itemId:${menuItem.title}") 30 | } 31 | 32 | override fun onUpdateTitle(selectCount: Int, total: Int) { 33 | toolbar.title = "选中:$selectCount,总共:$total" 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/goyourfly/multiselectadapter/more/Demo6Activity.java: -------------------------------------------------------------------------------- 1 | package com.goyourfly.multiselectadapter.more; 2 | 3 | import android.graphics.Color; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.view.Gravity; 7 | import android.view.MenuItem; 8 | 9 | import com.goyourfly.multiple.adapter.MultipleAdapter; 10 | import com.goyourfly.multiple.adapter.MultipleSelect; 11 | import com.goyourfly.multiple.adapter.menu.MenuController; 12 | import com.goyourfly.multiple.adapter.viewholder.view.CheckBoxFactory; 13 | import com.goyourfly.multiple.adapter.menu.CustomMenuBar; 14 | import com.goyourfly.multiselectadapter.DemoSectionAdapter; 15 | import com.goyourfly.multiselectadapter.R; 16 | import com.goyourfly.multiselectadapter.RecyclerActivity; 17 | 18 | import org.jetbrains.annotations.NotNull; 19 | 20 | /** 21 | * Created by gaoyufei on 2017/6/12. 22 | */ 23 | 24 | public class Demo6Activity extends RecyclerActivity { 25 | 26 | @Override 27 | protected void onCreate(@Nullable Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | DemoSectionAdapter demoSectionAdapter = new DemoSectionAdapter(); 30 | MultipleAdapter adapter = MultipleSelect 31 | .with(this) 32 | .adapter(demoSectionAdapter) 33 | .ignoreViewType(new Integer[]{1}) 34 | .linkList(demoSectionAdapter.getList()) 35 | .decorateFactory(new CheckBoxFactory(Color.RED, 300, Gravity.RIGHT, 8)) 36 | .customMenu(new CustomMenuBar(this, R.menu.menu_select,getResources().getColor(R.color.colorPrimaryDark),Gravity.TOP) { 37 | @Override 38 | public void onMenuItemClick(@NotNull MenuItem menuItem,MenuController controller) { 39 | 40 | } 41 | }) 42 | .build(); 43 | getRecycler().setAdapter(adapter); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/goyourfly/multiselectadapter/more/Demo7Activity.kt: -------------------------------------------------------------------------------- 1 | package com.goyourfly.multiselectadapter.more 2 | 3 | import android.os.Bundle 4 | import android.util.Log 5 | import android.view.Gravity 6 | import android.widget.TextView 7 | import android.widget.Toast 8 | import com.chad.library.adapter.base.BaseQuickAdapter 9 | import com.chad.library.adapter.base.BaseViewHolder 10 | import com.goyourfly.multiple.adapter.* 11 | import com.goyourfly.multiple.adapter.viewholder.view.CheckBoxFactory 12 | import com.goyourfly.multiple.adapter.menu.SimpleDeleteMenuBar 13 | import com.goyourfly.multiselectadapter.DemoSectionAdapter 14 | import com.goyourfly.multiselectadapter.R 15 | 16 | class Demo7Activity : com.goyourfly.multiselectadapter.RecyclerActivity() { 17 | val stateChangeListener = com.goyourfly.multiple.adapter.SimpleStateChangeListener() 18 | 19 | override fun onCreate(savedInstanceState: android.os.Bundle?) { 20 | super.onCreate(savedInstanceState) 21 | 22 | val list = arrayListOf() 23 | for (i in 0..100){ 24 | list.add("index of $i") 25 | } 26 | val adapter = MyQuickAdapter(R.layout.item_section,list) 27 | recycler.adapter = MultipleSelect.with(this) 28 | .adapter(adapter) 29 | .decorateFactory(CheckBoxFactory(Gravity.RIGHT)) 30 | .customMenu(SimpleDeleteMenuBar(this, resources.getColor(R.color.colorAccent), Gravity.BOTTOM)) 31 | .linkList(list) 32 | .ignoreViewType(arrayOf(1)) 33 | .stateChangeListener(stateChangeListener) 34 | .build() 35 | } 36 | 37 | class MyQuickAdapter(layout:Int,list:List) : BaseQuickAdapter(layout,list) { 38 | override fun convert(baseViewHolder: BaseViewHolder, value: String) { 39 | baseViewHolder.getView(R.id.section).text = value 40 | baseViewHolder.getView(R.id.section).setOnClickListener { 41 | Toast.makeText(it.context,"I am click:${baseViewHolder.adapterPosition}",Toast.LENGTH_LONG).show() 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_star_border_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_base_recycler_adapter_helper.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_more.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 |