44

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>
Community
  • 1
  • 1
Stefan Frye
  • 2,007
  • 1
  • 20
  • 24
  • I would do this using RelativeLayout. Can you post your code with RelativeLayout? – Chiral Code Jul 15 '13 at 14:19
  • Spent hours trying to achieve the exact same layout, to the conclusion that this cannot be done with default android elements. The problem here is that there is no way to configure a set of rules for "hey do not overlap if you are big AND do not take all the space if you are small". Any configuration ends with view1 pushed to the right if text is small or overlaid if text is big. – GuillermoMP Dec 27 '15 at 23:13
  • 1
    Does somebody tried to solve the issue with ConstraintLayout? I've tried and after several hours I've bumped into same problems as with old-fashioned layouts. – lookashc Apr 27 '17 at 18:30

14 Answers14

21

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

Yuntao
  • 655
  • 5
  • 7
9

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>
invertigo
  • 6,336
  • 5
  • 39
  • 64
  • yeah, 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? – invertigo Jul 15 '13 at 14:57
  • Unfortunately, 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 :( – Stefan Frye Jul 15 '13 at 15:03
  • sorry, try my changed suggestion above, i had "weight" instead of "layout_weight" /facepalm – invertigo Jul 15 '13 at 15:04
  • I noticed (and edited) that myself :) It still doesn't work :( – Stefan Frye Jul 15 '13 at 15:06
  • also added layout_weight to the first textview, did you get that in your edit? – invertigo Jul 15 '13 at 15:06
  • I 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. – Stefan Frye Jul 15 '13 at 15:09
  • sounds like you might be stuck manipulating the layout programatically then :/ – invertigo Jul 15 '13 at 15:24
  • Yes, think so, too. Thanks for your time, though. – Stefan Frye Jul 15 '13 at 15:36
  • A 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. – keyboardr Apr 29 '15 at 01:13
4

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] |
+----------------------------------------+
dinesh sharma
  • 3,312
  • 1
  • 22
  • 32
  • Sorry, 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. – Stefan Frye Jul 23 '13 at 08:49
  • I have edited the answer after implementing it please have a look. If you still need different thing please feel free to ask – dinesh sharma Jul 23 '13 at 09:00
  • As 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 :) – Stefan Frye Jul 23 '13 at 12:32
  • I 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 Jul 24 '13 at 04:50
  • Also try to tune in the provided xml for example play with min_width property of the view1 that will help you more :) – dinesh sharma Jul 24 '13 at 06:38
  • I really appreciate your effort, but still: there is whitespace between text and view1, which I don't want. – Stefan Frye Jul 24 '13 at 15:52
  • No 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. – dinesh sharma Jul 25 '13 at 04:14
  • I'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 Jul 25 '13 at 07:52
3

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.

Leonidos
  • 10,482
  • 2
  • 28
  • 37
  • Spent 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. – Sergii Rudchenko Jul 24 '13 at 19:32
  • Yeah, I spent hours experimenting with default views. At the end I wrote my own layout ) – Leonidos Jul 25 '13 at 07:23
3

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.

Allan Spreys
  • 5,287
  • 5
  • 39
  • 44
2

I think there's just a small issue on the layout that could be solved, anchoring the view3 to the right and start from there to force the view to have a delimited area (hence being able to properly set the ellipse):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content">
<TextView
        android:id="@+id/rl3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="(view2)" />
<TextView
        android:id="@+id/rl2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/rl3"
        android:text="(view1)" />
<TextView
        android:id="@+id/rl1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ellipsize="end"
        android:singleLine="true"
        android:layout_alignParentLeft="true"
        android:layout_toLeftOf="@id/rl2"
        android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis" />
</RelativeLayout>

Hope this helps...

Regards!

Martin Cazares
  • 13,637
  • 10
  • 47
  • 54
  • 2
    Like most other answers, this doesn't work for short texts: whitespace grows between rl1 and rl2 instead of between rl2 and rl3. – Stefan Frye Jul 25 '13 at 08:01
