Android how to display 2 listviews in one activity one after the other
Asked Answered
C

9

44

I have used this code to display 2 list view one on top of the other.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<ListView
    android:id="@+id/listView1"
    android:layout_width="match_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    android:background="#f00" >
</ListView>

<ListView
    android:id="@+id/listView2"
    android:layout_width="match_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    android:background="#0f0" >
</ListView>

The problem is that, this causes the 2 listviews to each occupy half of the screen. I am adding a header to both lists like this.

LevelAdapter adapter = new LevelAdapter(getActivity(),
            R.layout.list_item, weather_data);

    View header = inflater.inflate(R.layout.header2, null);
    View header2 = inflater.inflate(R.layout.header, null);
   lv1.addHeaderView(header);
   lv2.addHeaderView(header2);
    lv1.setAdapter(adapter);
    lv2.setAdapter(adapter);

I would like the header of the second list to appear after the first list is over. How do i do this?How do i make the listviews appear such that the second one starts when the first one is over ? Thanks

Conservationist answered 17/7, 2013 at 7:20 Comment(0)
K
46

Use Like this:

Remove Linear layout. use relative layout and inside that place your two list view like this.

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/scrollojt"
android:fillViewport="true" >

   <RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >

<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#f00" >
 </ListView>

 <ListView
android:id="@+id/listView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/listView1"
android:background="#0f0" >
</ListView>
    </RelativeLayout>
  </ScrollView>

add Utility.java

public class Utility {

    public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null) {
            // pre-condition
            return;
        }

        int totalHeight = 0;
        int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST);
        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, listView);
            listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
            totalHeight += listItem.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
        listView.requestLayout();
    }
}

In your Activity:

 lv1.setAdapter(adapter);
 lv2.setAdapter(adapter);

Utility.setListViewHeightBasedOnChildren(lv1);
Utility.setListViewHeightBasedOnChildren(lv2);
Kobe answered 17/7, 2013 at 7:22 Comment(7)
Sorry this doesnt work.Now both of them together fill half the screen. How can you explicitly give the height of the listview ? Also i have used a linear layout in which layout_below is probably invalidConservationist
Soory, Not work properly, it contain half screen in layout. Have you any other idea? Please help me...Ailurophile
@135 Then go for custom listview.Kobe
I am using Fragment, so i don't know how to use ListFragment.Ailurophile
it is working fine but i have add header or footer dynamically than layout look like unfit.Clerk
You should never put a ListView in a ScrollViewLouden
This is very bad approach. Because after setListViewHeightBasedOnChildren() list view will displays ALL views, instead of 5-10 elements on screen. If your adapter contain 10k items, your app will crashes with OOM.Opiate
D
107

Before scrolling

After scrolling activity_main.xml

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:fillViewport="true" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="10dip" >

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:text="ANDROID" />

        <ListView
            android:id="@+id/listView1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dip"
            android:background="#B29090" >
        </ListView>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dip"
            android:gravity="center_vertical"
            android:text="IOS" />

        <ListView
            android:id="@+id/listView2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dip"
            android:background="#4A9C67" >
        </ListView>
    </LinearLayout>

</ScrollView>

MainActivity.java

package com.example.listviewin1xmldemo;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;

public class MainActivity extends ActionBarActivity {

    private ListView mListView1, mListView2;

