android listview display all available items without scroll with static header

82,427

Solution 1

The solution I used is to replace ListView with LinearLayout. You can create all your items inside LinearLayout, they will all be displayed. So there's really no need to use ListView.

LinearLayout list = (LinearLayout)findViewById(R.id.list_recycled_parts);
for (int i=0; i<products.size(); i++) {
  Product product = products.get(i);
  View vi = inflater.inflate(R.layout.product_item, null);
  list.addView(vi);
}

Solution 2

As @Alex noted in the accepted answer that LinearLayout is hardly a replacement. I had a problem where LinearLayout was not an option, that's when i came across this blog. I will put the code here for reference purposes. Hope it helps someone out there!

public class UIUtils {

    /**
     * Sets ListView height dynamically based on the height of the items.
     *
     * @param listView to be resized
     * @return true if the listView is successfully resized, false otherwise
     */
    public static boolean setListViewHeightBasedOnItems(ListView listView) {

        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter != null) {

            int numberOfItems = listAdapter.getCount();

            // Get total height of all items.
            int totalItemsHeight = 0;
            for (int itemPos = 0; itemPos < numberOfItems; itemPos++) {
                View item = listAdapter.getView(itemPos, null, listView);
                item.measure(0, 0);
                totalItemsHeight += item.getMeasuredHeight();
            }

            // Get total height of all item dividers.
            int totalDividersHeight = listView.getDividerHeight() *
                    (numberOfItems - 1);

            // Set list height.
            ViewGroup.LayoutParams params = listView.getLayoutParams();
            params.height = totalItemsHeight + totalDividersHeight;
            listView.setLayoutParams(params);
            listView.requestLayout();

            return true;

        } else {
            return false;
        }

    }
}

Usage:

//initializing the adapter
listView.setAdapter(adapter);
UIUtils.setListViewHeightBasedOnItems(listView);

//whenever the data changes
adapter.notifyDataSetChanged();
UIUtils.setListViewHeightBasedOnItems(listView);

Solution 3

You can make your own customlistview. (It can extends ListView/ExpandableListView/GridView) and override the onMeasure method with this. With this you'll never need to call a function or anything. Just use it in your xml.

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

Solution 4

I had a ListView in my layout and wanted to use a library which can't handle a ListView here because it wraps it into a ScrollView. The best solution for me is based on Fedor´s answer.

Since I already got an ArrayAdapter for the ListView I wanted to re-use it:

LinearLayout listViewReplacement = (LinearLayout) findViewById(R.id.listViewReplacement);
NamesRowItemAdapter adapter = new NamesRowItemAdapter(this, namesInList);
for (int i = 0; i < adapter.getCount(); i++) {
    View view = adapter.getView(i, null, listViewReplacement);
    listViewReplacement.addView(view);
}

For me this works fine because I just need to display dynamic data varying from 1 to 5 elements. I just had to add my own divider.

Solution 5

If someone still has the problem then you can make customList and add onMesure() method just like I implemented it:

public class ScrolleDisabledListView extends ListView {

private int mPosition;

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

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

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

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK;

    if (actionMasked == MotionEvent.ACTION_DOWN) {
        // Record the position the list the touch landed on
        mPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
        return super.dispatchTouchEvent(ev);
    }

    if (actionMasked == MotionEvent.ACTION_MOVE) {
        // Ignore move events
        return true;
    }

    if (actionMasked == MotionEvent.ACTION_UP) {
        // Check if we are still within the same view
        if (pointToPosition((int) ev.getX(), (int) ev.getY()) == mPosition) {
            super.dispatchTouchEvent(ev);
        } else {
            // Clear pressed state, cancel the action
            setPressed(false);
            invalidate();
            return true;
        }
    }

    return super.dispatchTouchEvent(ev);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
            MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, expandSpec);
}
}
Share:
82,427
d-man
Author by

d-man

Full stack Web Developer

Updated on January 31, 2021

