41

I have a gray area in understanding the use of Constraint Layout.

I have implemented my layout with Constraint Layout. But It happens that I want to make a group of the view items to act as one view, for example making two ImageViews and a TextView to respond to click like a single view so I need to put them in another layout and use this layout to respond to click. I am wondering is it alright to put them in another Constraint Layout ( other layouts can not give the arrangement of views that I want to have) which will led to having nested Constraint Layout in a single layout.

So generally is it alright to have nested Constraint Layout or it will be a wrong practice regarding the purpose of it (i.e. having flat layout)?

Edit

As in answers there are suggestions for setting listener for each of these views instead of setting it for their parent layout, I have already tested this approach and it is not what I need. An example is when I have a customized button with text and a drawable (which I can't make it with drawableLeft or drawableRight attributes of a button itself because it won't look like what we had in design). So as you see I can't make ImageView and TextView listen to the click individually because user will see two different click effect and it won't look like a single button click.

Akram
  • 2,158
  • 1
  • 17
  • 24

4 Answers4

12

Based on this article from android developers blog. I would like to mention few things. You can read the complete article and decide for yourself but I would like to mention few key points.

1. How android draws Views

When a user brings an Android view into focus, the Android framework directs the view to draw itself. This drawing process comprises 3 phases:

  1. Measure: measure view and view groups.
  2. Layout: determine position of childview based on measure.
  3. Draw: Create canvas for each object and draw the view.

Each phase within the drawing process requires a top-down traversal of the view tree. Therefore, the more views you embed within each other (or nest) into the view hierarchy, the more time and computation power it takes for the device to draw the views. By keeping a flat hierarchy in your Android app layouts, you can create a fast and responsive user interface for your app.

As constraint layout will allow you to create a flat hierarchy that will use less computational power and will be faster. Based on the result of tests performed against traditional layout, you can see the results below.

enter image description here

Based on my understanding of the way layout works and behaviour of constraint layout, your nested constraint layout will be faster than all traditional layout, But due to nesting it will be slower than complete flat hierarchy. Also, to accomplish your goal of allowing user to click, why not set click listeners to both the view that should work out for you.

Community
  • 1
  • 1
karan
  • 8,637
  • 3
  • 41
  • 78
  • 3
    what exactly is your understanding based on? Because everything you quote here does not take nesting into account – Tim Dec 17 '18 at 11:26
  • @TimCastelijns : while drawing view system will require top-down traversal of view tree, so more the nesting, more time and computational power it takes to draw the particular view. – karan Dec 17 '18 at 11:32
  • @KaranMer I have edited my questions and explained why I can't do it with setting listener for each of the view. – Akram Dec 17 '18 at 11:34
  • @Merka : than you can continue using your approach. – karan Dec 17 '18 at 11:40
  • 1
    It could well be an outlier, but we cut measure+layout times from 1.5s to <0.5s in a complex and large layout where nested ConstraintLayouts were previously used. We switched to using more deeply nested LinearLayouts, but the overall performance was improved *very* significantly (both in startup time and CPU usage). – necavit Apr 20 '21 at 15:19
11

I wouldn't nest multiple constraint layouts as that would negate the purpose of flatness as you mention, but if it's just the one, I wouldn't worry about memory efficiency and flatness. As a solution though, you could include a transparent view to cover the group that you want to respond to a single click, and have that overlay view absorb the click. All you have to do is constrain it to the edges of the other views and still maintain one parent constraint layout.

EDIT: After your updated question, I think there's no option for you but create that nested layout. Lint has the max number of nested layouts set to 10, so that alone is an indicator of the threshold that nested layouts can be damaging to the overall performance. I wouldn't worry too much about one nesting layout. You can use systrace for your scenario and see that the difference in time is probably insignificant.

Nikos Hidalgo
  • 3,666
  • 9
  • 25
  • 39
6

Probably you want to create a Group in your constraint layout and set a click listener for it.

Check the accepted answer for this one. Use group in ConstraintLayout to listen for click events on multiple views.

Catluc
  • 1,775
  • 17
  • 25
  • I have edited my questions and explained why I can't do it with setting listener for each of the view. It won't have the effect that is intended in design. – Akram Dec 17 '18 at 11:35
  • The u should try to extend button and create it ur way, in this way u wouldn´t have nested layout. This can be overkilling, but it´s answering ur question – Catluc Dec 17 '18 at 12:49
  • Yes, it will solve it for one button but I have different buttons with different designs. Also I have other cases which it is not a button but I need similar behavior. I expect some feature in `Constraint Layout` that make it possible without nesting layouts. This design requirement ruins the philosophy of `Constraint Layout`. – Akram Dec 17 '18 at 13:44
  • 1
    Group is designed for maintain the visibility, not for click events. It is not a good design (you cannot achieve the click effect for multiple views, ...). – Francis Mar 29 '20 at 16:50
1

You can achieve a single click event for a group of views in a ConstraintLayout by wrapping the views with a generic View where you constrain the start, top, bottom, end of the desired area around the views you want to be grouped together for the click event.

<View
  android:id="@+id/image_click_container"
  android:layout_width="0dp"
  android:layout_height="0dp"
  app:layout_constraintTop_toTopOf="iv_1"
  app:layout_constraintBottom_toBottomOf="iv_2"
  app:layout_constraintStart_toStartOf="iv_1"
  app:layout_constraintEnd_toEndOf="iv_2"
/>

<ImageView
  android:id="@+id/iv_1"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  app:layout_constraintStart_toStartOf="parent"
  app:layout_constraintTop_toTopOf="parent"
/>

<ImageView
  android:id="@+id/iv_2"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  app:layout_constraintStart_toEndOf="iv_1"
  app:layout_constraintTop_toBottomOf="iv_1"
/>

Then in the code you could bind it like this

binding.imageClickContainer.setOnClickListener {
   //on click listener code for the area around both image views
}

This way there is no need to nest layouts, you get to keep the performance of a flat hierarchy.

thesultan192
  • 169
  • 9