0

Try this

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:baselineAligned="false"
    android:orientation="horizontal">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center">
       <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:singleLine="true"
            android:text="Long text to demonstrate problem with TextView in GridLayout taking up too much space despite ellipsis"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center">
        <TextView
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="left"
             android:text="(view1)"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center">
        <TextView
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="right"
             android:text="(view2)"/>
    </LinearLayout>

</LinearLayout>

Currently, all views are centered. You can change android:gravity property to meet your needs. For example, you may want to align view1 right and view2 left in which case last two LinearLayouts would look something like (with 5dp margin on the right and left respectively):

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:gravity="center|right">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:layout_marginRight="5dp"
        android:text="(view1)"/>
</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:gravity="center|left">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:layout_marginLeft="5dp"
        android:text="(view2)"/>
</LinearLayout>
ozbek
  • 20,955
  • 5
  • 61
  • 84
  • Not 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 Jul 15 '13 at 15:34
  • Hmm... 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 for `view1 + view2` – ozbek Jul 15 '13 at 15:40
0

I find my solution for the case number 2 (the one with a long text):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:weightSum="3" >

    <TextView
        android:id="@+id/rl0"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        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_marginLeft="10dp"
        android:layout_weight="1"
        android:text="(view1)" />

    <TextView
        android:id="@+id/rl2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_weight="1"
        android:text="(view2)" />

</LinearLayout>

The real problem is case one, and i didn't try a lot of things for this. I hope it helps (and if i have more spare time, i will try to achieve first one!).

JJ86
  • 5,055
  • 2
  • 35
  • 64
  • This gives the same result as invertigos answer. I need a solution for both cases, of course. – Stefan Frye Jul 18 '13 at 09:45
  • @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? – JJ86 Jul 18 '13 at 10:06
  • This would be the programmatic solution that I hoped to avoid. – Stefan Frye Jul 18 '13 at 11:03
0

If the views on the right get pushed over by the text by design, you might as well use a ListView instead of a GridView.

You would just need to make the base of the list item layout a RelativeLayout, and set rules like this:

  1. You can set the two views on the right to alignParentRight (using android:layout_alignParentLeft="true"), but make sure the first view stays to the left of the second so it will push itself to the left as the views stretch out.

  2. You can make the TextView on the left align to the left, but stay to the left of the first view (using android:layout_toLeftOf="@+id/viewId") so it won't overlap with the views.

afollestad
  • 2,929
  • 5
  • 30
  • 44
  • 1
    I 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 Jul 23 '13 at 07:06
0

Try using Layout Weight

   <TableRow
        android:id="@+id/tableRow3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/tableRow2"
        android:layout_alignParentBottom="true"
        android:gravity="center"
        android:weightSum="10"
        android:background="@android:color/black" >

        <TextView
            android:id="@+id/txtInningsTotal"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:gravity="center"
            android:text="0" 
            android:textColor="@android:color/white" />

        <TextView
            android:id="@+id/txtTeamOneTotal"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2.5"
            android:gravity="center"
            android:text="0" 
            android:textColor="@android:color/white" />

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.2" />

        <TextView
            android:id="@+id/txtTeamTwoTotal"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2.5"
            android:gravity="center"
            android:text="0"
            android:textColor="@android:color/white"  />

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.2" />

        <TextView
            android:id="@+id/txtGrandTotal"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="3"
            android:gravity="center"
            android:text="0"
            android:textColor="@android:color/white"  />
    </TableRow>

Here i have taken table row in which there is layout weight sum which is of 10 means that it is 100% width of its parent. and in all its child views i have set width to 0Dp and given weight to 1 or 2. so that it will take up to that percent of total 10. so the layout will be adjusted accordingly screen and also there will be no issue of overlapping.

If i have understood you correctly then this is the answer you wanted.

Hope it Helps!

Armaan Stranger
  • 3,140
  • 1
  • 14
  • 24
  • Quite 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 Jul 24 '13 at 15:44
  • this is just another example. i wanted to show you weight usage in it. – Armaan Stranger Jul 25 '13 at 04:53
