Textview with long text pushes out other views in GridLayout despite ellipsize=end
Solution 1
I seem to have found a potential solution to prevent a TextView in GridLayout from growing unboundedly and pushing out other views. Not sure if this has been documented before.
You need to use fill layout_gravity and set an arbitrary layout_width or width on the long TextView in need of ellipsizing.
android:layout_gravity="fill"
android:layout_width="1dp"
Works for both GridLayout and android.support.v7.widget.GridLayout
Solution 2
I'm a big fan of LinearLayouts, so here's my suggestion using those:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_weight="1" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="(view1)" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="(view2)" />
</LinearLayout>
Solution 3
I will suggest you to play with layout_weight property of your widget
Example:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="10">
<LinearLayout
android:id="@+id/ll_twoViewContainer"
android:layout_weight="8"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/rl0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
android:text="Long text" />
<TextView
android:id="@+id/rl1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@id/rl0"
android:layout_weight="1"
android:minWidth="120dp"
android:text="(view1)" />
</LinearLayout>
<TextView
android:id="@+id/rl2"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/rl1"
android:layout_alignParentRight="true"
android:layout_marginLeft="10dp"
android:text="(view2)" />
</LinearLayout>
</LinearLayout>
finally your layout will look like as follow:
+----------------------------------------+
| short text [view1] [view2] |
+----------------------------------------+
| long text with ell ... [view1] [view2] |
+----------------------------------------+
Solution 4
I think you should create custom layout for your purpose. I don't know how to do this using only default layouts/view and make it work for all cases.
Solution 5
The trick which worked for me was to use maxWidth to restrict the width of the first view. You need to do it with Java, here is the basic logic:
firstView.setMaxWidth(parentView.getWidth() - view2.getWidth() - view1.getWidth() - padding * 2);
Not pretty, but it works.
Stefan Frye
Java / full stack dev. Owner of Deitmer IT GmbH. Drummer of the Karmakazees. CU Boulder alumni.
Updated on June 09, 2022Comments
-
Stefan Frye about 2 years
My problem is very similar to How to get a layout where one text can grow and ellipsize, but not gobble up the other elements on the layout, but read on below why I can't use TableLayouts as proposed there.
I'm trying to create a listview row that basically looks like this:
| TextView | View 1 | View 2 |
All views contain variable width elements. The TextView has ellipsize="end" set. View 1 should align left of the TextView, while View 2 should align to the right of the screen. So, normally, there would be whitespace between View 1 and View 2. As the text in the TextView grows longer, the TextView should grow, pushing View 1 to the right until there is no more whitespace left. Then, ellipsize should kick in, cutting of the text in TextView and appending an ellipsis ("...") at the end.
So, the result should look something like this:
+----------------------------------------+ | short text [view1] [view2] | +----------------------------------------+ | long text with ell ... [view1] [view2] | +----------------------------------------+
I've tried:
- TableLayouts, but they seem to make scrolling extremely slow on some devices.
- RelativeLayouts, but I either had overlapping views, or view1 or view2 disappeared completely.
- GridLayouts, but the TextView always grows until it takes up the whole width of the screen, thus pushing view1 and view2 out of the screen.
This is the GridLayout I tried:
<GridLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:layout_gravity="left|fill_horizontal" android:ellipsize="end" android:singleLine="true" android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" /> <TextView android:layout_gravity="left" android:text="(view1)" /> <TextView android:layout_gravity="right" android:text="(view2)" /> </GridLayout>
View 1 and View 2 are not really TextViews, I just used them in the example to simplify things.
Is there any way to achieve this without using TableLayouts?
EDIT: As requested, here is my attempt at solving this with a RelativeLayout. The TextView takes up the full width of the screen in this case, so neither view1 nor view2 are visible.
<RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/rl0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:ellipsize="end" android:singleLine="true" android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" /> <TextView android:id="@+id/rl1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/rl0" android:layout_marginLeft="10dp" android:text="(view1)" /> <TextView android:id="@+id/rl2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/rl1" android:layout_alignParentRight="true" android:layout_marginLeft="10dp" android:text="(view2)" /> </RelativeLayout>
-
invertigo almost 11 yearsyeah, i'm just noticing that as well. can you use static widths for any of your views, or do they all have to be wrap_content?
-
Stefan Frye almost 11 yearsUnfortunately, they all have to be wrap_content, as they are all of variable length. If there is no other way, I could set a static size on view2, as there is a maximum size view2 could take. But that would mean quite some whitespace between view1 and view2 in most cases :(
-
invertigo almost 11 yearssorry, try my changed suggestion above, i had "weight" instead of "layout_weight" /facepalm
-
Stefan Frye almost 11 yearsI noticed (and edited) that myself :) It still doesn't work :(
-
invertigo almost 11 yearsalso added layout_weight to the first textview, did you get that in your edit?
-
Stefan Frye almost 11 yearsI didn't. After adding that, I can see both view1 and view2, but view1 is always right-aligned, so if the TextView is short, the whitespace appears between the TextView and view1, instead of between view1 and view2.
-
invertigo almost 11 yearssounds like you might be stuck manipulating the layout programatically then :/
-
Stefan Frye almost 11 yearsNot quite what I asked for, sorry. Using your code, all three views take up about equal space. I want view1 and view2 to take up just as much space as they need, and the TextView to grow as needed until there is no more room.
-
Stefan Frye almost 11 yearsYes, think so, too. Thanks for your time, though.
-
ozbek almost 11 yearsHmm... you can't have unknown width for all three views. You need to have some definitive values. Like, half width for the
TextView
, and the other half forview1 + view2
-
Stefan Frye almost 11 yearsThis gives the same result as invertigos answer. I need a solution for both cases, of course.
-
JJ86 almost 11 years@StefanDeitmer the only think that came in my mind is to add margin on right side of rl1 to my code, if text is short. But you have to determine how many margin you have to set (and i think this is not the best solution). What do you think?
-
Stefan Frye almost 11 yearsThis would be the programmatic solution that I hoped to avoid.
-
Stefan Frye almost 11 yearsI believe this gives the same result as most other answers: whitespace grows between the text and view1 instead of between view1 and view2.
-
Stefan Frye almost 11 yearsSorry, but this doesn't work either. Example 1 has view2 not right-aligned. Example 2 doesn't show view1 at all, and view2 is not right-aligned, again.
-
dinesh sharma almost 11 yearsI have edited the answer after implementing it please have a look. If you still need different thing please feel free to ask
-
Stefan Frye almost 11 yearsAs you show in your diagram, whitespace grows between text and view1 instead of view1 and view2. Answering a question by changing the question doesn't count :)
-
dinesh sharma almost 11 yearsI have worked on it and now looks like as you want but some how you also have to do some changes in that as per your need
-
dinesh sharma almost 11 yearsAlso try to tune in the provided xml for example play with min_width property of the view1 that will help you more :)
-
Stefan Frye almost 11 yearsQuite frankly, I can't see what this has in common with the layout I'm trying to achieve. Also, it is using TableLayouts, which don't work for me, as I said in my question.
-
Stefan Frye almost 11 yearsI really appreciate your effort, but still: there is whitespace between text and view1, which I don't want.
-
Sergii Rudchenko almost 11 yearsSpent a lots of time on this puzzle. The best solution I've came accoss involves a LinearLayout inside of a RelativeLayout plus we have to adjust a certain padding manually in runtime. That's totally don't worth it, writing a custom ViewGroup is going to a cleaner and much more efficient solution.
-
dinesh sharma almost 11 yearsNo one can give the exact output as you want until you sit with the helping buddies or just try to manipulate the things otherwise the efforts of the people will be worthless.
-
Armaan Stranger almost 11 yearsthis is just another example. i wanted to show you weight usage in it.
-
Leonidos almost 11 yearsYeah, I spent hours experimenting with default views. At the end I wrote my own layout )
-
Stefan Frye almost 11 yearsI've been working on this for hours, and I've had more than one solution of the "almost good" kind, but just not perfect. I don't think that the approach with LinearLayouts and weights can work. I wouldn't know how, so I wouldn't know what to manipulate. If you think your solution would work with minor adjustments, then why don't you make those adjustments? This might sound lazy and/or ungrateful, but as I said, I tried a lot and just couldn't get it to work. Again, I really do appreciate your effort.
-
Stefan Frye almost 11 yearsLike most other answers, this doesn't work for short texts: whitespace grows between rl1 and rl2 instead of between rl2 and rl3.
-
keyboardr about 9 yearsA problem with
LinearLayout
is that it can take two layout passes for it to be fully laid out, so nesting them can be problematic.GridLayout
was built to solve this. -
Christian García over 8 yearsWarning:
layout_columnWeight
is only available after API 21. Although, yes, it solves the OP's problem -
Ameen Maheen over 8 yearsits not a problem i am using the support library android.support.v7.widget.GridLayout
-
FeelGood about 8 yearsI don't know how did you find it but it works! It works with fill_horizontal too.
-
Mert Akcakaya about 6 yearsAnd you have to apply this for every row or it won't work.