Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange change in ConstraintLayout behavior from 1.1.2 to 1.1.3

I have noticed a strange change in ConstraintLayout behavior from 1.1.2 to 1.1.3 which can cause a lot of problems in layout. In addition, I personally believe it is a bug, because this behavior should be incorrect.

Check following Layout:

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">    
<Button
    android:id="@+id/test1_btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="test1"
    app:layout_constraintTop_toTopOf="@id/test2_btn"
    app:layout_constraintBottom_toBottomOf="@id/test2_btn"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toStartOf="@id/test2_btn"
    app:layout_constraintHorizontal_chainStyle="spread_inside"
    app:layout_constraintHorizontal_bias="1"/>

<Button
    android:id="@+id/test2_btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="test2"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toEndOf="@id/test1_btn"/>
</android.support.constraint.ConstraintLayout>

Here is how this layout is rendered in both version 1.1.2 and 1.1.3 of ConstraintLayout:

enter image description here

Now we add android:visibility="gone" to test1_btn. In ConstraintLayout version 1.1.2, layout is rendered as follows:

enter image description here

This is completely logical, because we have app:layout_constraintHorizontal_bias="1" set, so test2_btn should stay at far right of the chain. Now if we use ConstraintLayout version 1.1.3, layout will be rendered as follows:

enter image description here

Just what happened? Why I lost chain bias?

like image 472
Afshin Avatar asked Jan 02 '23 14:01

Afshin


2 Answers

To get the old behavior while still using version 1.1.3, add this attribute to your <ConstraintLayout> tag:

app:layout_optimizationLevel="direct|barrier"

Version 1.1 of the ConstraintLayout library introduced new optimizations. These optimizations parse your ConstraintLayout and look for constraints that can be removed or simplified.

As of version 1.1.2, the only optimizations enabled by default were direct and barrier. Version 1.1.3 also enables chain by default. You can return to the 1.1.2 behavior by manually specifying which optimizations should be enabled.


For another way to show that this is the real issue, I tried enabling the chain optimizations while using version 1.1.2.

The first screenshot is taken using version 1.1.2 and your posted layout (with the android:gone attribute added). I then added this attribute to the root ConstraintLayout tag:

app:layout_optimizationLevel="chains"

and now I see the same behavior you found in version 1.1.3:

like image 117
Ben P. Avatar answered Feb 10 '23 22:02

Ben P.


I looks like you have identified a problem, but not for the reason you think IMHO. If you look at the documention for ConstraintLayout bias under "Positioning," it states:

The default when encountering such opposite constraints is to center the widget; but you can tweak the positioning to favor one side over another using the bias attributes:

layout_constraintHorizontal_bias would apply to the widget and not the chain. Bias of a chain is affected, however, if the chain is a packed chain and bias is applied to a widget in the chain. It is unclear what should happen when the chain is spread_inside since this chain type dictates that the end widgets adhere to the sides.

The same documentation states:

GONE widgets, as usual, are not going to be displayed and are not part of the layout itself (i.e. their actual dimensions will not be changed if marked as GONE).

But in terms of the layout computations, GONE widgets are still part of it, with an important distinction:

  • For the layout pass, their dimension will be considered as zero (basically, they will be resolved to a point)
  • If they have constraints to other widgets they will still be respected, but any margins will be as if equals to zero

So, a GONE widget should still participate in the chain - it just has dimensions of zero. In your example, I would expect the right TextView to remain stationary when the visibility of the left TextView is changed to GONE. So, the behavior of 1.1.2 seems to be correct while 1.1.3 does seem to be inconsistent with the documentation.

like image 29
Cheticamp Avatar answered Feb 10 '23 22:02

Cheticamp