70

I'm trying to make a layout like this:

The problem is that I don't want the ListViews to be scrollable. I want them to be as high as they need to and make the whole screen be scrollable. If I set the height of the ListView to wrap_content, that doesn't work. The only way to make it work is to set a specific height - but I don't know how many items will be in the ListView.

I know that I should not put ListView inside ScrollView - but I don't want the ListView to be scrollable, just to show all items.

Maybe there is a better way to make it work?

Ishaan Javali
  • 1,681
  • 3
  • 12
  • 23
Dennis
  • 2,221
  • 6
  • 25
  • 42

7 Answers7

157

You Create Custom ListView Which is non Scrollable

public class NonScrollListView extends ListView {

    public NonScrollListView(Context context) {
        super(context);
    }
    public NonScrollListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public NonScrollListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
                    Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
            ViewGroup.LayoutParams params = getLayoutParams();
            params.height = getMeasuredHeight();    
    }
}

In Your Layout Resources File

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fadingEdgeLength="0dp"
    android:fillViewport="true"
    android:overScrollMode="never"
    android:scrollbars="none" >

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

        <!-- com.Example Changed with your Package name -->

        <com.Example.NonScrollListView
            android:id="@+id/lv_nonscroll_list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
        </com.Example.NonScrollListView>

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/lv_nonscroll_list" >

            <!-- Your another layout in scroll view -->

        </RelativeLayout>
    </RelativeLayout>

</ScrollView>

In Java File

Create a object of your customListview instead of ListView like :
NonScrollListView non_scroll_list = (NonScrollListView) findViewById(R.id.lv_nonscroll_list);

Dedaniya HirenKumar
  • 2,770
  • 2
  • 21
  • 25
  • 2
    When swapping this into an existing codebase, it's likely only the XML needs to be modified after the new class is added; most existing references casting the instance to `(ListView)` should still work fine. – rymo Aug 20 '14 at 05:38
  • your logic is working perfectly for me.But when i enter into the layout that contains nonscrollListview ,that list is showing prior to the details that is displayed above the listview.So the user is compelled to scroll down to view the details that is displayed above the listview.Any solution??? –  Oct 07 '14 at 12:03
  • 1
    @DEV please give information in detail actually what type of layout you needed – Dedaniya HirenKumar Oct 09 '14 at 08:36
  • actually i am using nonscrollable ln my cart layout.The Cart layout contains this nonscrollable listview in middle and other details are showing above and below the listview.But when ever the layout is loaded, this list is projecting first and we have to scroll up and down to view the other details..hope you get it.. –  Oct 15 '14 at 11:53
  • What makes this custom listview non scrollable? I don't see any code that shuts off scrolling. – JPM Nov 12 '14 at 17:43
  • 3
    @Dedaniyahirenkumar, When android displays a layout containing the `NonScrollListView`, the parent `ScrollView` is scrolled to the top of the `NonScrollListView`, rather than the top of the `ScrollView`. (The user must scroll up to the `ScrollView` contents that come before the `NonScrollListView`.) This happens for `EXACTLY` and `AT_MOST` measurement modes, and for any integer height passed to `makeMeasureSpec()` – kdbanman Mar 12 '15 at 20:40
  • 4
    @Dedaniyahirenkumar, However, if the measurement mode is switched to `UNSPECIFIED`, the parent `ScrollView` stays at scroll Y=zero (the expected behaviour). Obviously the `NonScrollListView` does not display its entire contents in this case, however. – kdbanman Mar 12 '15 at 20:42
  • Anybody could fix that issue? – Joaquin Iurchuk Apr 17 '15 at 13:34
  • 1
    That is what i am looking for thank you so much Mr.Dedaniya Hiren It works like a charm :) – Kishan Soni Oct 30 '15 at 13:19
  • 1
    NonScrollListView didn't notify adapter every time i scrolled the scrollview top and down, eg, when i put time change with seconds when scroll the listview this time will change , but in this NonScrollListView the time not change, programmatically this NonScrollListView didn't recycle it's view – mostafa hashim Nov 19 '15 at 09:53
  • 1
    Worked fine for me but have one problem when list item is 1 or 2 that time remaining space of screen getting full white.. Any suggestions.. – CrazyMind Jan 08 '16 at 11:43
  • 1
    To all of you doubting: This works! To answer's author: Thank you for the great help, saved lots of time! – PALEN May 02 '16 at 21:57
  • 1
    Thank you so much. I've been searching for a working solution for the past 30 minutes now and this is the only one that does what I want, thanks! – Stefan Teunissen Oct 22 '16 at 20:42
  • i am finding this type of solution for which project i lead right now...thanl you very much @hiren (Talala Gir) – seggy Nov 16 '16 at 09:07
  • Best solution, I was not going to accept a "You cant't nest a list inside a scrollview" as an answer. – Josh Jan 23 '18 at 13:47
  • Brother, I bloody love you. Thank you, brilliant! – yUdoDis Mar 21 '18 at 14:10
  • Hello. This is a great implementing. However When I have more than 200 items to load in this view. it takes 10 second to load the data onto it. If there away to improve it ? – Thiago Apr 05 '18 at 08:30
  • I used with `LinearLayout` and got one problem, the `ScrollView` scrolled when I touch in other layouts but `NonScrollListView`. So when my list have many items, the `NonScrollListView` filled up the whole screen, I cannot do anything. Does anyone faced with this? – Jacky Apr 26 '19 at 07:07
  • Amazing! Worked for me perfectly! – Alex Wang Sep 18 '19 at 15:53
