:bug: :art: · CoderLPF/AndroidFilePicker@906110a · GitHub
Skip to content

Commit 906110a

Browse files
committed
🐛 🎨
[Fix] - CheckBox status was not changed immediately because of item view recycler mechanism. - Sample code crash due to NPE. [Update] - Refactored FileListAdapter method's code. - other code formatting.
1 parent f8ee3e1 commit 906110a

6 files changed

Lines changed: 115 additions & 103 deletions

File tree

filepicker/src/main/java/me/rosuh/filepicker/FilePickerActivity.kt

Lines changed: 10 additions & 37 deletions
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package me.rosuh.filepicker.adapter
22

33
import android.support.v7.widget.RecyclerView
4+
import android.view.View
45
import me.rosuh.filepicker.bean.FileBean
56

6-
abstract class BaseAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>() {
7+
abstract class BaseAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
78
abstract fun getItem(position: Int): FileBean?
9+
abstract fun getItemView(position: Int): View?
810
}

filepicker/src/main/java/me/rosuh/filepicker/adapter/FileListAdapter.kt

Lines changed: 88 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,11 @@ import android.support.v7.widget.RecyclerView
44
import android.view.LayoutInflater
55
import android.view.View
66
import android.view.ViewGroup
7-
import android.widget.CheckBox
8-
import android.widget.ImageView
9-
import android.widget.RadioButton
10-
import android.widget.TextView
7+
import android.widget.*
118
import me.rosuh.filepicker.FilePickerActivity
129
import me.rosuh.filepicker.R
1310
import me.rosuh.filepicker.bean.FileItemBeanImpl
14-
import me.rosuh.filepicker.config.FilePickerManager
11+
import me.rosuh.filepicker.config.FilePickerManager.config as config
1512
import java.io.File
1613

1714
/**
@@ -23,7 +20,7 @@ import java.io.File
2320
class FileListAdapter(
2421
private val activity: FilePickerActivity,
2522
var dataList: ArrayList<FileItemBeanImpl>?,
26-
private var isSingleChoice: Boolean = FilePickerManager.config.singleChoice
23+
private var isSingleChoice: Boolean = config.singleChoice
2724
) : BaseAdapter() {
2825
private var latestChoicePos = -1
2926
private lateinit var recyclerView: RecyclerView
@@ -54,6 +51,10 @@ class FileListAdapter(
5451
}
5552
}
5653

54+
override fun getItemView(position: Int): View? {
55+
return recyclerView.findViewHolderForAdapterPosition(position)?.itemView
56+
}
57+
5758
override fun getItemCount(): Int {
5859
return dataList?.size ?: 10
5960
}
@@ -66,6 +67,32 @@ class FileListAdapter(
6667
(holder as BaseViewHolder).bind(dataList!![position], position)
6768
}
6869

70+
override fun onBindViewHolder(
71+
holder: RecyclerView.ViewHolder,
72+
position: Int,
73+
payloads: MutableList<Any>
74+
) {
75+
// Using payload to refresh partly
76+
// 使用 payload 进行局部刷新
77+
if (payloads.isNullOrEmpty()) {
78+
onBindViewHolder(holder, position)
79+
return
80+
}
81+
when (holder) {
82+
is FileListItemHolder -> {
83+
holder.itemView.findViewById<CheckBox>(R.id.cb_list_file_picker)?.let {
84+
it.isChecked = payloads[0] as Boolean
85+
}
86+
}
87+
is FileListItemSingleChoiceHolder -> {
88+
holder.itemView.findViewById<RadioButton>(R.id.rb_list_file_picker)?.let {
89+
it.isChecked = payloads[0] as Boolean
90+
}
91+
}
92+
}
93+
}
94+
95+
6996
override fun getItem(position: Int): FileItemBeanImpl? {
7097
if (position >= 0 &&
7198
position < dataList!!.size &&
@@ -74,108 +101,108 @@ class FileListAdapter(
74101
return null
75102
}
76103

77-
fun disCheck(position: Int, view: View) {
78-
getItem(position)?.let {
79-
it.setCheck(false)
80-
view.findViewById<CheckBox>(R.id.cb_list_file_picker).isChecked = false
104+
/*--------------------------OutSide call method begin------------------------------*/
105+
inline fun multipleCheckOrNo(
106+
item: FileItemBeanImpl,
107+
position: Int,
108+
isCanSelect: () -> Boolean,
109+
checkFailedFunc: () -> Unit
110+
) {
111+
when {
112+
item.isChecked() -> {
113+
// 当前被选中,说明即将取消选中
114+
// had selected, will dis-select
115+
multipleDisCheck(position)
116+
}
117+
isCanSelect() -> {
118+
// 当前未被选中,并且检查合格,则即将新增选中
119+
// current item is not selected, and can be selected, will select
120+
multipleCheck(position)
121+
}
122+
else -> {
123+
// 新增选中项失败的情况
124+
// add new selected item failed
125+
checkFailedFunc()
126+
}
81127
}
82128
}
83129