0

First, you must layout [view 2] to parent Right;

Again, you reference the reference to the last two layout!

<Relativelayout android:layout_width="match_parent"
            android:layout_height="wrap_content"
      <TextView
        android:id="@+id/view2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
       />

      <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toLeft="@id/view2"
        android:gravity="left">

        <TextView
            android:id="@+id/shortORlongtTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/view1"
            android:ellipsize="end"
            android:maxLines="1"
            android:textSize="18dp"/>

        <TextView
            android:id="@+id/view1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
           />
    </RelativeLayout>

Jenus Dong
  • 304
  • 2
  • 7
0

I had the same problem with the grid layout. what i did is given a fixed width for the text view and also given layout_columnWeight property for each text view then the issue was fixed ,hope it helps ...

           <TextView
                android:id="@+id/txtName"
                style="@style/MyDetailTitle"
                android:layout_width="@dimen/detail_length"
                android:layout_height="wrap_content"
                android:text="@string/app_name"
                app:layout_column="3"
                app:layout_columnWeight="1"
                app:layout_gravity="start"
                app:layout_row="1" />
Ameen Maheen
  • 2,719
  • 1
  • 28
  • 28
0

GridLayout is like the other things on Android : flawed by design.

You will need a custom Layout, the following example will allow you to layout things like:

    [      label | short text     | very long label | short text     ]

    [ long label | very very very |           label | very long text ] 
    [            | long text      |                 |                ]



import android.content.Context;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;


public class TwoColumsGridLayout extends ViewGroup {
    private final List<List<View>> rows;
    private int rowCount = 0;
    private int firstColumWidth;
    private int secondColumWidth;
    private int thirdColumWidth;
    private int fourthColumnWidth;
    private final List<Integer> rowHeights = new ArrayList<>();
    private final List<List<Integer>> cellHeights = new ArrayList<>();
    private final List<Integer> firstCellsWidths = new ArrayList<>(4);
    private final List<Integer> thirdCellsWidths = new ArrayList<>(4);

    public TwoColumsGridLayout(Context context, int rowCount) {
        super(context);
        rows = new ArrayList<>(rowCount);
    }


    public void add(Context ctx, TextView l1, View t1, TextView l2, View t2) {
        final List<View> row = new ArrayList<>(4);
        row.add(l1);
        row.add(t1);
        row.add(l2);
        row.add(t2);
        rows.add(row);
        this.addView(l1);
        this.addView(t1);
        if (l2 != null)
            this.addView(l2);
        if (t2 != null)
            this.addView(t2);
        this.rowCount++;
    }

