I was having trouble getting some views to wrap to the correct height while matching constraints, and I managed to condense my issue down to a single text view.
For some reason, when I'm using layout_constrainedWidth and layout_constrainedHeight, they can't handle text views that just barely wrap onto the next line.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="64dp"
android:layout_marginBottom="8dp"
android:text="If a single word wraps onto the next line it is cut off one"
android:visibility="visible"
app:layout_constrainedHeight="true"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
I'm actually using it on a scroll view that contains some text views, and it doesn't work at all unless I also apply it to the child views as well.
Is this a bug in Android?
Yes, it was a bug in Android.
https://issuetracker.google.com/issues/123551995
Google marked it as resolved with the release of ConstraintLayout 2.0 beta 2
Related
I have a widget that, no matter what constraints I place upon it and other widgets, including the addition of barriers, always positions itself at the top of the layout.
This is a fairly simple arrangement of two rows of two elements each, not aligned column wise. The first element in each row is a TextView label, the second an input (Spinner).
There is also a lone TextView title above the first row stretching all the way across. By my understanding and previous experience with constraint layout, this shouldn't require a barrier between the rows, and that was my initial version.
This is the design view, where the selected element ("Credentials") is supposed to be in the second row but instead appears above the first row, over top of the title TextView ("PKIX"):
Actual result in the emulator looks much the same. The selected "Credentials" element is the fourth of five elements in the XML layout below. All of the other elements are in the right place.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="#+id/addsrv_pkix_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#drawable/bottomborder"
android:text="PKIX"
android:textAlignment="center"
android:layout_marginHorizontal="10sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#+id/addsrv_trust_lbl"
/>
<TextView
android:id="#+id/addsrv_trust_lbl"
android:text="Trust"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#+id/addsrv_trust_spin"
app:layout_constraintTop_toBottomOf="#+id/addsrv_pkix_title"
app:layout_constraintBaseline_toBaselineOf="#+id/addsrv_trust_spin"
app:layout_constraintBottom_toTopOf="#+id/addsrv_cred_lbl"
/>
<Spinner
android:id="#+id/addsrv_trust_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#+id/addsrv_trust_lbl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/addsrv_pkix_title"
app:layout_constraintBottom_toTopOf="#+id/addsrv_cred_spin"
/>
<TextView
android:id="#+id/addsrv_cred_lbl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:paddingHorizontal="10sp"
android:text="Credentials"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#+id/addsrv_cred_spin"
app:layout_constraintTop_toBottomOf="#+id/addsrv_trust_lbl"
app:layout_constraintBaseline_toBaselineOf="#+id/addsrv_cred_spin"
/>
<Spinner
android:id="#+id/addsrv_cred_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#+id/addsrv_cred_lbl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/addsrv_trust_spin"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
I'm perplexed. The addsrv_cred_lbl TextView ("Credentials") is:
Start aligned with parent.
End aligned with the addsrv_cred_spin spinner, which appears correctly positioned;
this alignment is reciprocated to create a horizontal chain. They are also baseline
aligned.
Top aligned with the bottom of the TextView above it, addsrv_trust_lbl.
This alignment is also reciprocated.
There's no bottom alignment yet (there's another row to go); bottom aligning it with the parent makes no difference unless I bottom align the spinner from the same row, in which case the result goes from bad to worse.
Since this did not work, I tried to use a barrier between the rows. If I use it as a "top", with the second row widgets as the constraint referents, the barrier appears at the top, above the title, regardless of what constraints are used to position it below the first row. Used as a "bottom", with the first row widgets referenced and the second row chained below it (which is more logical), things are a little bit better in that the barrier appears in the right place -- but the "Credentials" widget is still up top.
The design view of this looks exactly the same as the previous one except the barrier is visible below the first row. In the XML, I aslo added optimizationLevel="none" after having read this can help with misbehaving barriers (but it made no difference). There's also a few stylistic elements added back here (such as font size) I removed for brevity before.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
app:layout_optimizationLevel="none"
>
<TextView
android:id="#+id/addsrv_pkix_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#drawable/bottomborder"
android:backgroundTint="#color/tbar"
android:text="PKIX"
android:textAlignment="center"
android:textSize="#dimen/addsrv_bigfont"
android:textColor="#color/titleText"
android:layout_marginHorizontal="10sp"
app:layout_constraintBottom_toTopOf="#+id/addsrv_trust_lbl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="#+id/addsrv_trust_lbl"
android:text="Trust"
android:textSize="#dimen/addsrv_fontsz"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#+id/addsrv_trust_spin"
app:layout_constraintTop_toBottomOf="#+id/addsrv_pkix_title"
app:layout_constraintBaseline_toBaselineOf="#+id/addsrv_trust_spin"
app:layout_constraintBottom_toTopOf="#+id/addsrv_bar1"
app:layout_constraintHorizontal_chainStyle="packed"
/>
<Spinner
android:id="#+id/addsrv_trust_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#+id/addsrv_trust_lbl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/addsrv_pkix_title"
app:layout_constraintBottom_toTopOf="#+id/addsrv_bar1"
/>
<androidx.constraintlayout.widget.Barrier
android:id="#+id/addsrv_bar1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="bottom"
app:constraint_referenced_ids="addsrv_trust_lbl,addsrv_trust_spin"
app:layout_constraintBottom_toTopOf="#+id/addsrv_cred_lbl"
/>
<TextView
android:id="#+id/addsrv_cred_lbl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10sp"
android:text="Credentials"
android:textSize="#dimen/addsrv_fontsz"
app:layout_constraintBaseline_toBaselineOf="#+id/addsrv_cred_spin"
app:layout_constraintEnd_toStartOf="#+id/addsrv_cred_spin"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/addsrv_bar1" />
<Spinner
android:id="#+id/addsrv_cred_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#+id/addsrv_cred_lbl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/addsrv_bar1"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
Am I correct in observing that some of the constraints on addsrv_cred_lbl are being completely ignored? Doesn't topToBottom mean that the top of the widget is aligned with the bottom of the other? Instead, it seems simply to mean that they will be connected with a squiggly, potentially curved and convoluted line in the design view, and the spacial relation of the two widgets is arbitrary, such that the semantic logic might as well be inverted, "top = bottom, bottom = top", etc.
Please note that I do not want to use absolute values to position anything. If the only way to get this to work is to do that, constraint layout seems a complete waste of time even in this simple case, and I'd rather just stack some liner layouts.
The problem is that Spinner doesn't have a baseline. You were trying to tie it to the baseline of the item inside the Spinner is my guess - ConstraintLayout can't reach children of its children.
You can check it via the design tab with a right click. TextViews will show an option "Show baseline" but the Spinner doesn't.
Also snippet from the doc
Align the text baseline of a view to the text baseline of another
view.
That's what baselines are for, if you want two TextViews connect together so they don't have the height where the text starts messed up.
I think there is a tiny flaw in your approach to the chain. You were setting the top constraint of both elements in each row to the bottom of the previous row(or title in the first row). Even if the Spinner would have a baseline, this would make the label off-centered in relation to the Spinner(slightly higher because the baseline of a text is higher than the actual bottom of the view).
I think the best approach in these types of layouts is to have one guiding element(which is also the element of the chain) that represents the row and let other elements be positioned in relation to it.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="#+id/addsrv_pkix_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="PKIX"
android:textAlignment="center"
android:layout_marginHorizontal="10sp"
app:layout_constraintVertical_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#+id/addsrv_trust_spin"
/>
<TextView
android:id="#+id/addsrv_trust_lbl"
android:text="Trust"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#+id/addsrv_trust_spin"
app:layout_constraintTop_toTopOf="#+id/addsrv_trust_spin"
app:layout_constraintBottom_toBottomOf="#+id/addsrv_trust_spin"
/>
<Spinner
android:id="#+id/addsrv_trust_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#+id/addsrv_trust_lbl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/addsrv_pkix_title"
app:layout_constraintBottom_toTopOf="#+id/addsrv_cred_spin"
/>
<TextView
android:id="#+id/addsrv_cred_lbl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10sp"
android:text="Credentials"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#+id/addsrv_cred_spin"
app:layout_constraintTop_toTopOf="#+id/addsrv_cred_spin"
app:layout_constraintBottom_toBottomOf="#+id/addsrv_cred_spin"
/>
<Spinner
android:id="#+id/addsrv_cred_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#+id/addsrv_cred_lbl"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/addsrv_trust_spin"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
NOTE: I added the last bottom constraint to the parent and "spread" to the chain for demonstration but also know that if you don't have the bottom of the last view constrained to something - it's not a chain.
Working with ConstraintLayout is easy if you obey few simple rules:
Create one chain. That means Views hooking to each other reciprocally, all the way.
Now that you have a working chain, you can manipulate it with layout_constraintVertical_bias and layout_constraintVertical_chainStyle. If changing those does nothing, it means your chain is broken.
hook remaining Views to ones laid out by the chain
every control must have 4 constraints: top, bottom, start and end
do not create competing chains and try to force them into working together.
Spinner cannot have baseline, only TextView and its descendants have it. Spinner is AdapterView, so it can contain whatever you can imagine.
BTW: don't use #+id to refer to existing ids. Plus means creating new id, so if you make a typo it will create new id that refers to nothing instead of error "there's no such id".
Here's an example: top label and Spinners form the main chain and side labels are positioned each to their Spinner:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
>
<TextView
android:id="#+id/addsrv_pkix_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10sp"
android:background=""
android:text="PKIX"
android:textAlignment="center"
app:layout_constraintBottom_toTopOf="#id/addsrv_trust_spin"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintVertical_chainStyle="packed"
/>
<TextView
android:id="#+id/addsrv_trust_lbl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10sp"
android:text="Trust"
app:layout_constraintBottom_toBottomOf="#id/addsrv_trust_spin"
app:layout_constraintEnd_toStartOf="#id/addsrv_trust_spin"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#id/addsrv_trust_spin"
app:layout_constraintVertical_bias="1.0"
/>
<Spinner
android:id="#+id/addsrv_trust_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="#id/addsrv_cred_spin"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/addsrv_trust_lbl"
app:layout_constraintTop_toBottomOf="#id/addsrv_pkix_title"
app:layout_constraintVertical_bias="0.0"
/>
<TextView
android:id="#+id/addsrv_cred_lbl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10sp"
android:text="Credentials"
app:layout_constraintBottom_toBottomOf="#id/addsrv_cred_spin"
app:layout_constraintEnd_toStartOf="#id/addsrv_cred_spin"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#id/addsrv_cred_spin"
app:layout_constraintVertical_bias="1.0"
/>
<Spinner
android:id="#+id/addsrv_cred_spin"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/addsrv_cred_lbl"
app:layout_constraintTop_toBottomOf="#id/addsrv_trust_spin"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
My layout includes:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="#+id/btnFindPOIs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="Find POIs"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/btnGetLocation" />
<TextView
android:id="#+id/txtPoiDetails"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/btnFindPOIs" />
</androidx.constraintlayout.widget.ConstraintLayout>
When the content of TextView extends beyond one line it correctly flows to a second line but the text extends right to the edge of the screen ignoring the 16dp left and right margins.
Layout Margin affects the View object, in this case a TextView. Not the actual text inside the object. So it will still go right up against the object's edge.
I would recommend using padding, it will directly affect the text. You may also want to consider adding gravity to the object?
I would also recommend using layout weights on these views or you are going to have resizing issues!
android:paddingStart="16dp"
Cheers!
I am developing an android application to display current news or events. But, starting the interface with the toolbar and the login page, I have a problem with ConstraintLayout. I do not know why but the textview and imageview are red while in RelativeLayout and LinearLayout it works.
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.exemple.rivoramampiandra.appsname.MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Connexion"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.079" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent" />
<EditText
android:id="#+id/editText"
android:layout_width="367dp"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
tools:layout_editor_absoluteX="9dp"
tools:layout_editor_absoluteY="85dp" />
Seeing your code would help a lot in solving the problem, some guesses though might be:
Constraints were not added to the TextView and ImageView as each view place in the UI must be constrained to its parent or child in some way
https://developer.android.com/training/constraint-layout/index.html#add-a-constraint
If you converted the ConstraintLayout to a RelativeView or a LinearLayout. It is possible the attributes are left in the XML of the constrained attributes within the children views inside your layout. thosapp:layout_constraintBaseline_toBaselineOf="#+id/text_title"
https://medium.com/exploring-android/exploring-the-new-android-constraintlayout-eed37fe8d8f1
Hope any of this solved your problem!
I have a constraint layout inside a ScrollView. This ConstraintLayout is supposed to be a parent for other Views that will be added into it, as shown:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.ConstraintLayout
android:id="#+id/generated_main_constraint"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.constraint.ConstraintLayout>
When I try to add view to this ConstraintLayout, I inflate the view from XML, with the following code:
(ConstraintLayout) getLayoutInflater().inflate(R.layout.box_npcs, MAIN_CONSTRAINT, false);
This layout is defined in XML1 (end of the question).
Then I add TextViews with information to this Layout's LinearLayout, for that I use a programatically created TextView and add it into the layout
linearLayout.addView(new TextView("Foo"));
With that setup, I add this box to the main constraint layout.
The problem is: When I try to add more than 5 views, it takes a long time to proccess the UI, taking up to 5 seconds on the max amount of view to be added (50).
How can I add Complex Views to a ConstraintLayout in a way that it doesn't lag when trying to add the views?
XML1:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/box_npcs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="#+id/npcImage"
android:layout_width="88dp"
android:layout_height="88dp"
android:layout_marginBottom="0dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:scaleType="fitXY"
app:layout_constraintBottom_toBottomOf="#+id/layoutInformation"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="#+id/layoutInformation"
app:srcCompat="#drawable/camera" />
<android.support.constraint.ConstraintLayout
android:id="#+id/layoutInformation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="8dp"
android:maxWidth="280dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toRightOf="#+id/npcImage"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/top_priority"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="0dp"
android:layout_marginTop="0dp"
android:ellipsize="start"
android:text="DummyTextIsDummy"
android:textAppearance="#style/TextAppearance.AppCompat.Body1"
android:textColor="#color/common_google_signin_btn_text_light_default"
android:textSize="22sp"
android:textStyle="bold"
android:typeface="normal"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="HardcodedText" />
<LinearLayout
android:id="#+id/linearLayout_high_highest_normal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintLeft_toLeftOf="#+id/top_priority"
app:layout_constraintTop_toBottomOf="#+id/top_priority" />
</android.support.constraint.ConstraintLayout>
Images for examples:
Each 'box' in this screen is a box in the Main Constraint Layout.
Each TextLine is a different TextView added to the LinearLayout
What is the android version in your test device?
A few days ago, I found a problem.
If I use two or more ConstraintLayouts in Android 5 or 6, it will be slow.
When I used the Android Studio CPU Profiler, I saw the com.android.internal.policy.impl.phonewindow$decorview.onmeasure spent much time.
So I tried to use LinearLayout, and the problem was solved.
I think ConstraintLayout in Support Library is not friendly for Android 5 or 6.
I have a XML layout for a ViewHolder inside a RecyclerView.
This layout's root is a ConstraintLayout whose height is set to wrap_content.
Inside this flat hierarchy there are 3 textviews and an image view with a fixed height; think of:
<ConstraintLayout>
<TextView height=wrap>
<TextView height=wrap>
<TextView height=wrap>
<ImageView height=150dp>
</ConstraintLayout>
It's a relatively simple layout. In beta4 this is how it looks in the Designer (and eventually at runtime, each recyclerView cell):
Apologies for the "red tape" but it's NDA blah blah.
That being said, the elements are:
The 3 text views (red taped with a nice purple background)
The ImageView with 150dp height is the gray thing.
The Purple background was applied to the root ConstraintLayout. All nice.
Now this is how it looks, without a single modification with Beta 5:
As you can see the Purple (root) Constraint Layout is now "confused" and doesn't wrap content as it used to.
Things I tried:
Adding app:layout_constraintHeight_default="wrap" to the ConstraintLayout (and spread too). Didn't make a difference.
The ImageView has a app:layout_constraintBottom_toBottomOf="parent" constraint that I tried removing, didn't make a difference either.
Revert back to beta4 :)
For the record, this is the full layout (id's have been renamed for red-tape reasons and no tools:text or similar due to the same reasons). The layout is otherwise exactly the same.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorAccent">
<TextView
android:id="#+id/toplabel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text=""
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="#+id/top_bottom_label"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#+id/top_right_label"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/top_right_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginTop="8dp"
android:ellipsize="end"
android:gravity="end"
android:maxLines="1"
android:text=""
app:layout_constraintBottom_toTopOf="#+id/top_bottom_label"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintLeft_toRightOf="#+id/toplabel"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<TextView
android:id="#+id/top_bottom_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginTop="8dp"
android:ellipsize="end"
android:gravity="end"
android:maxLines="1"
android:text=""
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintLeft_toRightOf="#+id/toplabel"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/top_right_label" />
<ImageView
android:id="#+id/imageview"
android:layout_width="0dp"
android:layout_height="150dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/top_bottom_label"
app:srcCompat="#android:color/darker_gray" />
</android.support.constraint.ConstraintLayout>
Am I supposed to do something different? (I know I can replace this with a RelativeLayout and probably do the same, but anyway… I believe in ConstraintLayout!) :)
I filed a bug about this and I got a workaround.
It's a regression and will be fixed (we hope) but… turns out my Chain is also incorrectly defined. My top_bottom_label does not have a bottom endpoint, and according to the documentation elements in a chain should be connected on both endpoints.
So I added app:layout_constraintBottom_toTopOf="#id/imageview" to the top_bottom_label and this seems to work for my case. I have, effectively added the imageView to the chain, even do I don't really care much for it. It works for now.
Update February 14th 2017: The ConstraintLayout team # Google fixed the issue in master. It will likely be fixed in a next release. (Thanks!).