10

There is no need to use a listview at all.

If you really think about it, a listview can be replaced with a LinearLayout in your case. The Adapter would be the same, however instead of attaching the adapter with your listview, simply call the getView function of the adapter in a for loop on your data and add the retrieved views to your vertical linearlayout.

However this approach is only recommended if you have a small number of items in your list and your display representation of those items is not memory intensive.

Ishaan Javali
  • 1,681
  • 3
  • 12
  • 23
Sam
  • 3,373
  • 1
  • 16
  • 20
  • i use linear layout instead of list view, it work but items that there are not space do not seen! i use linear layout in parent – Hossein Apr 29 '14 at 20:37
  • `LinearLayout` isn't a fair replacement for `ListView` when you want to use the goodness behind `AbsListView.CHOICE_MODE_MULTIPLE_MODAL` - to avoid reinventing the wheel, see the `NonScrollListView` solution – rymo Aug 20 '14 at 05:32
  • I think that replacing ListView with LinearLayout seems logic, but also you lose the ability of recycling that is inherent to a ListView. Try to have a LinearLayout and charge it dynamically by inflating a lot of views inside it. Garbage collector will go nuts – Joaquin Iurchuk Apr 17 '15 at 13:23
2

The best way to do this (in 2017) is to use a RecyclerView with a NestedScrollView.

No hacks required and it works out of the box like you want it to.

Ishaan Javali
  • 1,681
  • 3
  • 12
  • 23
Anthony Chuinard
  • 1,018
  • 10
  • 16
  • 1
    Whilst that is a nice solution, I don't think it is what the OP wanted as `The problem is that I don't want the ListViews to be scrollable` – Dan Apr 02 '18 at 19:06
0

Well, there is a cool Android guy named Mark Murphy a.k.a. CommonsWare and he built a very useful component named CWAC Merge Adapter that allows you to do what you need. You'll need to add the views dynamically and not from XML; but considering your simple UI, that shouldn't be a problem. I'm using it for these kind of cases when I have no idea on what kind of data I'm supposed to scroll.

If you don't want to use it (for licensing reasons maybe), you can have a single listview there (instead of those 2 consecutive list-views) and override getItemViewsCount, getItemViewType and getView in order to give above layout. If you search android listview different rows on Google you'll find useful info. For example this link, or this one.

However, I would go for merge-adapter.

Community
  • 1
  • 1
gunar
  • 14,580
  • 7
  • 55
  • 86
  • Thank you. The problem is that I want the ImageView and the TextView TO BE scrollable - if I scroll down they'll go up and the items in the ListView will appear. – Dennis Sep 15 '13 at 14:35
  • Then use the merge adapter and add the ImageView and TextView in there. Even with multiple listtypes you can do the same thing by setting view type for ImageView and TextView as 1 and 2. For the rest of the types you could have 3 and 4. – gunar Sep 15 '13 at 14:38
0

I have a easy solution if it's possible to calculate your item height/wide ... You just need to create a parent Linearlayout of ListView and then fixed parent Height from Java.

enter image description here

Suppose you need to design this view... Now Parent layout size is defining from java...

final LinearLayout parent=(LinearLayout)findViewById(R.id.parent);
final ListView  listview=(ListView)findViewById(R.id.listview);
parent.setLayoutParams(new LinearLayout.LayoutParams(parent.getLayoutParams().width, dpToPx( number_of_item_in_list * per_item_size_in_dp )));
//number_of_item_in_list is list side ~ listArray.size();
//per_item_size_in_dp = calculate item size in dp. Ex: 80dp

public static int dpToPx(int dp)
{
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}

that's all :)

Shohan Ahmed Sijan
  • 4,211
  • 1
  • 31
  • 38
0

Choose the ListView that's you want to be Scrollable, and after that add the method 'setOnTouchListener' to automatically the system insert the scroll inside the ListView

final ListView listview = (ListView) findViewById(R.id.list);


    listview.setOnTouchListener(new ListView.OnTouchListener()
    {
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            int action = event.getAction();
            switch (action)
            {
                case MotionEvent.ACTION_DOWN:
                    // Disallow ScrollView to intercept touch events.
                    v.getParent().requestDisallowInterceptTouchEvent(true);
                    break;

                case MotionEvent.ACTION_UP:
                    // Allow ScrollView to intercept touch events.
                    v.getParent().requestDisallowInterceptTouchEvent(false);
                    break;
            }

            // Handle ListView touch events.
            v.onTouchEvent(event);
            return true;
        }
    });
    listview.setClickable(true);

I hope that works for you

0
  1. How to scroll listView In scrollView

    listViewName.setOnTouchListener(new ListView.OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
        int action = event.getAction();
        switch (action) {
          case MotionEvent.ACTION_DOWN:
            // Disallow ScrollView to intercept touch events.
            v.getParent().requestDisallowInterceptTouchEvent(true);
            break;
          case MotionEvent.ACTION_UP:
            // Allow ScrollView to intercept touch events.
            v.getParent().requestDisallowInterceptTouchEvent(false);
            break;
        }
        // Handle ListView touch events.
        v.onTouchEvent(event);
        return true;
      }
    });
    listViewName.setClickable(true);
    
cassioso
  • 918
  • 1
  • 12
  • 27
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-ask). – Community Sep 14 '21 at 11:07