Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use group in ConstraintLayout to listen for click events on multiple views

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?

like image 281
Endzeit Avatar asked Oct 14 '17 11:10

Endzeit


People also ask

How do I set click listener?

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.

Is constraint layout a view group?

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.

Should you use ConstraintLayout?

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.


2 Answers

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.

like image 92
Cheticamp Avatar answered Oct 05 '22 00:10

Cheticamp


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.

like image 36
Vitthalk Avatar answered Oct 05 '22 02:10

Vitthalk