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-

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!

32 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
  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
  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
  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
  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