以这种方式使用 recyclerView 而不是直接复选框:-
活动代码:-
lateinit var recyclerView: RecyclerView
lateinit var adapter: CheckboxAdapter
lateinit var list3: List<RowModel>
lateinit var list1: List<RowModel>
lateinit var list2: List<RowModel>
lateinit var list4: List<RowModel>
lateinit var list: List<RowModel>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_select_courses)
recyclerView = findViewById(R.id.trail_rv)
list1 = listOf(
RowModel(RowType.TopHeader, "", "", "", false)
)
list2 = listOf(
RowModel(RowType.Course, "", "", "Science", false),
RowModel(RowType.SubjectRow, "Physics", "", "Science", false),
RowModel(RowType.Dummy, "Physics", "Physics", "Science", false),
RowModel(RowType.SubjectRow, "Math", "", "Science", false),
RowModel(RowType.Dummy, "Math", "Math", "Science", false),
RowModel(RowType.SubjectRow, "Chemistry", "", "Science", false),
RowModel(RowType.Dummy, "Chemistry", "Chemistry", "Science", false)
)
list3 = listOf(
RowModel(RowType.Course, "", "", "Arts", false),
RowModel(RowType.SubjectRow, "Economics", "", "Arts", false),
RowModel(RowType.Dummy, "Economics", "Economics", "Arts", false),
RowModel(RowType.SubjectRow, "History", "", "Arts", false),
RowModel(RowType.Dummy, "History", "History", "Arts", false),
RowModel(RowType.SubjectRow, "Political Science", "", "Arts", false),
RowModel(RowType.Dummy, "Political Science", "Political Science", "Arts", false)
)
list4 = listOf(
RowModel(RowType.Course, "", "", "Commerce", false),
RowModel(RowType.SubjectRow, "Accountancy", "", "Commerce", false),
RowModel(RowType.Dummy, "Accountancy", "Accountancy", "Commerce", false),
RowModel(RowType.SubjectRow, "Business Studies", "", "Commerce", false),
RowModel(RowType.Dummy, "Business Studies", "Business Studies", "Commerce", false),
RowModel(RowType.SubjectRow, "Physical Education", "", "Commerce", false),
RowModel(RowType.Dummy, "Physical Education", "Physical Education", "Commerce", false)
)
list = list1 + list2 + list4 + list3
adapter = CheckboxAdapter(this, list)
adapter.setList(list)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this)
findViewById<Button>(R.id.showTextBtn).setOnClickListener {
val checkboxesValue: String = selectedCheckboxes.joinToString(separator = ";\n")
findViewById<TextView>(R.id.ShowTextView).text = checkboxesValue
}
findViewById<Button>(R.id.clearTextBtn).setOnClickListener {
selectedCheckboxes.clear()
adapter.setList(list)
}
}
}
适配器代码:-
class CheckboxAdapter(
private val context: Context,
var productList: List<RowModel>,
) : RecyclerView.Adapter<CheckboxAdapter.TableViewHolder>() {
override fun onBindViewHolder(holder: TableViewHolder, position: Int) {
val item = productList[position]
holder.checkBox.setOnCheckedChangeListener(null)
holder.checkBox.isChecked = item.isChecked
val params: ViewGroup.MarginLayoutParams =
holder.checkBox.layoutParams as ViewGroup.MarginLayoutParams
when (item.rowType) {
RowType.TopHeader -> {
holder.checkBox.text = "All Courses"
holder.checkBox.visibility = View.VISIBLE
holder.checkBox.typeface = Typeface.DEFAULT_BOLD
params.setMargins(0, 0, 0, 0)
holder.checkBox.layoutParams = params
}
RowType.Course -> {
holder.checkBox.visibility = View.VISIBLE
holder.checkBox.text = item.course
holder.checkBox.typeface = Typeface.DEFAULT_BOLD
params.setMargins(20, 0, 0, 0)
holder.checkBox.layoutParams = params
}
RowType.SubjectRow -> {
holder.checkBox.visibility = View.VISIBLE
holder.checkBox.text = item.subjectName
holder.checkBox.typeface = Typeface.DEFAULT
params.setMargins(convertDpToPixel(40f, context).toInt(), 0, 0, 0)
holder.checkBox.layoutParams = params
}
RowType.Dummy -> {
holder.checkBox.visibility = View.GONE
holder.checkBox.text = item.subjectName
holder.checkBox.typeface = Typeface.DEFAULT
params.setMargins(convertDpToPixel(60f, context).toInt(), 0, 0, 0)
holder.checkBox.layoutParams = params
}
}
holder.checkBox.setOnCheckedChangeListener { _, isChecked ->
if (item.isChecked != isChecked) {
item.isChecked = isChecked
when (item.rowType) {
RowType.TopHeader -> {
val indexList = mutableListOf<Int>()
productList.filter { it.rowType != RowType.TopHeader }.forEach {
it.isChecked = isChecked
indexList.add(productList.indexOf(it))
}
indexList.forEach {
notifyItemChanged(it)
}
}
RowType.Course -> {
val indexList = mutableListOf<Int>()
productList.filter { it.rowType == RowType.SubjectRow && it.course == item.course }
.forEach {
it.isChecked = isChecked
indexList.add(productList.indexOf(it))
}
productList.filter { it.rowType == RowType.Dummy && it.course == item.course }
.forEach {
it.isChecked = isChecked
indexList.add(productList.indexOf(it))
}
indexList.forEach {
notifyItemChanged(it)
}
isAllItemsSameStatus() //for header
}
RowType.SubjectRow -> {
val indexList = mutableListOf<Int>()
productList.filter { it.rowType == RowType.Dummy && it.subjectName == item.subjectName }
.forEach {
it.isChecked = isChecked
indexList.add(productList.indexOf(it))
}
indexList.forEach {
notifyItemChanged(it)
}
isAllItemsSameStatus()
}
}
}
}
when (item.rowType) {
RowType.Course -> {
if (holder.checkBox.isChecked)
selectedCheckboxes.add(holder.checkBox.text.toString())
if (!holder.checkBox.isChecked) {
selectedCheckboxes.remove(holder.checkBox.text.toString())
}
}
RowType.Dummy -> {
if (holder.checkBox.isChecked)
selectedCheckboxes.add(holder.checkBox.text.toString())
if (!holder.checkBox.isChecked) {
selectedCheckboxes.remove(holder.checkBox.text.toString())
}
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TableViewHolder {
return TableViewHolder(
LayoutInflater.from(context).inflate(
R.layout.checkbox,
parent,
false
)
)
}
class TableViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val checkBox: CheckBox = itemView.findViewById(R.id.Checkbox)
}
override fun getItemCount() = productList.size
fun setList(profiles: List<RowModel>) {
productList = profiles
notifyDataSetChanged()
}
private fun isAllItemsSameStatus(cat: String? = null) {
val row: RowModel
var isChecked: Boolean = true
var position: Int = 0
if (cat != null) {
val catRow = productList.find { it.rowType == RowType.Course && it.course == cat }
catRow?.let {
val subList =
productList.filter { it.course == it.course && it.rowType == RowType.SubjectRow }
isChecked = subList.filter { it.isChecked }.size == subList.size
position = productList.indexOf(catRow)
}
if (catRow == null)
return
else
row = catRow
} else {
row = productList[0]
isChecked =
productList.filter { it.rowType != RowType.TopHeader && it.isChecked }.size == productList.size - 1
position = 0
}
updateHeader(row, isChecked, position)
}
private fun isAllSubjectItemsSameStatus(cat: String? = null) {
val row: RowModel
var isChecked: Boolean = true
var position: Int = 0
if (cat != null) {
val catRow =
productList.find { it.rowType == RowType.SubjectRow && it.subjectName == cat }
catRow?.let {
val subList =
productList.filter { it.subjectName == it.subjectName && it.rowType == RowType.Dummy }
isChecked = subList.filter { it.isChecked }.size == subList.size
position = productList.indexOf(catRow)
}
if (catRow == null)
return
else
row = catRow
} else {
row = productList[0]
isChecked =
productList.filter { it.rowType != RowType.TopHeader && it.isChecked }.size == productList.size - 1
position = 0
}
updateHeader(row, isChecked, position)
}
private fun updateHeader(item: RowModel, isChecked: Boolean, position: Int) {
if (item.isChecked != isChecked) // no need to update if no change
{
item.isChecked = isChecked
notifyItemChanged(position)
}
}
private fun convertDpToPixel(dp: Float, context: Context): Float {
return dp * (context.resources
.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
}
companion object {
var selectedCheckboxes: ArrayList<String> = ArrayList()
}
}
模型数据类代码:-
data class SubjectRowModel (
val SubjectRowType: SubjectRowType,
val subjectName: String,
val dummyName: String,
val course: String,
var isChecked: Boolean = true)
enum class SubjectRowType(val id : Int) {
TopHeader(1),
Course(2),
SubjectRow(3),
Dummy(4);
}