Nick
Nick

Reputation: 351

Listview same height as content

I used custom listview . Content comes from dynamic I want to same listview height same as content.

I used wrap_content but this does not help If I remove scrollview then its work

Code. "The vertically scrolling ScrollView should not contain another vertically scrolling widget (ListView)"

<ScrollView 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"
    android:background="@drawable/background_img"
    android:scrollbars="none" >

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

<ListView
            android:id="@+id/lstsemtrack"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
        android:divider="#f2e4e4"
        android:dividerHeight="1dip"
             >
        </ListView>

Item list

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="10dip"
    android:scrollbars="none" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:weightSum="4" >

        <TextView
            android:id="@+id/txtBiology"
            style="@style/sem_rowtext"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginRight="5dip"
            android:layout_weight="1"
            android:text="Biology" />

        <TextView
            android:id="@+id/txtClass"
            style="@style/sem_rowtext"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Biology - 101" />

        <TextView
            android:id="@+id/txtGrade"
            style="@style/sem_rowtext"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Grade" />

        <TextView
            android:id="@+id/txtGrade"
            style="@style/sem_rowtext"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Remove" />
    </LinearLayout>

</LinearLayout>

output like below I want same as content no scrollview

enter image description here

Upvotes: 17

Views: 38365

Answers (10)

Pierre Alexandre
Pierre Alexandre

Reputation: 239

The problem is the "ListView" inside "ScrollView"

ListView have already an automatic scroll, so you can delete it

Upvotes: 0

Smaran
Smaran

Reputation: 1651

couple of things to note here..

  1. Do not use ListView inside the ScrollView
  2. You will need to dynamically calculate the listView items to get the height for it.

Here is a function to do that..

public void setListViewHeightBasedOnChildren(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null) {
        return;
    }

    int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
    for (int i = 0; i < listAdapter.getCount(); i++) {
        View listItem = listAdapter.getView(i, null, listView);
        if (listItem instanceof ViewGroup)
            listItem.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        listItem.measure(0, 0);
        totalHeight += listItem.getMeasuredHeight();
    }

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

}

You will need to call the same in

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
setListViewHeightBasedOnChildren(listview)
    }

Upvotes: 1

Erik Melkersson
Erik Melkersson

Reputation: 997

As noted by Permita you should not have a ListView in a Scrollview. You should use for example a LinearLayout instead.

In some cases you have already made custom adapters you want to reuse. In that case these code snippets may be useful.

Old view:

...
<ListView android:id="@+id/myListView" ... />
...

New view:

...
<LinearLayout
    android:orientation="vertical"
    android:id="@+id/myLinearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
...

Old code: (in dialog/fragment/activity)

YourAdapter listAdapter;
...
ListView listView = (ListView)rootView.findViewById(R.id.myListView);
...
if (listView != null) {
    if (listAdapter == null) {
        listAdapter = new YourAdapter(...);
        listView.setAdapter(listAdapter);
    } else {
        listAdapter.notifyDataSetChanged();
    }
}

New code: (doing some "listview"-stuff ourselves, to reuse views if possible)

YourAdapter listAdapter;
...
LinearLayout linearLayout = (LinearLayout) rootView.findViewById(R.id.myLinearLayout);
...
if (linearLayout != null) {
    if (listAdapter == null) listAdapter = new YourAdapter(...);
    for (int pos = 0; pos < listAdapter.getCount(); pos++) {
        View existingView = linearLayout.getChildAt(pos);
        if (existingView != null) listAdapter.getView(pos, existingView, linearLayout);
        else linearLayout.addView(listAdapter.getView(pos, null, linearLayout));
    }
    while (linearLayout.getChildCount() > listAdapter.getCount()) linearLayout.removeViewAt(listAdapter.getCount());
}

UPDATE: Or just add this to your adapter and call it instead of setAdapter on the list view and and notifyDataUpdated on the adapter:

public void updateOnLinearView(ViewGroup parentView) {
    // Note reusing child views if there are any
    for (int pos = 0; pos < getCount(); pos++) {
        View existingView = parentView.getChildAt(pos);
        if (existingView != null) getView(pos, existingView, parentView);
        else parentView.addView(getView(pos, null, parentView));
    }
    while (parentView.getChildCount() > getCount())
        parentView.removeViewAt(getCount());
}

Upvotes: 2

user4696837
user4696837

Reputation:

Use Own Custom ListView
Create a class CustomListView.java and extend ListView like this..

public class CustomListView extends ListView {

private android.view.ViewGroup.LayoutParams params;
private int prevCount = 0;

public CustomListView(Context context, AttributeSet attrs)
{
    super(context, attrs);
}

@Override
protected void onDraw(Canvas canvas)
{
    if (getCount() != prevCount) 
    {
        int height = getChildAt(0).getHeight() + 1 ;
        prevCount = getCount();
        params = getLayoutParams();
        params.height = getCount() * height;
        setLayoutParams(params);
    }

    super.onDraw(canvas);
}

}

Then use it in xml

 <yourPackageName.CustomListView
        android:id="@+id/lstsemtrack"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:divider="#f2e4e4"
        android:dividerHeight="1dip">
 </yourPackageName.ListView>

Upvotes: 2

josephus
josephus

Reputation: 8304

Other suggestions will not work, because there is no way to determine the height of the content of the ListView until after it's drawn into the screen (unless of course you have a fixed height, then use that as your ListView's height also).

What you can do is set the ListView's height AFTER drawing the elements inside it. You can do this in onWindowFocusChanged in your activity. As an example:

public void onWindowFocusChanged(boolean hasFocus) {
    // get content height
    int contentHeight = listView.getChildAt(0).getHeight();

    // set listview height
    LayoutParams lp = listView.getLayoutParams();
    lp.height = contentHeight;
    listView.setLayoutParams(lp);
}

Upvotes: 4

Raj008
Raj008

Reputation: 3917

Use this code

public class MyListView  extends ListView {

    public MyListView  (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyListView  (Context context) {
        super(context);
    }

    public MyListView  (Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }
}

Upvotes: 43

Permita
Permita

Reputation: 5493

You shouldn't put a ListView inside a ScrollView because ListView itself is a view group that displays a list of scrollable items. If you use it inside scrollview it will not receive scroll events because they all are handled by the parent ScrollView. Using a ListView to make it not scroll is extremely expensive and goes against the whole purpose of ListView. You should NOT do this. Just use a LinearLayout instead.

However, if you really want to do this you can have a look at this: How can I put a ListView into a ScrollView without it collapsing?

Upvotes: 12

VikramV
VikramV

Reputation: 1111

In your parent layout set the height to wrap_content. This should work.

Upvotes: 8

Gil Moshayof
Gil Moshayof

Reputation: 16761

try wrapping your list view with a LinearLayout and set the LinearLayout's height to wrap_content.

Upvotes: 0

Pratik Dasa
Pratik Dasa

Reputation: 7439

Use android:layout_height="match_parent", it will work I think.

Upvotes: -1

Related Questions