    private String [] data1 ={"Hiren", "Pratik", "Dhruv", "Narendra", "Piyush", "Priyank"};
    private String [] data2 ={"Kirit", "Miral", "Bhushan", "Jiten", "Ajay", "Kamlesh"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mListView1 = (ListView)findViewById(R.id.listView1);
        mListView2 = (ListView)findViewById(R.id.listView2);

        mListView1.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data1));
        mListView2.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data2));

        ListUtils.setDynamicHeight(mListView1);
        ListUtils.setDynamicHeight(mListView2);
    }


    public static class ListUtils {
        public static void setDynamicHeight(ListView mListView) {
            ListAdapter mListAdapter = mListView.getAdapter();
            if (mListAdapter == null) {
                // when adapter is null
                return;
            }
            int height = 0;
            int desiredWidth = MeasureSpec.makeMeasureSpec(mListView.getWidth(), MeasureSpec.UNSPECIFIED);
            for (int i = 0; i < mListAdapter.getCount(); i++) {
                View listItem = mListAdapter.getView(i, null, mListView);
                listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
                height += listItem.getMeasuredHeight();
            }
            ViewGroup.LayoutParams params = mListView.getLayoutParams();
            params.height = height + (mListView.getDividerHeight() * (mListAdapter.getCount() - 1));
            mListView.setLayoutParams(params);
            mListView.requestLayout();
        }
    }
}
Donettedoney answered 25/2, 2015 at 7:47 Comment(12)
Thanks dude that code worked like charm ....I have tried the previous codes in this post they worked partially. This should be the correct accepted order. FOR THE OTHER USERS LIKE ME . PLEASE REFER THIS EXAMPLE. THIS WORKS 100 % . other are partially working .Claqueur
Thanks man! You saved my day. Two tips here for others: 1) Reconsider to replace this really cool code with ExpandableListView. 2) If you lazy like me and don't want to do 1) - don't forget to call setDynamicHeight after Adapter.notifyDataSetChanged()Prankster
Using two list view in same view will create performance issue. It's better to use single list view with two prototype cell. one for header and second for item for that you can use getItemViewType(int position) methodPotentilla
@Hiren Patel where is android.R.layout.simple_list_item_1? Is it a generic layout ID used by android system? I am getting "your content must have a Listview whose id attribute is 'android.R.id.list'Pastiche
@user914425, can you please copy full code and run it ? Hope it will help you.Donettedoney
i am using your code for custom listviews but it's not showing the last row for second listview.Alectryomancy
Remember to setDynamicHeight whenever the adapter items change length to update the height of the listView.Sounding
finally i got the solution after long time. I am trying this last three days and this answer for for me. Thanks @HirenPatel for post this answerLamori
I'm getting a null pointer exception java.lang.NullPointerException: Attempt to read from field 'int android.view.ViewGroup$LayoutParams.width' on a null object reference at this line: listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED); any idea why?Calycine
@HirenPatel It works.Thanks a lot. But the last items in both listview are not displayed fully. I changed the height whenever adapter item changes. Eventhough I am getting the same problem.And the footer is not visibleSlang
can i use this for expandable listview?Sisyphean
@HirenPatel how to use this with ExpandableListView ? stackoverflow.com/q/49879295/6067866Rolanda
K
46

Use Like this:

Remove Linear layout. use relative layout and inside that place your two list view like this.

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/scrollojt"
android:fillViewport="true" >

   <RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >

<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#f00" >
 </ListView>

 <ListView
android:id="@+id/listView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/listView1"
android:background="#0f0" >
</ListView>
    </RelativeLayout>
  </ScrollView>

add Utility.java

public class Utility {

    public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null) {
            // pre-condition
            return;
        }

        int totalHeight = 0;
        int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST);
        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, listView);
            listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
            totalHeight += listItem.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
        listView.requestLayout();
    }
}

In your Activity:

 lv1.setAdapter(adapter);
 lv2.setAdapter(adapter);

Utility.setListViewHeightBasedOnChildren(lv1);
Utility.setListViewHeightBasedOnChildren(lv2);
Kobe answered 17/7, 2013 at 7:22 Comment(7)
Sorry this doesnt work.Now both of them together fill half the screen. How can you explicitly give the height of the listview ? Also i have used a linear layout in which layout_below is probably invalidConservationist
Soory, Not work properly, it contain half screen in layout. Have you any other idea? Please help me...Ailurophile
@135 Then go for custom listview.Kobe
I am using Fragment, so i don't know how to use ListFragment.Ailurophile
it is working fine but i have add header or footer dynamically than layout look like unfit.Clerk
You should never put a ListView in a ScrollViewLouden
This is very bad approach. Because after setListViewHeightBasedOnChildren() list view will displays ALL views, instead of 5-10 elements on screen. If your adapter contain 10k items, your app will crashes with OOM.Opiate
D
9

