Development issue/problem:
Information is added below to explain in more detail why/what the width/height is limited and when they can be used.
If you are using ConstraintLayout 1.1.0, the correct property is app:layout_constrainedWidth=true instead of the old app:layout_constraintWidth_default=wrap (and its height counterpart). See the updated answer.
If you are using ConstraintLayout 1.0.0 stable (or newer) (currently 1.0.2), see the updated answer for a simpler solution without nested layouts.
Using ConstraintLayouts Beta3, published on 3. November 2016. (Source.)
Here’s what I’m trying to do:
| In order to be able to use this information, it is necessary to have the following information at hand
That’s what I have with this layout:
It looks good, but if the text is longer than the available space….
| |
|
The text display has a style that defines it:
1
1
End
So it should work, but I’m not sure what restrictions I need to have to make the slide of the image correct and then it stops there and the view of the text understands that there is no more space.
What am I missing?
Pay attention: If I set the display width of the text to 0dp, it works, but the image is always on the right side (the horizontal bias seems to be ignored for this).
Note 2 : I also tried it with beta2, in fact beta3 seems to have a bug in the visual editor.
UPDATE: I tried copying it to Xcode/AutoLayout:
This is what the short text looks like.
Now the same layout, I type a long text in the text view….
As you can see, the track border (right) to view the image indicates that you are 8 or more points away from the right edge.
It is also attached to the left side of the label (textView).
From what I’ve just learned on Twitter, this may not be possible on Android ConstraintLayout at the moment: Source:
How can I solve this problem?
Solution 1:
UPDATEJULY 2020: What is the effect of limited width/height?
Many people asked me what this limited width/height does when it is set to where (by default it is false).
I finally got an answer (from a Google employee), so instead of removing the doubts that people who come to this post still have, here’s what I’ve collected (a few of my words, a few direct quotes from Google’s original question about quotes.
ConstraintLayout must define the size of each affected view, and depending on how the specified view is reduced, it must perform different calculations.
With regard to:
- if it’s a fixed dimension, CL just uses that dimension.
- If it matches the parent, CL uses the exact measurement of the parent.
- if it is a wrap_content, the CL will ask the widget for its size and then use it as a fixed dimension
- if it’s 0dp, the CL applies size restrictions.
1) Fixed measurement
This is a view with a fixed width/height, for example B. 24dp. In this case the CL only uses this value, no further calculation is needed for this widget in terms of size.
2) match_older
I always thought this didn’t apply to CL, but it turns out that it behaves the same as in previous versions, it catches the size of the parent and uses it as a patch. Contrary to point 1 above, I assume that the calculation can be more computationally intensive, since CL now has to make sure that the dimensions of the parents are known to be able to use them here. I have no proof or a lot of experience because I always thought it wasn’t valid, so I never used it.
3) wrap_content
As expected, the image must determine the required size, i.e. if it is B. an ImageView, it will retrieve the size based on the source. Once the specified number is received, it is used as a fixed quantity such as #1.
4) 0dp
In this case, CL shines by applying restrictions to each measurement (width and height) and by determining the value of the measurement based on the results of the algorithm.
Then why is it necessary (limited width/height)?
The first thing to understand is that 0dp has a spread and wrap (and percentage) behaviour; for the wrap, the engine works with a wrap_content view format (#3 above), but waits for restrictions to adjust it if necessary. Suppose you use an envelope with the width of a text view, and its limitations tie it to the edges of the screen (beginning/end of the mother view).
They can be dragged in different directions; the text display will probably have to be small to wrap the text, and the restrictions will drag the edges of the widget to reach the beginning/end of the parent. There’s a fight going on here. (If the text has more space, the battle is still there, but in reverse).
The reason for the presence of this attribute is that some widgets (e.g. textView) use multiple links and do not always correctly update to 0dp. It is important to note that LinearLayouts did the same with 0dp + weight (hence the LL problem); with a limited width/height a widget like TextView can use 0dp correctly with wrapping behaviour if needed; it allows the view to re-measure itself correctly.
This problem is most common when reusing TexViews (I don’t know what other viewpoints would benefit from it, but I think everything with text tends to have shortcuts/calculations and may need this extra information to properly initiate a new action). The reuse of a text widget in the form of TextView is most necessary. Think of a RecyclerView where your ViewHolder is in the (quite normal) ConstraintLayout, when you scroll the ViewHolder is reused and linked to another data model, and without this attribute the TextView will not / cannot be adapted for a new text that might appear in the future.
I hope that makes sense.
tl;dr: this is a workaround to address the potential problems associated with the fact that some widgets cannot recalculate their size when reusing, especially, but probably not only, RecyclerView.
That’s all I’m saying.
UPDATED IN JULY 2018:
If you are using ConstraintLayout 1.1.0, the correct property app:layout_constrainedWidth=true instead of the old app:layout_constraintWidth_default=wrap (and its height counterpart) is
UPDATED NOVEMBER 2017
I use Constraint Layouts 1.0.2 and found a less complicated solution using app:layout_constraintWidth_default=wrap (a property introduced in version 1.0.0 but not in the beta version of this message).
Instead of FrameLayout with LinearLayout, you can now remove all this and keep it as it is:
// …IT’S THE KEY TO HOW IT WORKS.
In fact, it does exactly what I want it to do, without any hack, without any recommendations, without any rigid prescribed measures.
The TextView will use the size specified by the restrictions (which under normal circumstances would mean that it is incorrect or larger than the parent one), but with the new attribute these restrictions can be folded/reduced if the content is smaller/larger.
I have to say this works much better than the IOS priorities. (At least I’m much easier to understand). Give Google a pat on the back on this occasion.
Old answer (if you still need it).
Based on Nicolas Roord’s answer, I wanted to create a custom container that basically calculates the available space and sets the maximum width of the TextView by programming. Instead of adding another class, a unit test, a set of possible errors, etc., you can add a new class. Instead of adding another class, a unit test, a set of possible errors, etc. to the project, I have tried a slightly less efficient method of nesting a few planes; given that we have nested planes from the beginning, and that it is not too much (or not at all) in a drop-down view or displacement list, and that I use ConstraintLayouts to smooth out most of the hierarchy (like never before!), I don’t think this little nest, until it is better supported, is that bad.
So basically I used FrameLayout, which is designed to be optimized (or intended) to have one child (i.e. it can contain more). This FrameLayout is a framework in which the ConstraintLayout rules are applied in a similar way:
So, in my real application this FrameLayout is in another ConstraintLayout which has an icon on the left side and a few other things, but for this example, imagine that you have to attach the left/right side of this FrameLayout to the space you want to occupy. In this example you can see that I use the parent in all restrictions, but there may be other widgets to the left and right of this FrameLayout; thanks to the magic of the ConstraintLayout it takes up all the available space.
And here’s the second part of the tip…. Because ConstraintLayout ensures that FrameLayout uses all the space we have, and never more (or less), I can now use LinearLayout indoors, so…
Attentive readers will notice that LinearLayout has a wrap_content width, which is important because the child TextView can then have a width of 0dp and a weight of 1, which means that it takes up all the free space available after all other widgets have calculated their width.
In this particular case, the cursor of the other child element (ImageView) does not have a fixed weight and width, so TextView does not have to share the free space and can occupy it completely (but only the free space, remember that the width is 0dp).
This less efficient approach allows me to get exactly what I wanted, but with less coercive layout magic, if you like.
On the other hand, I didn’t have to create a custom view, do the calculations, and do the output requestLayout() after all the calculations; this less efficient approach will/must be scaled, and until ConstraintLayout offers a suitable alternative, that might be enough.
Congratulations to the Google engineers who responded to the social media and eventually took the time to think about it. Maybe in the future, when they write their homework and talk about ConstraintLayout 1.1, they will remember it and find a good solution.
Solution 2:
In fact, here is how you can do it for TextViews — use android:maxWidth :
This is not exactly what you asked for (you need to know it and set the size to limit the width), but it may help you until we support it in the ConstraintLayout itself.
Solution 3:
For ImageView, you can use the relative position in the restriction format with negative fields. Note android: layout_marginRight=26dp and android: layout_marginLeft=-26dp
For long text:
.
Solution 4:
In my case an update of July 2018 of Martin does not work:
If you are using ConstraintLayout 1.1.0, the correct property is
app:layout_constrainedWidth=true instead of the old
app:layout_constraintWidth_default=wrap (and its height counterpart)
I need to use android:width=wrap_content to display text with app:layout_constrainedWidth=true.
android:layout_width=0dp (match_constraint) makes the display of text stretched for shorter lines in my case.
Another way to get the same result would be to use android:layout_width=0dp with the flag app:layout_constraintWidth_max=wrap.
To learn more about compulsive layout flags, see:
https://developer.android.com/reference/android/support/constraint/ConstraintLayout.
Solution No 5:
This answer is inspired by Martin Marconcini’s (https://stackoverflow.com/a/40491128/1151701).
To reduce the hierarchy, you can replace the restriction format with a simple view.
By the way, I use ConstraintLayout androidx.constraintlayout:2.0.0-alpha3, but app:layout_constrainedWidth=true works as expected in this case. So I used app:layout_constraintWidth_default=wrap here
Good luck!
Related Tags:
textview maxlines,android spinner ellipsize,android spannable – ellipsize,android-edittext ellipsize not working,android textview ellipsize=middle not working,autocompletetextview ellipsize not working,constraintlayout barrier,constraint layout margin not working,constraintlayout guideline center,constraint guideline percent,layout_constrainthorizontal_bias,constraintlayout guideline relative to view,type of viewgroup,kotlin constraint layout programmatically,constraintlayout 50 50,constraint layout distribute evenly,constraint layout one below another,constraintlayout fill remaining space,constraintlayout anchor,constraint layout cheat sheet,constraint layout bounds,android ellipsize end not working constraintlayout