0

I've been struggling to lay out two ListViews in a vertical LinearLayout. I finally saw the answer on here about wrapping each in their own LinearLayout, and adding each one of these LinearLayouts to the original LinearLayout with weights of 1. So that's what I tried... but I just cannot seem to get this to work.

I'm doing this all in code:

public class MyDualList extends LinearLayout
{
    private LinearLayout    _layout1;
    private LinearLayout    _layout2;
    private ListView        _list1;
    private ListView        _list2;

    public MyDualList(Context context, ListView list1, ListView list2)
    {
        super(context);

        _list1 = list1;
        _list2 = list2;

        _layout1 = new LinearLayout(context);
        _layout1.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, 0, 1));
        _layout1.addView(_list1, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

        _layout2 = new LinearLayout(context);
        _layout2.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, 0, 1));
        _layout2.addView(_list2, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

        addView(_layout1);
        addView(_layout2);
    }
}

This is my latest attempt, but I swear I've tried every combination/setting for the LayoutParams' height (FILL_PARENT, WRAP_CONTENT, 0) as well as various weights.

The result is never very good; if my second list is very long, it inevitably takes up the vast majority of the original vertical layout (certainly much more than 50%).

I'm not going to give up! Maybe someone can help me out a bit.

Thanks, Ken

Ken
  • 1
  • 1
  • 2
  • Not sure if this relates, but I think there was a difference with the addView methods. Can you try to call: `addView(_layout1, new LayoutParams(LayoutParams.FILL_PARENT, 0, 1));` instead of setting the LayoutParams beforehand. Same for `_layout2`. – Sebastian Roth Feb 11 '11 at 05:16
  • @Sebastian - that won't make any difference. `addView(aView)` is exactly the same as `addView(aView, aView.getLayoutParams())`. – Ted Hopp Feb 11 '11 at 07:01
  • I'm not quite sure why you need _layout1 and _layout2. Why not just set the heights of _list1 and _list2 to 0, their weights to 1, and add them directly to the dual list? – Ted Hopp Feb 11 '11 at 07:06
  • I tried without the two layouts with no success -- well, it behaved exactly the way it does now. I switched to the two layouts because of the post (not sure how to embed the URL yet... sorry): http://stackoverflow.com/questions/3968171/android-split-the-screen-in-2-equals-parts-with-2-listviews – Ken Feb 11 '11 at 15:05
  • Have you tried my suggestion? Romain is correct with his statement. `addView` will set different layout params. Btw, why not using XML? – Sebastian Roth Feb 11 '11 at 15:36
  • Nope, no difference with how I set LayoutParams. BTW, I find it easier to prototype UI in code. Maybe that's just me ;-) If there's a functional difference (between coded UI and XML), that would be bad IMO, although I could live with it if that is indeed the case. I still think there must be something simple I'm missing. – Ken Feb 12 '11 at 03:02
  • Google recommends to create UIs in XML, as it's more flexible (i.e. how will your hardcoded UI respond to 1. different orientations 2. different screen sizes 3. ever tried to code a complex `RelativeLayout` in Java? ;-) I will take a look and try to reproduce your problem with a layout written in Java. – Sebastian Roth Feb 13 '11 at 07:17
  • I'm not advocating coding UI -- it's just what's working for me right now. BTW, my coded UI handles all the above cases. Granted, I may not have the most interesting/demanding UI in the world... – Ken Feb 13 '11 at 07:48

3 Answers3

2

I like to ask you to move view logic to XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
        >
    <ListView
            android:id="@+id/list1"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            />
    <ListView
            android:id="@+id/list2"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            />
</LinearLayout>

Java code could be:

final String[] data1 = new String[] { "1a", "1b", "1c", "1d", "1e", "1f", "1g", "1h", "1i" };
final String[] data2 = new String[] { "2a", "2b", "2c", "2d", "2e", "2f", "2g", "2h", "2i" };

final ListView l1 = (ListView) findViewById(R.id.list1);
final ListView l2 = (ListView) findViewById(R.id.list2);

l1.setAdapter(new ArrayAdapter<String>(this, R.layout.item, R.id.text, data1));
l2.setAdapter(new ArrayAdapter<String>(this, R.layout.item, R.id.text, data2));