You should use ExpandableListView (http://developer.android.com/reference/android/widget/ExpandableListView.html). You would have two sections instead of two listviews but they (including headers) will be aligned as you described.

Driest answered 19/12, 2013 at 12:34 Comment(1)
how to use multiple ExpandableListView in single screen ? stackoverflow.com/q/49879295/6067866Rolanda
L
5

It is not a good practice to use more than one ListViews' in a single container. It causes measuring and performance problems. Better is to use single ListView with several view types. In your case view types could be: listview1_viewtype, listview2_viewtype, listview2_header_viewtype. For first ListView's header you can use just header.

Longshoreman answered 27/8, 2014 at 10:1 Comment(0)
D
2

when weights are provided height should be provided as 0dp or wrap_content. but you are not doing so. change your xml file as below. I hope it works for you.

as per your comment i am editing my post according to requirement Solution

1- : Create a list view with only 2 row

1.1-: Add a list view as a row child in first listview #1

1.2-: Add another list view as second row child in first listview #1

i hope by this way you can achieve success.

Digressive answered 17/7, 2013 at 7:24 Comment(1)
Hi. could you elaborate how i can use frame layout here. Possibly some sample code ?Conservationist
B
2

I'm new to Android as well and I got something similar (not exactly but kind of workaround) but much EASIER, by making a layout file and putting the required number of list views in it and another XML layout and wrap the previously made layout in ScrollView.

Suppose you have layout named two_listview_layout.xml defined as

<RelativeLayout
..>
    <ListView
        android:id="@+id/listViewOne"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <ListView
        android:id="@+id/listViewTwo"
        android:layout_width="match_parent"
        android:layout_width="wrap_content"/>
</RelativeLayout>

RelativeLayout is not mandatory here but you can play around with your requirements and the layouts.

Now make another layout in which this layout is wrapped in ScrollView. As ScrollView can have only 1 direct child, you'll have this complete layout as its child.

Name this (below) layout as final_layout.xml

<FrameLayout
...>
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <include layout="@layout/two_listview_layout" />
    </ScrollView>
</FrameLayout>

Now inflate this final_layout.xml in your fragment/activity and use the Id's that were named in the two_listview_layout.xml to access any of the listview.

Output is something like this: (apologies for the bad quality of screen recorder :p ) Trailers and Reviews - both are listviews here.

enter image description here

Baten answered 9/2, 2016 at 18:22 Comment(0)
L
2

Try with ScrollView and LinearLayout:

activity_main.xml

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
   <ScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/action_bar1"
    android:fillViewport="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="10dip">

        <ListView
            android:id="@+id/listView1"
            android:layout_width="match_parent"
            android:layout_height="200dip"
            android:layout_margin="10dip"
            android:background="#B29090">
        </ListView>



        <ListView
            android:id="@+id/listview2"
            android:layout_width="match_parent"
            android:layout_height="200dip"
            android:layout_margin="10dip"
            android:background="#4A9C67">
        </ListView>
    </LinearLayout>
</ScrollView>
</RelativeLayout>

MainActivity.java

 private ListView list1, list2;
private String [] data1 ={"H", "P", "D", "N", "P", "P"};
private String [] data2 ={"K", "M", "B", "K", "A", "K"};
 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_sounds);
    list1 = (ListView) findViewById(R.id.listView1);
    list2 = (ListView) findViewById(R.id.listview2);

    list1.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,android.R.id.text1,data1));
    list2.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,android.R.id.text1,data2));



}
Larentia answered 10/1, 2017 at 10:49 Comment(0)
T
0

Adding layout_weight worked for me.

<ListView
    android:id="@+id/excerciseListView"
    android:layout_width="match_parent"
    android:layout_height="0px"
    android:divider="#B6B6B6"
    android:dividerHeight="1sp"
    android:layout_weight="3"></ListView>
<ListView
    android:id="@+id/instructionListView"
    android:layout_width="match_parent"
    android:layout_height="0px"
    android:divider="#B6B6B6"
    android:dividerHeight="1sp" 
   android:layout_weight="1"></ListView>
Twine answered 21/1, 2015 at 9:28 Comment(0)
S
-3

Try with relative layout:

<?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="fill_parent" >

<ListView
 android:id="@+id/listView1"
 android:layout_width="match_parent"
 android:layout_height="fill_parent"
 android:layout_weight="1"
 android:layout_below="@+id/listView1"
 android:background="#f00" >
</ListView>
<ListView
 android:id="@+id/listView2"
 android:layout_width="match_parent"
 android:layout_height="fill_parent"
 android:layout_weight="1"
 android:background="#0f0" >
</ListView>
</RelativeLayout>
Stodder answered 17/7, 2013 at 7:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.