Monday, December 24, 2012

ListView into ScrollView in Android

Hello Friends!
Today I am going to share very important code for ListView into ScrollView.
Many Android developers says: You should not put a ListView in a ScrollView because a ListView already a scrollview.

 But some times its really needed in project “ how can place a ListView into a ScrollView without it collapsing to its minimum height?

And finally I got it on stack over flow-

waste a lot of time in goggling so I don’t want some one do same so you can follow my blog 
step by step-

UPDATE: Please check my this post for in case any of issue-
http://www.androidhub4you.com/2014/03/android-listview-into-scrollview-issue.html

PrintScren:


Step1- Create an Activity name-MainActivity.java and create a listview.

package com.example.scrollviewlistviewdemo;

import android.os.Bundle;
import android.app.Activity;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends Activity {
       private String listview_array[] = { "ONE", "TWO", "THREE", "FOUR", "FIVE",
                     "SIX", "SEVEN", "EIGHT", "NINE", "TEN" };
       ListView myList;

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

              myList = (ListView) findViewById(R.id.listView);
              myList.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, listview_array));
              Helper.getListViewSize(myList);
      
       }
}
Step2- Create main.xml-
<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"
    tools:context=".MainActivity" >

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

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="19dp"
            android:text="@string/hello_world" />

        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@drawable/ic_launcher" />

        <ListView
            android:id="@+id/listView"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />
    </LinearLayout>

</ScrollView>

Step3- Finally and important thing create another class Helper.java and put below given code-
package com.example.scrollviewlistviewdemo;

import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.ListView;

public class Helper {
    public static void getListViewSize(ListView myListView) {
        ListAdapter myListAdapter = myListView.getAdapter();
        if (myListAdapter == null) {
            //do nothing return null
            return;
        }
        //set listAdapter in loop for getting final size
        int totalHeight = 0;
        for (int size = 0; size < myListAdapter.getCount(); size++) {
            View listItem = myListAdapter.getView(size, null, myListView);
            listItem.measure(0, 0);
            totalHeight += listItem.getMeasuredHeight();
        }
      //setting listview item in adapter
        ViewGroup.LayoutParams params = myListView.getLayoutParams();
        params.height = totalHeight + (myListView.getDividerHeight() * (myListAdapter.getCount() - 1));
        myListView.setLayoutParams(params);
        // print height of adapter on log
        Log.i("height of listItem:", String.valueOf(totalHeight));
    }
}

Hope it will help you thanks!