Additionally, if you insist on Java coding for the UI, I would try to set the LayoutParams in your calls to addView(_layout1) -> addView(_layout1, new LayoutParams(LayoutParams.FILL_PARENT, 0, 1)).

BTW: Where do you set the orientation of this layout? Default is horizontal.

Sebastian Roth
  • 11,344
  • 14
  • 61
  • 110
  • I snipped only a bit of my code for this posting. My class is in reality a vertical LinearLayout. – Ken Feb 12 '11 at 03:06
1

You are replacing the correct layout params (the ones you set with setLayoutParams) with incorrect layout params (the one you pass in addView.) Just call addView(_list1) instead, without specifying layout params. Edit: Sorry, I misread the code, ignore this :)

Romain Guy
  • 97,993
  • 18
  • 219
  • 200
  • Really? How can calling `_layout1.addView(_list1, new LayoutParams(...))` affect the layout params set for _layout1? If that's what was happening, _layout1 would always fill the parent's height and would push _layout2 off the screen, but that's not what OP reports is happening. – Ted Hopp Feb 11 '11 at 07:05
0

So here is solution 2:

public class Q4965745 extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

//        setContentView(R.layout.main);
        setContentView(new Q4965745View(this));

        final String[] data1 = new String[]{"1a", "1b", "1c", "1d", "1e", "1f", "1g", "1h", "1i"};
        final String[] data2 = new String[]{"2a", "2b", "2c", "2d", "2e", "2f", "2g", "2h", "2i"};

        final ListView l1 = (ListView) findViewById(11);
        final ListView l2 = (ListView) findViewById(22);

        l1.setAdapter(new ArrayAdapter<String>(this, R.layout.item, R.id.text, data1));
        l2.setAdapter(new ArrayAdapter<String>(this, R.layout.item, R.id.text, data2));
    }

    class Q4965745View extends LinearLayout {
        public Q4965745View(Context context) {
            super(context);
            Q4965745View.this.setOrientation(LinearLayout.VERTICAL);

            ListView lv1 = new ListView(context);
            lv1.setId(11);

            ListView lv2 = new ListView(context);
            lv2.setId(22);

            Q4965745View.this.addView(lv1, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f));
            Q4965745View.this.addView(lv2, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f));
        }
    }
}

Which produces:

Screenshot

EDIT:

When filling data2 with 1000 entries:

final String[] data2 = new String[1000];
for(int i = 0; i < 1000; i++) {
    data2[i] = "test" + i;
}

I still get the same layout:

Screenshot 50/50 * 1000 entries

EDIT 2:

I was able to get a "better behavior" at least by using TableLayout:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
    <TableRow>
        <ListView
                android:id="@+id/list1"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                />
    </TableRow>
    <TableRow>
        <ListView
                android:id="@+id/list2"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                />
    </TableRow>
</TableLayout>

Maybe Romain has an idea on how to make it really 50/50 independent of the amount of items in the ListViews..

EDIT 3:

Ok, final solution (using inner LinearLayout):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        >
    <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            >
        <ListView
                android:id="@+id/list1"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                />
    </LinearLayout>
    <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            >
        <ListView
                android:id="@+id/list2"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                />
    </LinearLayout>
</LinearLayout>

Maybe good enough? ;-)

Sebastian Roth
  • 11,344
  • 14
  • 61
  • 110
  • Thanks for the suggestion. But I think you'll find that if you make your second list a lot longer than the first (in my test cases, the first list had 3 entries, the second had > 1000 entries) you'll no longer see the 50/50 split. Could be wrong, but I believe that's the behavior I was seeing... – Ken Feb 13 '11 at 07:45
  • Wish I could agree. Did some test, but cannot reproduce your problem, see my edit. Did you check SDK Version, target SDK version, phone etc? Maybe some more details? – Sebastian Roth Feb 13 '11 at 08:13
  • Ah, finally I see: I set "data1" to 3 items -> the layout is broken in the way you explained. I guess you need to wrap in child layouts in this case. `LinearLayout` is probably re-setting its minimal height. EDIT: Will need to check this, simple addition of an child layout may not solve the problem. – Sebastian Roth Feb 13 '11 at 08:16