Search code examples
androidkotlinandroid-viewbinding

How can I shorten this code in Android using view binding by Kotlin?



override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        select(viewBinding.btnPearKind1)
        select(viewBinding.btnPearKind2)
        select(viewBinding.btnPearKind3)
        select(viewBinding.btnPearKind4)
        select(viewBinding.btnPearKind5)
        select(viewBinding.btnPearKind6)
    }

Clicking one button changes the other 5 buttons.

I use these functions.

fun select(btn: Button){
        btn.setOnClickListener {      
            val kind = listOf("1","2","3","4","5","6")
            for(i in kind) {
                    if (i != btn.tag){
                        viewBinding.kindGrid.findViewWithTag<View>(i).backgroundTintList =
                            ContextCompat.getColorStateList(it.context, R.color.btn_color_off)
                    }else{
                        viewBinding.kindGrid.findViewWithTag<View>(i).backgroundTintList =
                            ContextCompat.getColorStateList(it.context, R.color.btn_color)
                    }
            }
        }
    }

When I wrote it with view combination, the duplicate code came out like this. How can I reduce it?


Solution

  • Your select function is already hardcoded to find all the buttons in the view hierarchy by the looks of it? Personally I'd just repurpose that code to create a button lookup, and then you can use that for easy click listener setting and UI changes:

    lateinit val buttons: List<Button>
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val tags = listOf("1","2","3","4","5","6")
        // look up all your buttons, creating a list of Button views
        buttons = tags.map { tag ->
            viewBinding.kindGrid.findViewWithTag<Button>(tag)
        }
        // now you can just apply a click listener to each of them
        buttons.forEach {
            setOnClickListener { view -> select(view as Button) }
        }
    }
    
    fun select(selected: Button){
        buttons.forEach { button ->
            // you could check the tags, but since we have a list of all the actual
            // buttons, we can just check which of them has been passed in
            val colour = if (button == selected) R.color.btn_color else R.color.btn_color_off
            button.backgroundTintList = ContextCompat.getColorStateList(it.context, colour)
        }
    }
    

    You could also do tags.associateWith instead of map to build up a tag -> Button Map, if you needed to directly look up a button by tag instead of iterating over them