Home > Net >  Kotlin ActivityMainBinding build id in for loop
Kotlin ActivityMainBinding build id in for loop

Time:02-10

I have a problem. In my xml file, I have multiple textViews with the following id's:

txtRow1Column1
txtRow1Column2
txtRow2Column1
txtRow2Column2
txtRow3Column1
txtRow3Column2
txtRow4Column1
txtRow4Column2

Now I filled an array with random numbers between 1..2 and using the 1 or 2 I want to add a text in the textview from the resources. For that I already have the following function:

private fun startNewRound() {

    // Define the array for (row, column, value)
    val rows = arrayOf<Array<Int>>();

    // Fill the array for each row and for each column
    for (row in 1..4) {
        rows.set(row, emptyArray())
        for (column in 1..2) {
            rows[row].plus((1..2).random())
        }
    }

    // Show the correct text using the filled array
    for (columns in rows) {
        for (value in columns) {
            val id = "txtRow"   rows.indexOf(columns)   "Column"   (columns.indexOf(value)   1)
            when (value) {
                1 -> binding."ID HERE".text = getString(R.string.strTrue)
                2 -> binding."ID HERE".text = getString(R.string.strFalse)
            }
        }
    }
}

Currently I have added "ID HERE" instead of the id of the view, because I need to use a string as id to bind to the view. My question is: How can I use that string to find the correct id and be able to bind to that specific view?

CodePudding user response:

Side note, the way you're building that 2D array looks like O(n^2), even if it wasn't going to throw IndexOutOfBoundsExceptions.

The way you're getting the column index won't work. Suppose you have the value 1 twice in a column. indexOf is going to return 0 both times because it returns the first valid match. Also, using indexOf inside your 2D loop results in O(n^3) complexity when it could just be O(n).

As to your problem, you can use Resources.getIdentifier() to find the Int ID of a view so you can find the view using findViewById. The alternative would be to use reflection on the binding class to find a field with that name, but that's uglier.

fun <T> View.getChildWithName(name: String): T {
    val id = context.resources.getIdentifier("id", name, context.packageName)
    return findViewById(id)
}

private fun startNewRound() {

    val rows = Array(4) { Array(2) { (1..2).random() } }

    rows.forEachIndexed { rowIndex, row ->
        row.forEachIndexed { colIndex, value ->
            val id = "txtRow${rowIndex   1}Column${colIndex    1}" 
            val view = binding.root.getChildWithName<TextView>(id)
            view.text = when (value) {
                1 -> getString(R.string.strTrue)
                2 -> getString(R.string.strFalse)
            }
        }
    }
}
  •  Tags:  
  • Related