I am trying to make a game of life grid based game in Android Studio using kotlin. Essentially, every second the grid will update based off a set of rules. However, I can not for the life of me get the grid to update.
For some reason, notifyItemChanged() is not calling onBindViewHolder to properly update the grid visually. I was able to find a work around for some cases, that being calling onBindViewHolder specifically and passing through the current cellViewHolder and it's position, but this won't get me the result I am looking for. Specifically, in the function I declared testUpdate(), I need to be able to change an array of data that the grid is based on, and then from that function notify the grid that changes were made and it should update. However, notifyItemChanged() as well as notifyDatasetChanged() both do not call onBindViewHolder(). I am at a loss, any help would be much appreciated!
I am very new to Kotlin, so I apologize if this code is horrible.
Here is my code:
package com.example.project2
import android.graphics.Color
import android.os.Bundle
import android.text.Layout
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageButton
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.os.Handler;
class BoardFragment : Fragment() {
private lateinit var recyclerView: RecyclerView
var gridArray = IntArray(400)
val handler = Handler()
var isRunning: Boolean = false
val colorRed = Color.RED
val colorBlue = Color.BLUE
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.board_fragment, container, false)
val startButton = view.findViewById(R.id.start_button) as Button
val recyclerView = view.findViewById(R.id.recycler_view) as RecyclerView
recyclerView.layoutManager = GridLayoutManager(activity, 20)
recyclerView.adapter = GridAdapter()
startButton.setOnClickListener {
isRunning = !isRunning
if (isRunning) {
testUpdate()
}
}
return view
}
fun testUpdate() {
handler.postDelayed({
if (gridArray[3] == 0) {
gridArray[3] = 1
} else {
gridArray[3] = 0
}
if (isRunning) {
testUpdate()
}
GridAdapter().notifyItemChanged(3)
}, 1000)
}
override fun onStart() {
super.onStart()
}
private inner class CellViewHolder(cellView: View): RecyclerView.ViewHolder(cellView) {
val button: ImageButton
init {
button = cellView.findViewById(R.id.cell_button)
button.setColorFilter(null)
button.setOnClickListener {
if (gridArray[position] == 0) {
gridArray[position] = 1
} else {
gridArray[position] = 0
}
GridAdapter().notifyItemChanged(position)
GridAdapter().onBindViewHolder(this, position)
}
}
fun display(position: Int) {
}
}
private inner class GridAdapter: RecyclerView.Adapter<CellViewHolder>() {
final val NUM_CELLS: Int = 400
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CellViewHolder {
val inflater: LayoutInflater = LayoutInflater.from(parent.context)
val cellView: View = inflater.inflate(R.layout.board_cell, parent, false)
return CellViewHolder(cellView)
}
override fun onBindViewHolder(holder: CellViewHolder, position: Int) {
holder.display(position)
if (gridArray[position] == 0) {
holder.button.setColorFilter(null)
} else {
holder.button.setColorFilter(Color.RED)
}
}
override fun getItemCount(): Int {
return NUM_CELLS
}
}
}
I don't know what you're trying to achieve but a few tip
GridAdapter().notifyItemChanged(position)
change
to
modify your class like this