android listview display all available items without scroll with static header

Viewed 83404

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?

13 Answers

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);
}

I don't have a static header, but using HussoM's post as a clue, here is what I was able to get to work. In my scenario, the height of the items in the list was non-uniform, due to variable text sentences in each of the items, and I am using wrap_content for the height and match_parent for the width.

public class NonScrollableListView extends ListView {

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

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

  public NonScrollableListView(Context context, AttributeSet attrs, int defStyleAttr) {
      super(context, attrs, defStyleAttr);
  }

  public NonScrollableListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
      super(context, attrs, defStyleAttr, defStyleRes);
  }

  /**
   * Measure the height of all the items in the list and set that to be the height of this
   * view, so it appears as full size and doesn't need to scroll.
   * @param widthMeasureSpec
   * @param heightMeasureSpec
   */
  @Override
  public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      ListAdapter adapter = this.getAdapter();
      if (adapter == null) {
          // we don't have an adapter yet, so probably initializing.
          super.onMeasure(widthMeasureSpec, heightMeasureSpec);
          return;
      }

      int totalHeight = 0;

      // compute the height of all the items
      int itemCount = adapter.getCount();
      for (int index=0; index<itemCount; index++) {
          View item = adapter.getView(index, null, this);
          // set the width so it can figure out the height
          item.measure(widthMeasureSpec, 0);
          totalHeight += item.getMeasuredHeight();
      }

      // add any dividers to the height
      if (this.getDividerHeight() > 0) {
          totalHeight += this.getDividerHeight() * Math.max(0, itemCount - 1);
      }

      // make it so
      this.setMeasuredDimension(widthMeasureSpec,
              MeasureSpec.makeMeasureSpec(totalHeight, MeasureSpec.EXACTLY));
  }

}

If you want a simple solution to this problem without extending ListView class, this is a solution for you.

 mListView.post(new Runnable() {
        @Override
        public void run() {
            int height = 0;
            for(int i = 0; i < mListView.getChildCount();i++)
                height += mListView.getChildAt(i).getHeight();
            ViewGroup.LayoutParams lParams = mListView.getLayoutParams();
            lParams.height = height;
            mListView.setLayoutParams(lParams);
        }
    });

In my case, I had ListView inside ScrollView and scrollview was shrinking listview by default. So I just add this in my ScrollView and it worked for me

android:fillViewport="true"

Set android:layout_height="fill_parent" in your LinearLayout

Related