Search code examples
androidperformancekotlinandroid-constraintlayoutandroid-motionlayout

Multiple view click events using nested constraint layout (2.0.0 beta 2)


I have created my layout with ConstraintLayout and as ConstraintLayout allows you to build complex layouts without having to nest View. In my case, I want multiple view click events.

I have tried using Group as you can get a list of ids that are members of your Group in your code and set click listener.

 fun Group.setAllOnClickListener(listener: View.OnClickListener?) {
            referencedIds.forEach { id ->
                rootView.findViewById<View>(id).setOnClickListener(listener)
            }
        }

However, this does not seem to work as of the ConstraintLayout version 2.0.0-beta2. This code is working till 2.0.0-alpha3. I have implemented using multiple ConstraintLayout so is it alright to use nested constraint layout?

I am using MotionLayout and other animation of constraint layout so I can't use a lower version of ConstraintLayout.


Solution

  • There has been a change to when a group's referenced ids are available. Before 2.0.0-beta2, they are available immediately in onCreate(). It seems that with 2.0.0-beta2, they are only available post-layout. I am not sure if this is documented or if it is just a side-effect.

    The following will work for you in 2.0.0-beta2:

    class MainActivity : AppCompatActivity() {
        fun Group.setAllOnClickListener(listener: View.OnClickListener?) {
            referencedIds.forEach { id ->
                rootView.findViewById<View>(id).setOnClickListener(listener)
            }
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            // Referenced ids are not available here but become available post-layout.
            layout.post {
                group.setAllOnClickListener(object : View.OnClickListener {
                    override fun onClick(v: View) {
                        val text = (v as Button).text
                        Toast.makeText(this@MainActivity, text, Toast.LENGTH_SHORT).show()
                    }
                })
            }
        }
    }