84-
fun check(position: Int, view: View) {
85-
if (isSingleChoice) {
86-
singleCheck(position, view)
87-
} else {
88-
multipleCheck(position, view)
130+
fun multipleCheck(position: Int) {
131+
getItem(position)?.let {
132+
it.setCheck(true)
133+
notifyItemChanged(position, true)
89134
}
90135
}
91136

92-
/*--------------------------OutSide call method begin------------------------------*/
93137

94-
private fun multipleCheck(position: Int, view: View) {
138+
fun multipleDisCheck(position: Int) {
95139
getItem(position)?.let {
96-
it.setCheck(true)
97-
view.findViewById<CheckBox>(R.id.cb_list_file_picker).isChecked = true
140+
it.setCheck(false)
141+
notifyItemChanged(position, false)
98142
}
99143
}
100144

101-
private fun singleCheck(position: Int, view: View) {
102-
val rb = view.findViewById<RadioButton>(R.id.rb_list_file_picker)
145+
146+
fun singleCheck(position: Int) {
103147
when (latestChoicePos) {
104148
-1 -> {
105149
// 从未选中过
106150
getItem(position)?.let {
107151
it.setCheck(true)
108-
rb.isChecked = true
152+
notifyItemChanged(position, true)
109153
}
110154
latestChoicePos = position
111155
}
112156
position -> {
113157
// 取消选中
114158
getItem(latestChoicePos)?.let {
115159
it.setCheck(false)
116-
rb.isChecked = false
160+
notifyItemChanged(latestChoicePos, false)
117161
}
118162
latestChoicePos = -1
119163
}
120164
else -> {
121-
// 选中新项
165+
// disCheck the old one
122166
getItem(latestChoicePos)?.let {
123167
it.setCheck(false)
124-
recyclerView.findViewHolderForAdapterPosition(latestChoicePos)
125-
?.itemView
126-
?.findViewById<RadioButton>(R.id.rb_list_file_picker)
127-
?.isChecked = false
168+
notifyItemChanged(latestChoicePos, false)
128169
}
170+
// check the new one
129171
latestChoicePos = position
130172
getItem(latestChoicePos)?.let {
131173
it.setCheck(true)
132-
rb.isChecked = true
174+
notifyItemChanged(latestChoicePos, true)
133175
}
134176
}
135177
}
136178
}
137179

138180
fun disCheckAll() {
139-
dataList?.forEachIndexed { index, item ->
140-
if (!(FilePickerManager.config.isSkipDir && item.isDir) && item.isChecked()) {
141-
val itemView = recyclerView.findViewHolderForAdapterPosition(index)?.itemView
142-
if (isSingleChoice) {
143-
itemView?.findViewById<RadioButton>(R.id.rb_list_file_picker)?.let {
144-
it.isChecked = false
145-
}
146-
} else {
147-
itemView?.findViewById<CheckBox>(R.id.cb_list_file_picker)?.let {
148-
it.isChecked = false
149-
}
181+
dataList
182+
?.forEachIndexed { index, item ->
183+
if (!(config.isSkipDir && item.isDir) && item.isChecked()) {
184+
item.setCheck(false)
185+
notifyItemChanged(index, false)
150186
}
151-
item.setCheck(false)
152187
}
153-
}
154188
}
155189

156190
fun checkAll(hadSelectedCount: Int) {
157191
var checkCount = hadSelectedCount
158-
dataList?.forEachIndexed { index, item ->
159-
if (checkCount >= FilePickerManager.config.maxSelectable){
160-
return
161-
}
162-
if (!(FilePickerManager.config.isSkipDir && item.isDir) && !item.isChecked()) {
163-
val itemView = recyclerView.findViewHolderForAdapterPosition(index)?.itemView
164-
if (isSingleChoice) {
165-
itemView?.findViewById<RadioButton>(R.id.rb_list_file_picker)?.let {
166-
it.isChecked = true
167-
}
168-
} else {
169-
itemView?.findViewById<CheckBox>(R.id.cb_list_file_picker)?.let {
170-
it.isChecked = true
171-
}
192+
dataList
193+
?.forEachIndexed { index, item ->
194+
if (checkCount >= config.maxSelectable) {
195+
return
196+
}
197+
if (!(config.isSkipDir && item.isDir) && !item.isChecked()) {
198+
item.setCheck(true)
199+
notifyItemChanged(index, true)
200+
checkCount++
172201
}
173-
item.setCheck(true)
174-
checkCount++
175202
}
176-
}
177203
}
178204

205+
179206
/*--------------------------OutSide call method end------------------------------*/
180207

181208
/*--------------------------ViewHolder Begin------------------------------*/
@@ -190,7 +217,7 @@ class FileListAdapter(
190217
inner class FileListItemSingleChoiceHolder(itemView: View) :
191218
BaseViewHolder(itemView) {
192219

193-
private val isSkipDir: Boolean = FilePickerManager.config.isSkipDir
220+
private val isSkipDir: Boolean = config.isSkipDir
194221
private val mTvFileName = itemView.findViewById<TextView>(R.id.tv_list_file_picker)!!
195222
private val mRbItem = itemView.findViewById<RadioButton>(R.id.rb_list_file_picker)!!
196223
private val mIcon = itemView.findViewById<ImageView>(R.id.iv_icon_list_file_picker)!!
@@ -226,7 +253,7 @@ class FileListAdapter(
226253
inner class FileListItemHolder(itemView: View) :
227254
BaseViewHolder(itemView) {
228255

229-
private val isSkipDir: Boolean = FilePickerManager.config.isSkipDir
256+
private val isSkipDir: Boolean = config.isSkipDir
230257
private val mTvFileName = itemView.findViewById<TextView>(R.id.tv_list_file_picker)!!
231258
private val mCbItem = itemView.findViewById<CheckBox>(R.id.cb_list_file_picker)!!
232259
private val mIcon = itemView.findViewById<ImageView>(R.id.iv_icon_list_file_picker)!!

filepicker/src/main/java/me/rosuh/filepicker/adapter/FileNavAdapter.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package me.rosuh.filepicker.adapter
22

33
import android.support.v7.widget.RecyclerView
44
import android.view.LayoutInflater
5+
import android.view.View
56
import android.view.ViewGroup
67
import android.widget.TextView
78
import me.rosuh.filepicker.FilePickerActivity
@@ -15,11 +16,19 @@ import me.rosuh.filepicker.bean.FileNavBeanImpl
1516
*/
1617
class FileNavAdapter(private val activity: FilePickerActivity, var data: MutableList<FileNavBeanImpl>) :
1718
BaseAdapter(){
19+
private lateinit var recyclerView: RecyclerView
1820

1921
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
22+
if (parent is RecyclerView){
23+
recyclerView = parent
24+
}
2025
return NavListHolder(activity.layoutInflater, parent)
2126
}
2227

28+
override fun getItemView(position: Int): View? {
29+
return recyclerView.findViewHolderForAdapterPosition(position)?.itemView
30+
}
31+
2332
override fun getItemCount(): Int {
2433
return data.size
2534
}

sample/src/main/java/me/rosuh/sample/SampleActivity.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,10 @@ import me.rosuh.filepicker.config.FilePickerConfig
2121
import me.rosuh.filepicker.config.FilePickerManager
2222
import me.rosuh.filepicker.config.SimpleItemClickListener
2323
import me.rosuh.filepicker.filetype.RasterImageFileType
24+
import me.rosuh.filepicker.utils.ScreenUtils
2425

2526

2627
class SampleActivity : AppCompatActivity() {
27-
private var rv: RecyclerView? = null
28-
2928
/**
3029
* 自定义文件过滤器
3130
*/
@@ -224,8 +223,9 @@ class SampleActivity : AppCompatActivity() {
224223
FilePickerManager.REQUEST_CODE -> {
225224
if (resultCode == Activity.RESULT_OK) {
226225
val list = FilePickerManager.obtainData()
227-
rv!!.adapter = SampleAdapter(layoutInflater, ArrayList(list))
228-
rv!!.layoutManager = LinearLayoutManager(this@SampleActivity)
226+
rv_main.adapter = SampleAdapter(layoutInflater, ArrayList(list))
227+
rv_main.layoutManager = LinearLayoutManager(this@SampleActivity)
228+
ns_root.scrollTo(0, ScreenUtils.getScreenHeightInPixel(this))
229229
} else {
230230
Toast.makeText(this@SampleActivity, "没有选择图片", Toast.LENGTH_SHORT).show()
231231
}

sample/src/main/res/layout/demo_activity_main.xml

Lines changed: 1 addition & 0 deletions

0 commit comments

Comments
 (0)