Basically I'd like to attach a single OnClickListener to multiple views inside a ConstraintLayout.
Before migrating to the ConstraintLayout the views where inside one layout onto which I could add a listener. Now they are on the same layer with other views right under the ConstraintLayout.
I tried adding the views to a android.support.constraint.Group
and added a OnClickListener to it programmatically.
group.setOnClickListener { Log.d("OnClick", "groupClickListener triggered") }
However this does not seem to work as of the ConstraintLayout version 1.1.0-beta2
Have I done something wrong, is there a way to achieve this behaviour or do I need to attach the listener to each of the single views?
Link the button from the XML by calling findViewById() method and set the onClick listener by using setOnClickListener() method. setOnClickListener takes an OnClickListener object as the parameter.
With groups, you can logically group together certain views. Don't confuse this with normal ViewGroups in Android though. A group in ConstraintLayout only contains references to the view ids and not nesting the views inside a group.
Well, each layout has its own benefits but when it comes to complex, dynamic and responsive views you should always choose Constraint Layout. Constraint Layout was added to Android Studio 2.2 in 2016 and it became the default layout of Android Studio because of its simplicity and ease of creating complex layouts.
The Group
in ConstraintLayout
is just a loose association of views AFAIK. It is not a ViewGroup
, so you will not be able to use a single click listener like you did when the views were in a ViewGroup
.
As an alternative, you can get a list of ids that are members of your Group
in your code and explicitly set the click listener. (I have not found official documentation on this feature, but I believe that it is just lagging the code release.) See documentation on getReferencedIds
here.
Java:
Group group = findViewById(R.id.group); int refIds[] = group.getReferencedIds(); for (int id : refIds) { findViewById(id).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // your code here. } }); }
In Kotlin you can build an extension function for that.
Kotlin:
fun Group.setAllOnClickListener(listener: View.OnClickListener?) { referencedIds.forEach { id -> rootView.findViewById<View>(id).setOnClickListener(listener) } }
Then call the function on the group:
group.setAllOnClickListener(View.OnClickListener { // code to perform on click event })
Update
The referenced ids are not immediately available in 2.0.0-beta2 although they are in 2.0.0-beta1 and before. "Post" the code above to grab the reference ids after layout. Something like this will work.
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() } }) } } }
This should work for releases prior to 2.0.0-beta2, so you can just do this and not have to do any version checks.
The better way to listen to click events from multiple views is to add a transparent view as a container on top of all required views. This view has to be at the end (i.e on top) of all the views you need to perform a click on.
Sample container view :
<View android:id="@+id/view_container" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="@+id/view_bottom" app:layout_constraintEnd_toEndOf="@+id/end_view_guideline" app:layout_constraintStart_toStartOf="@+id/start_view_guideline" app:layout_constraintTop_toTopOf="parent"/>
Above sample contains all four constraint boundaries within that, we can add views that to listen together and as it is a view, we can do whatever we want, such as ripple effect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With