Comments

  • d-man
    d-man about 3 years

    I'm having a little difficulties while trying to get a certain layout to work: I want to have list. List does not have to be scrollable, but should be shown completely. But the page itself should be able to scroll (with the lists in it), if the total content ist higher than the screen.

    <ScrollView
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         >
    
         <LinearLayout
             xmlns:android="http://schemas.android.com/apk/res/android"
             android:id="@+id/linear_layout"
             android:orientation="vertical"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:layout_weight="1"
             android:background="#ff181818"
             >
               <Textview android:id="@+id/my_text" text="header contents goes here" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
               <Textview android:id="@+id/headertext" text="header contents goes here" android:layout_width="fill_parent" android:layout_height="wrap_content"/>
    
              <ListView
                   android:id="@+id/my_list1"
                   android:layout_height="wrap_content"
                   android:layout_width="fill_parent"
              /> 
         </LinearLayout> 
    
    </ScrollView>
    

    it only uses a small part of the screen (about 2 lines per list), instead of filling the available height, and the lists themselves can be scrolled. How can I change the layout to always show the whole lists but have the screen be scrollalbe?

  • dierre
    dierre about 12 years
    Shouldn't you pass the object to inflate?
  • Ken
    Ken over 11 years
    what is R.layout.product_item??
  • Alex
    Alex about 11 years
    Linear layout is hardly a replacement. List view has built-in adapter (to fill the item views), dividers between items, item states, item click event.
  • Admin
    Admin about 10 years
    But how can we handle OnItemClick?
  • Justin
    Justin over 9 years
    Not to mention, listview has performance benefits in reusing the row views. If you have a large number of rows then linear layout isn't going to work, scrolling will be extremely choppy.
  • Aritz
    Aritz over 9 years
    What about ListView's benefits? Are they all gone because of the scroll?
  • Behnam
    Behnam over 9 years
    This is a roundabout at best, not real solution.
  • Ivan
    Ivan over 9 years
    listview has advantage of using adapter.using linear layout doesn't implement this convenient feature.
  • Ivan
    Ivan over 9 years
    you can make it with listview not only linear layout
  • Fire
    Fire about 9 years
    This is bad approach, because ListView can use Adapter, and LinearLayout can't.
  • Micah Montoya
    Micah Montoya almost 8 years
    I know everyone says this is a bad approach but a ListView shouldnt be placed inside of a ScrollView. This approach would allow such if you don't need click ability and are only showing a few things. FYI. For those wondering you can populate using the "vi" view as it is your layout for the row. Just my 2 cents.
  • Wackaloon
    Wackaloon almost 8 years
    this is the best idea to make a static list with all visible items
  • AITAALI_ABDERRAHMANE
    AITAALI_ABDERRAHMANE over 7 years
    The best solution for this issue :)
  • Hibbem
    Hibbem over 7 years
    Works like a charm, but shouldn't UIUtils.setListViewHeightBasedOnItems(adapter); be UIUtils.setListViewHeightBasedOnItems(listView); ?
  • hBrent
    hBrent over 7 years
    Seems to work. Pretty much the same as stackoverflow.com/a/27818661/1493426, I think.
  • Gautham C.
    Gautham C. about 7 years
    This is a much better answer as it is an extensible and clean approach.
  • anhtuannd
    anhtuannd almost 7 years
    It looks very clean. I wonder with this one can we place listview inside scrollview?
  • Francisco
    Francisco almost 7 years
    @anhtuannd I haven't try that... But the only thing that change is the onMeasure method, all the scroll methods of the ListView are still working but with nothing to scroll. So if the listview is inside the scrollview I think it will still override those methods. I would look for another approach to do that.
  • ARR.s
    ARR.s over 6 years
    if text in item in listview have more than one line it's not work ,How to fix it
  • Naveed Ahmad
    Naveed Ahmad about 6 years
    Oh man, love you. You are awesome, it worked as required. @d-man this should be the accepted answer
  • Rafael Moreno
    Rafael Moreno almost 6 years
    This worked great! Minor modification when you use relative inflated layouts: Before measure: v.setLayoutParams(new ViewGroup.LayoutParams(0,0));
  • Akhtar Khan
    Akhtar Khan about 5 years
    You can follow this answer: stackoverflow.com/questions/40861136/…
  • Nikita Vishwakarma
    Nikita Vishwakarma almost 5 years
    The best solution.. Thank you
  • Геннадий Курбесов
    Геннадий Курбесов over 3 years
    This is exactly what I was looking for! I have a ListView, it contains 3-4 items. I cannot use static elements as I need all the functionality of the ListView and that solved my problem when I put it in the ScrollView!