    public int getRowCount() {
        return rowCount;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int curLeft = 0;
        int curBottom;
        int curRight;
        int curTop = 0;
        int i = 0;
        for (List<View> row : rows) {
            final int rowHeight = this.rowHeights.get(i);
            final List<Integer> rowCellHeights = this.cellHeights.get(i);
            final View v0 = row.get(0);
            curLeft = 0;
            curRight = curLeft + this.firstColumWidth;
            if (v0 != null) {
                curBottom = curTop + rowCellHeights.get(0);
                // Right align
                v0.layout(curLeft + this.firstColumWidth - this.firstCellsWidths.get(i), curTop + 7, curRight, curBottom + 7);
            }
            //
            final View v1 = row.get(1);
            curLeft += this.firstColumWidth;

            curRight = curLeft + this.secondColumWidth;
            if (v1 != null) {
                curBottom = curTop + rowCellHeights.get(1);
                v1.layout(curLeft, curTop, curRight, curBottom);
            }
            //
            final View v2 = row.get(2);
            curLeft += this.secondColumWidth;
            curRight = curLeft + this.thirdColumWidth;
            if (v2 != null) {
                curBottom = curTop + rowCellHeights.get(2);
                // Right align
                v2.layout(curLeft + this.thirdColumWidth - this.thirdCellsWidths.get(i), curTop + 7, curRight, curBottom + 7);
            }
            //
            final View v3 = row.get(3);
            curLeft += this.thirdColumWidth;
            curRight = curLeft + this.fourthColumnWidth;
            if (v3 != null) {
                curBottom = curTop + rowCellHeights.get(3);
                v3.layout(curLeft, curTop, curRight, curBottom);
            }
            curTop += rowHeight;
            i++;
        }

    } 

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        final int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        // Compute first column width
        firstColumWidth = 0;
        for (List<View> row : rows) {
            final View v = row.get(0);
            if (v != null) {
                v.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                measureChild(v, widthMeasureSpec, heightMeasureSpec);
                final int w = v.getMeasuredWidth();
                if (firstColumWidth < w) {
                    firstColumWidth = w;
                }
            }
        }
        // Compute third column width
        thirdColumWidth = 0;
        for (List<View> row : rows) {
            final View v = row.get(2);
            if (v != null) {
                v.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                measureChild(v, widthMeasureSpec, heightMeasureSpec);
                final int w = v.getMeasuredWidth();
                if (thirdColumWidth < w) {
                    thirdColumWidth = w;
                }
            }
        }
        secondColumWidth = (parentWidth - firstColumWidth - thirdColumWidth) / 2;
        fourthColumnWidth = parentWidth - firstColumWidth - secondColumWidth - thirdColumWidth;
        // Clear
        this.rowHeights.clear();
        this.cellHeights.clear();
        this.firstCellsWidths.clear();
        this.thirdCellsWidths.clear();
        // Compute heights
        int height = 0;
        for (List<View> row : rows) {
            final ArrayList<Integer> rowCellHeights = new ArrayList<>(4);
            cellHeights.add(rowCellHeights);
            int rowHeight = 0;
            // First column
            final View v0 = row.get(0);
            if (v0 != null) {
                int h = v0.getMeasuredHeight();
                this.firstCellsWidths.add(v0.getMeasuredWidth());
                rowCellHeights.add(h);
                if (rowHeight < h) {
                    rowHeight = h;
                }
            } else {
                this.firstCellsWidths.add(0);
            }
            // Second column
            final View v1 = row.get(1);
            if (v1 != null) {
                v1.setLayoutParams(new ViewGroup.LayoutParams(secondColumWidth, LayoutParams.WRAP_CONTENT));
                measureChild(v1, widthMeasureSpec, heightMeasureSpec);
                int h = v1.getMeasuredHeight();
                rowCellHeights.add(h);
                if (rowHeight < h) {
                    rowHeight = h;
                }
            }
            // Third column
            final View v2 = row.get(2);
            if (v2 != null) {
                int h = v2.getMeasuredHeight();
                this.thirdCellsWidths.add(v2.getMeasuredWidth());
                rowCellHeights.add(h);
                if (rowHeight < h) {
                    rowHeight = h;
                }
            } else {
                this.thirdCellsWidths.add(0);
            }
            // Fourth column
            final View v3 = row.get(3);
            if (v3 != null) {
                v3.setLayoutParams(new ViewGroup.LayoutParams(fourthColumnWidth, LayoutParams.WRAP_CONTENT));
                measureChild(v3, widthMeasureSpec, heightMeasureSpec);
                int h = v3.getMeasuredHeight();
                rowCellHeights.add(h);
                if (rowHeight < h) {
                    rowHeight = h;
                }
            }
            height += rowHeight;
            this.rowHeights.add(rowHeight);

        }
        setMeasuredDimension(parentWidth, height);
    }
}

Have fun.

BluEOS
  • 576
  • 6
  • 13
0

TableLayout will give expected behavior. May cause performance issue as question's author mention, but works great with simple layout. If the row is repeatable and scrollable, consider use gridview instead

<TableLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:stretchColumns="1"
    android:shrinkColumns="0"
    >
    <TableRow>

        <TextView/>

        <View1/>

        <View2/>
    </TableRow>
</TableLayout>
thanhbinh84
  • 17,876
  • 6
  • 62
  • 69