for logic of the question you can refer to this question:- question Logic
After lots of efforts I have came to this point. Please help me solving this problem.
Here is activity code:-
class CheckboxesActivity : AppCompatActivity() {
lateinit var recyclerView: RecyclerView
lateinit var adapter: CheckboxAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_trail)
recyclerView =findViewById(R.id.trail_rv)
val list = listOf(
RowModel(RowType.TopHeader, "", "", false),
RowModel(RowType.Course, "", "Science", false),
RowModel(RowType.SubjectRow, "Physics", "Science", false),
RowModel(RowType.SubjectRow, "Math", "Science", false),
RowModel(RowType.SubjectRow, "Chemistry", "Science", false),
RowModel(RowType.Course, "", "Arts", false),
RowModel(RowType.SubjectRow, "Economics", "Arts", false),
RowModel(RowType.SubjectRow, "History", "Arts", false),
RowModel(RowType.SubjectRow, "Political Science", "Arts", false),
RowModel(RowType.Course, "", "Commerce", false),
RowModel(RowType.SubjectRow, "Accountancy", "Commerce", false),
RowModel(RowType.SubjectRow, "Business Studies", "Commerce", false),
RowModel(RowType.SubjectRow, "Physical Education", "Commerce", false)
)
adapter = CheckboxAdapter(this, list)
adapter.setList(list)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this)
findViewById<Button>(R.id.showTextBtn).setOnClickListener {
selectedCheckboxes!!.clear()
val checkboxesValue: String = selectedCheckboxes!!.joinToString(separator = ";")
findViewById<TextView>(R.id.ShowTextView).text = checkboxesValue
}
}
}
here is my adapter code:-
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.category
holder.checkBox.typeface = Typeface.DEFAULT_BOLD
params.setMargins(0, 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(20f, 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.category == item.category }
.forEach {
it.isChecked = isChecked
indexList.add(productList.indexOf(it))
}
indexList.forEach {
notifyItemChanged(it)
}
isAllItemsSameStatus() //for header
}
RowType.SubjectRow -> {
isAllItemsSameStatus(item.category) //set prep area accordingly
isAllItemsSameStatus() //set top header
}
}
}
}
when (item.rowType) {
RowType.SubjectRow -> {
if (holder.checkBox.isChecked)
selectedCheckboxes?.add(holder.checkBox.text.toString())
if (!holder.checkBox.isChecked) {
Toast.makeText(context, holder.checkBox.text, Toast.LENGTH_SHORT).show()
selectedCheckboxes?.remove(holder.checkBox.text.toString())
}
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TableViewHolder {
return TableViewHolder(
LayoutInflater.from(context).inflate(
R.layout.rv_trail,
parent,
false
)
)
}
class TableViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val checkBox: CheckBox = itemView.findViewById(R.id.trailCheckbox)
}
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.category == cat }
catRow?.let {
val subList =
productList.filter { it.category == it.category && 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 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: MutableList<String>? = null
}
}
here is my model code:-
data class RowModel (
val rowType: RowType,
val subjectName: String,
val category: String,
var isChecked: Boolean = true)
enum class RowType(val id : Int) {
TopHeader(1),
Course(2),
SubjectRow(3);
}
here is activity_trail layout code:-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".CheckboxesActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/trail_rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/showTextBtn"
style="@style/ButtonTransparent"
android:text="@string/save"/>
<TextView
android:id="@+id/ShowTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
The logic of the question is :-
I am trying to make to activity that if:- 1)all courses checkbox is selected then all other checkboxes should be checked and vice versa.
2)all science button is checked then all other subjects buttons should be selected and vice versa. Same for all other subjects as well.
3)if any course button is not checked then all courses button should also not be checked. Same for all subjects as well.
After clicking showTextBtn (Button). The app is crashing. Here is the crash report:-
java.lang.NullPointerException
at com.trail.CheckboxesActivity.onCreate$lambda-0(CheckboxesActivity.kt:45)
at com.trail.CheckboxesActivity.$r8$lambda$Q7Wv2MEY_mNrpZmgjbfsuGABR0o(Unknown Source:0)
at com.trail.CheckboxesActivity$$ExternalSyntheticLambda0.onClick(Unknown Source:2)
at android.view.View.performClick(View.java:8160)
at android.widget.TextView.performClick(TextView.java:16222)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1194)
at android.view.View.performClickInternal(View.java:8137)
at android.view.View.access$3700(View.java:888)
at android.view.View$PerformClick.run(View.java:30236)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:246)
at android.app.ActivityThread.main(ActivityThread.java:8653)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
Here I am trying to get the text of all the selected checkboxes. Show that text in the textView. Every other thing is working fine but the problem is only while getting the values of selected checkboxes text app is crashing. If possible can you tell me if how can I use string-array instead of typing all these list?
Instead of using :-
var selectedCheckboxes: MutableList<String>? = null
use:-
var selectedCheckboxes: ArrayList<String> = ArrayList()