109 comments :

  1. HI Manish, nice blog could you please let me know your contact info.

    ReplyDelete
    Replies
    1. Hi Abhay, Thanks for your comment you can find me on my blog "About Me" page..
      http://www.androidhub4you.com/p/about.html

      Thanks,

      Delete
    2. thanks work great!

      Delete
    3. Hi ,

      Plz give me sample how to get gridview insode scroll view. It is one of my modulus.

      Delete
  2. Thanx Manish Srivastava !!! It works properly !! Thanx again..

    Parwinder

    ReplyDelete
  3. I'm getting this error in my application:

    FATAL EXCEPTION: main
    java.lang.NullPointerException
    at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:493)
    at android.view.View.measure(View.java:15513)
    (...)

    Can you help me? Thanks a lot

    ReplyDelete
    Replies
    1. Hi!
      Its seems you are trying to add a view into your Relative Layout? If yes please don't add it in xml file just create a view in xml and add it in your activity.
      Or some thing else? let me know in detail? what are you doing in your code? only Log cat is not enough to find out bug..

      Thanks,

      Delete
  4. Hi Manish, in my listview I have rows with different height and the method getMeasuredHeight in for loop returns same height for every row. Do you have any idea why it returns wrong height? Thanks a lot

    ReplyDelete
    Replies
    1. Hi Tomas, I think you are working on custom list-view using custom adapter - BaseAdapter or ArrayAdapter.

      So also in this case my demo is working fine. Because I am getting size of adapter not a list-view..

      So if you have demo app please mail me I will try to short out your problem.

      Thanks,
      Manish

      Delete
    2. Thank you, but I found almost the same solution here http://nex-otaku-en.blogspot.cz/2010/12/android-put-listview-in-scrollview.html .

      Delete
    3. Then what you want from me? do you want promote above link here?

      Delete
  5. Hi Manish,
    thanks for this blog,that's work great but if u use custom listview with custom adapter u need to add :
    if (listItem instanceof ViewGroup)
    listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    before set mesure : listItem.measure(0, 0);

    ReplyDelete
  6. Hi Jamal thanks for your nice suggestion, I appreciate your R&D but my code is working Okay for every case , I mean simple list view and custom list view both..

    Infect my one reader getting some other type of issue but I have no time for R&D. If you really want to help me try one thing just change array item size like-
    private String listview_array[] = { "ONEkkkkkkkkkkkkkkkkkkkkkkkjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkk", "TWO", "THREE", "FOUR", "FIVE","SIX", "SEVEN", "EIGHT","NINEhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", "TEN" };

    Now you will see you are not getting all list-view item correctly. Problem is measurement of Adapter If you can see on it please check it..

    Thanks,

    ReplyDelete
    Replies
    1. Hi Manish,

      Thanx for such a wonderful tutorial, actually i was facing a problem for custom listView while calculating measure.
      But....

      Hi Jamal,

      Thanx for such a good point while using custom adapter like viewgroup.

      I used both of yours code, it working nice to me for custom adapter.

      Thank you once again :)

      Delete
    2. Hello Sudhir!
      Thanks for your comment...
      Have you got any solution? Please post here..

      Thanks a lot..

      Delete
  7. Hi Srivastava how are u ?
    that's true i had the same problem using BaseAdapter, i didn't get the real size of the list beacuse the size of textview change on the layout row of the list, and i'm always looking for solution.

    ReplyDelete
    Replies
    1. Please try at your end and when I will got any solution I will inform you..

      Well we can try simple View instead of List-view into scroll-view in this case :)

      Delete
  8. Wow, It works properly !! Thanks Manish and nice blog,

    ReplyDelete
  9. Hello manish,
    Nice blog, but i have a Question that, if i use Your class then it automatically scrolls down to listview, eventhough i am having some component on top, the view gets automatically scrolled at listview first index.

    I wanted to know if i can keep the view at top position only.

    ReplyDelete
    Replies
    1. I am not sure but try something like that-
      scrollViewEventDetails.fullScroll(View.FOCUS_UP);//if you move at the end of the scroll

      scrollViewEventDetails.pageScroll(View.FOCUS_UP);//if you move at the middle of the scroll

      Delete
    2. Well i have tried this, but not yet successfull...

      Delete
    3. Please search on google and stack overflow...and please put your answer here also so other can get help from your comment..
      Thanks..

      Delete
    4. nice work very useful info thanks

      Delete
  10. One thing is if you Use Runnable Method and inside it use your function. Keep sleep for 1 second, then the problem gets solved, the top view is always displayed, but it is not correct.

    Will definitely post here if i get a proper solution.

    Thank You.

    ReplyDelete
    Replies
    1. your most welcome I am waiting for your solution..

      Thanks,

      Delete
  11. I'm got error like this

    06-06 18:15:17.709: E/AndroidRuntime(9685): FATAL EXCEPTION: main
    06-06 18:15:17.709: E/AndroidRuntime(9685): java.lang.NullPointerException
    06-06 18:15:17.709: E/AndroidRuntime(9685): at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:470)
    06-06 18:15:17.709: E/AndroidRuntime(9685): at android.view.View.measure(View.java:15367)
    06-06 18:15:17.709: E/AndroidRuntime(9685): at com.truelife.tvtalk.TopicDetailHelper.getListViewSize(TopicDetailHelper.java:20)

    I use listview that set getview in myadapter class

    my code in Activity

    mAdapter = new TopicDetailCommentAdapter(this, MyArrList);
    listView1.setAdapter(mAdapter);
    TopicDetailHelper.getListViewSize(listView1);

    ReplyDelete
  12. and my adapter class

    public class TopicDetailCommentAdapter extends BaseAdapter {

    private Context context;
    private ArrayList> data;
    private static LayoutInflater inflater = null;

    public TopicDetailCommentAdapter(Context ct,
    ArrayList> d) {
    data = d;
    context = ct;
    inflater = (LayoutInflater) context
    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public int getCount() {
    // TODO Auto-generated method stub
    return data.size();
    }

    @Override
    public Object getItem(int position) {
    // TODO Auto-generated method stub
    return position;
    }

    @Override
    public long getItemId(int position) {
    // TODO Auto-generated method stub
    return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    View rowView = convertView;
    HashMap dataValue = new HashMap();
    dataValue = data.get(position);
    if(rowView == null) {
    rowView = inflater.inflate(R.layout.topic_detail_item, null);
    }

    try {

    ImageView imgViewAvatar = (ImageView) rowView.findViewById(R.id.ColAvatarComment);
    TextView txtComment = (TextView) rowView.findViewById(R.id.CommentDetail);
    TextView txtDateCreate = (TextView) rowView.findViewById(R.id.CommentCreated);
    final String userId = dataValue.get("user_id");
    String is_edit = dataValue.get("is_edit");
    final String boardId = dataValue.get("board_id");
    final String topicId = dataValue.get("topic_id");
    txtComment.setText(dataValue.get("CommentDetail"));
    txtDateCreate.setText(dataValue.get("CommentCreated"));

    String filename = dataValue.get("ColUserAvatar");
    if (filename != "") {
    ImageLoader.getInstance()
    .load(imgViewAvatar, filename, true);
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    return rowView;
    }
    }

    ReplyDelete
    Replies
    1. Your code is looking okay only one doubt here-
      1)where you have set your row layout? I can't see in you activity class nor CustomAdapter class..

      Please do one thing first remove scrollview and without measure it run your app.. is it working fine or not let me know please?

      Delete
    2. Hello this solution is not working for my code..please help.I am inserting items in list view dynamically..for dynamic insertion of items it is not working..It is working for static insertion of items

      Delete
    3. Please try this article, it will work 100%-
      http://www.androidhub4you.com/2014/03/android-listview-into-scrollview-issue.html

      Delete
  13. the man like you are rare thank you so much manish this code really very much help for me

    thanks

    ReplyDelete
  14. this method works but the last item of list is not completely visible.

    ReplyDelete
  15. Hi Manish,

    How can you access the non visible items of listview??
    > I have a list view which contains some 20 odd items along with a check
    > box. I am trying to set all the checkboxes when the first checkbox is clicked or checked,

    > iam getting NullPointerException at below written code, present inside the OnCheckedChange listener:
    >
    > CheckBox cbox= (CheckBox) view.getChildAt(j).findViewById (R.id.alarmCheck);
    >
    > here view.getChildAt(j) comes null, which is valid since the views are not visible and hence are not instantiated...

    > > Now if I have six elements in this ViewList, which are visible on the
    > > emulator, then the same code just works fine.
    > > Problem arises when the list is long and it starts scrolling and some
    > > element are not visible.
    > > I am working on this problem for some days, any help will be highly
    > > apperciated.

    ReplyDelete
    Replies
    1. I am not sure why this issue happening and what you trying to do actually..
      But in case of ListView, listview load only that part which part is visible and on scroll when top portion or bottom portion are invisible that will not load by listview. I think that make issue in your case.

      So my idea is that assign a value to all checkbox at the time of declaration time don't leave it null. Hope that will work for you or try to do something like that-
      if(chkBox1!=null){
      //add into listview
      }

      Thanks,
      Manish

      Delete
  16. Hi manish, could you answer please how i can do same thing for ExpandableListView

    ReplyDelete
    Replies
    1. Sorry Dear I have no idea, You can try by yourself..
      If you got any thing positive please let me know, I will thankful to you..

      Thanks!

      Delete
  17. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
  18. This is not working in my case can u please help me My layout is......
    Scrollview
    linearlayout
    framelayout
    viewpager
    viewpagerindicator
    framelayout
    listview
    progressbar
    linearlayout
    Scrollview

    ReplyDelete
    Replies
    1. Very complex layout, i am not sure it will work or not.. Please test it at your end.
      Thanks,

      Delete
    2. I have tested it at my end...it is not scrolling...full container.
      again it is scrolling listview only...

      Delete
  19. tengo la siguiente estructura

    ScrollView
    LinearLayout
    TextView
    ListView
    TextView

    /ScrollView
    /LinearLayout
    /TextView
    /ListView
    /TextView

    Pero me deja mucho espacio debajo del Listview, quizas unos 10 cms antes de mostrar el TextView, alguna solución.

    Acá el xml completo

    http://pastebin.com/PAx50nZv

    ReplyDelete
  20. this is the corrected structure

    ScrollView
    LinearLayout
    TextView
    /TextView
    ListView
    /ListView
    TextView
    /TextView
    /LinearLayout
    /ScrollView

    ReplyDelete
    Replies
    1. It is looking okay and it should scroll.

      Delete
  21. This is a bad solution guy. That Helper class loads all the views, therefore the ListView is not recycling its views. You will run into performance issues if you've got a large dataset and then throw in if each row view dowloads images via a webservice. The app will crash miserable. There's always repercussions using hack methods of doing stuff. The folks at Google know why they categorically stated that wrapping a ListView in a ScrollView is not a suitable design pattern. Guys be careful copying and pasting code!

    ReplyDelete
    Replies
    1. Yes you are right. It is not right solution. But some time if needed you can use this method, measure list-view adapter. Best way is linear layout instead of list-view inside scroll-view.

      Thanks!

      Delete
  22. Thanks Dear Manish..Good thoughts ...

    ReplyDelete
  23. This is working but since I am using a GridView, I can't seem to get the right totalHeight of my GridView. How do I calculate it properly?

    ReplyDelete
    Replies
    1. Sorry dear its have issue with custom views. Its give us wrong measurement. Please try another logic don't use listview inside scrollview.

      Delete
    2. Please try @Jamal Comment hope it will help you. last guys commented that its work for him-

      Hi Manish,
      thanks for this blog,that's work great but if u use custom listview with custom adapter u need to add :
      if (listItem instanceof ViewGroup)
      listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
      before set mesure : listItem.measure(0, 0);

      Delete
  24. hi mani
    your code is nice its working fine.but my prblm is when i am scrollling down its keep on coming even if no content.i am not getting y its behaving like this.

    ReplyDelete
    Replies
    1. which type of listview do you have simple or custom?

      Delete
  25. Thanks Jamal your answers really helps me to come out of this problem.

    ReplyDelete
    Replies
    1. Sajad, thanks for response back it will help to others.. Really Thanks!

      Delete
    2. Welcome dear Manish,Nice job from you as well.......thanks

      Delete
  26. Hey Dude Thanksssss it workssss!!!

    ReplyDelete
  27. Manish i got a problem here that the last item does't display compleatly .what is the problem ?

    ReplyDelete
    Replies
    1. I have already told that this is not good way to do thing listview inside scrollview. In case of custom views it does not work perfectly. well you have tried Jamal answer that did not help you?

      Delete
    2. it just total height problem..some how not able to get total height to draw all view...I added
      2* (listItem.getMeasuredHeight()) and it working fine for me...tested it on emulator.

      Delete
    3. @Shubham he he he its totally "Indain Jugadh" not a developer logic. You did a great job, I appreciate your logic but in every case it will not work.. Anyway thanks for posting your answer..

      Delete
  28. Hiii
    Thanks Manish ....
    This article helped me to solve my problem .............

    ReplyDelete
  29. Nice post, helped me a lot, just one thing. When you are using your own adapter you have to use that adapter in the helper to get the correct size

    ReplyDelete
  30. Hi Manish.
    You resolved me a big thing... I'm very pleased... cheers, and keep going, you're fantastic!

    ReplyDelete
  31. your blog is nice .. i m working on android appliacation i designed screen having radio buttons search edittext and buttons but when i m testing the application in mobile then keybord appear....and i cant see what i m selecting and typing in the edittext... so is there any way to scroll whole layout automatically when i m typing on keybord?? i have used many linearlayout in one root linearlayout....

    ReplyDelete
    Replies
    1. It should automatic scroll. Is your page have custom view like custum gridview etc? If your page is big please use scrollbar as parent of all views.

      Delete
  32. Hi ,

    Plz give me sample how to get gridview insode scroll view. It is one of my modulus.

    Read more: http://www.androidhub4you.com/2012/12/listview-into-scrollview-in-android.html#ixzz2mtyedwMc

    ReplyDelete
    Replies
    1. if you put gridview inside scroll-view any problem here?

      Delete
    2. The problem I am getting is when I mention layout_height attribute as wrap_content,fill_parent and match_parent it is showing only one row of the grid and it is giving a warning like "GridView and ListView should not be mentioned in ScrollView"

      Delete
    3. You are right we can't put any touch view inside other view like listview or gridview inside the scrollview. But try above logic may be it will help you. I have did it for listview just try above code for gridview may be it will work..

      Delete
    4. the above code works for me for GridView but the issue is I have a BaseAdapter class. I am getting problem in getting height of that adapter class. Please give me an idea on this.

      Delete
    5. BaseAdapter means? your CustomAdapter class which one is extend from BaseAdapter right? so you are not getting correct view?

      Delete
    6. Yes

      I am giving code which I tried

      public class NoteAdapter extends BaseAdapter {

      private Activity activity;
      private ArrayList> data;

      private static LayoutInflater inflater=null;
      int totalHeight = 0;

      public NoteAdapter(Result result,
      ArrayList> mylist) {
      // TODO Auto-generated constructor stub

      activity = result;
      data=mylist;
      //data2=mylist2;
      //data3=mylist3;

      System.out.println("Reminders is : "+data.size());
      //System.out.println("Expense is : "+data2.size());

      inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      }

      @Override
      public int getCount() {
      return data.size();
      }

      @Override
      public Object getItem(int position) {
      return position;
      }

      @Override
      public long getItemId(int position) {
      return position;
      }

      @Override
      public View getView(int position, View convertView, ViewGroup parent) {
      View vi=convertView;

      if(convertView == null)

      vi = inflater.inflate(R.layout.note_item, null);

      TextView title = (TextView)vi.findViewById(R.id.name);// title
      //TextView title1 = (TextView)vi.findViewById(R.id.name1);
      HashMap event = new HashMap();

      event = data.get(position);
      //ListAdapter myListAdapter = myListView.getAdapter();
      totalHeight += vi.getMeasuredHeight();
      //totalHeight += data.size();
      ViewGroup.LayoutParams params = title.getLayoutParams();
      params.height = totalHeight + (title.getHeight()); /** (myListAdapter.getCount() - 1));*/
      title.setLayoutParams(params);

      System.out.println("Note data is : "+event);
      title.setText(event.get(Result.KEY_NOTENAME));
      //title1.setText(event.get(Result.KEY_NOTENAME));

      return vi;
      }
      }

      Please check

      Delete
  33. Well this is pretty good blog where I found some useful information especially about android app development that most important in now a days. I'd like to say thank for this stuff keep it up dear..!

    ReplyDelete
  34. Thank you very much. it's good tutorial.

    ReplyDelete
  35. How I can do to make the focus of this app up and not on the first result of the listview?

    ReplyDelete
    Replies
    1. i think you should use android:focusable="false" or "true" in you scrollview.

      Delete
  36. Hi , This article is good. But i used ExpandableListView in the place of ListView. Then it is only scrolling expandable view, it not scrolling entire view. I have another LinearLayout contains two Buttons under Expandablelistview, those buttons are not scrolling. Could you help in out to fix it. My parent layout is ScrollView.

    Thanks in advance.
    Venkat K

    ReplyDelete
  37. hi Manish

    i'm using a custom listview and height of that is fixed.. i.e. only one item should be visible, if we scroll then we can see the other elements.

    Prob: I'm having a edit text, pick contact and add more contacts.
    so if i click add more contacts then it will add to the listview and will display, this works fine with pick contacts but problem is with edit text if i enter the phone number.. it won't scroll.

    Can you please suggest me a solution.

    Thanks in adavance. :)

    ReplyDelete
    Replies
    1. Try this link-
      http://www.androidhub4you.com/2014/03/android-listview-into-scrollview-issue.html

      Delete
  38. Hi Manish,

    I have tried the your listview sample with GridView (through CustomAdapter extends with BaseAdapter). But it the height of the gridview is growing as too large while scrolling. Please give some suggestion For me.

    ReplyDelete
    Replies
    1. Try to add your gridview into Linear some thing like this-
      http://www.androidhub4you.com/2014/03/android-listview-into-scrollview-issue.html

      Delete
  39. Thank!!!!! this solved my problem! omg, I had long been looking for a solution, thank again!

    ReplyDelete
    Replies
    1. Your welcome and in case of any issue you can follow this article-

      http://www.androidhub4you.com/2014/03/android-listview-into-scrollview-issue.html

      Delete
  40. The code which you posted has flaw...you are saying that ListView and ScrollView works but in this code only ScrollView is working and not the ListVIew. Check to it......

    ReplyDelete
  41. works like a charm! thank you ! :) :)

    ReplyDelete
  42. Dear Manish Srivastava,Thank you so so much. It is really working. You are so smart.

    ReplyDelete