how to maintain scroll position of listview when it updates

32,308

Solution 1

It is easier to maintain scroll position by calling notifydatasetchanged() only. The problem there is that you are creating a new adapter every time the data gets updated... you should do something like this:

if(listView.getAdapter()==null)
   listView.setAdapter(myAdapter);
else{
   myAdapter.updateData(myNewData);  //update adapter's data
   myAdapter.notifyDataSetChanged(); //notifies any View reflecting data to refresh
}

This way, your listview will mantain the scrolling position.

In case you want to scroll to a new position, use:

list.smoothScrollToPosition(int position);

Solution 2

In case for some reason you don't want to call notifyDataSetChanged(), the you can maintain the position by using setSelectionFromTop()

Before updating the adaptor:

lastViewedPosition = listView.getFirstVisiblePosition();

//get offset of first visible view
View v = listView.getChildAt(0);
topOffset = (v == null) ? 0 : v.getTop();

After updating the adaptor:

listView.setSelectionFromTop(lastViewedPosition, topOffset);

Solution 3

list.smoothScrollToPosition(int position);     //my favorite :)

It may also help you to scroll nice'n'smooth to a particular item

Solution 4

listview.setSelection( i );

this will help you to set particular row at top

Solution 5

For overall picture:

In your API response callback, call this function(example) below:

MyAdapter mAdapter;
ArrayList<Users> mUsers;

private void updateListView(ArrayList<Users> users) {
    mUsers.addAll(users);
    if(mAdapter == null) {
        mAdapter = new MyAdapter(getContext(), mUsers);
        mListView.setAdapter(mAdapter);
    }
    mAdapter.notifyDataSetChanged(); // Add this one
}
Share:
32,308

Related videos on Youtube

Aalok Sharma
Author by

Aalok Sharma

Updated on April 23, 2020

Comments

  • Aalok Sharma
    Aalok Sharma about 4 years

    I have read plenty of examples ,but if I wish to maintain my scroll position after a ListView is updated from JSON ,then can I do that without using an AsyncTask instance ???

    the code for my list is

     String wrd;
        //ArrayList<HashMap<String,String>> mylist;
        @Override
        public void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            Intent i2=getIntent();
             wrd=i2.getStringExtra("entrd");
            Log.v("keyis",wrd);
    
    
    
            final Handler handler = new Handler();
            Runnable runable = new Runnable() {
    
                @Override
                public void run() {
    
                    //call the function
                    LoadData();
                    //also call the same runnable
                    handler.postDelayed(this, 40000);
                }
            };
            handler.postDelayed(runable, 10);
    
        }public void LoadData(){
    
    
             JSONObject j2=JSONfunctions.getJSONfromURL("/webservice_search.php?keyword="+wrd+"&format=json");
             ArrayList<HashMap<String,String>> mylist = new  ArrayList<HashMap<String,String>>();
    
             try{JSONArray jray=j2.getJSONArray("listings");
                for(int i=0;i<jray.length();i++){
                    Log.v("state","json data being read");
                    JSONObject j3= jray.getJSONObject(i);
                    String first=j3.getString("listing");
                    Log.v("sublist", first);
                    JSONObject j4=j3.getJSONObject("listing");
                    String sec=j4.getString("links");
    
                    int maxLength = (sec.length() < 30)?sec.length():27;
                    sec.substring(0, maxLength);
                    String cutsec=sec.substring(0,maxLength);
                    Log.v("links are",cutsec);
                    String img=j4.getString("image_name");
                    Log.v("image name is ",img);
                    //Uri dimg=Uri.parse("http://zeesms.info/android_app_images/Koala.jpg");
                    HashMap<String,String> map=new HashMap<String,String>();
    
                    map.put("Id",String.valueOf(i));
                    map.put(Li_nk,cutsec);
                    map.put(Image_name,j4.getString("image_name"));
    
                    map.put(KEY_THUMB_URL,"http://zeesms.info/android_app_images/"+img);
                    mylist.add(map);
    
                }
    
                }
                catch(JSONException e){
    
                    Log.e("loG_tag","Error parsing"+e.toString());
                }
             LazyAdapter adapter = new LazyAdapter(this,mylist);
             adapter.notifyDataSetChanged();
    
                ListView list=(ListView)findViewById(R.id.lv1);
                 list.setEmptyView(findViewById(R.id.empty));
                 list.setAdapter(adapter);
    
                    list.setItemsCanFocus(false);
    

    and my adapter is

    public class LazyAdapter extends BaseAdapter {
    private Activity activity;
    private ArrayList<HashMap<String, String>> data;
    private static LayoutInflater inflater=null;
    public ImageLoader imageLoader; 
    
    
    public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
        activity = a;
        data=d;
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        imageLoader=new ImageLoader(activity.getApplicationContext());
    }
    
    @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) {
        View vi=convertView;
        if(convertView==null)
    
            vi = inflater.inflate(R.layout.custom_row_view1, null);
    
        TextView title = (TextView)vi.findViewById(R.id.linkname); // merchnts name
        TextView artist = (TextView)vi.findViewById(R.id.imagename); // address
        //TextView duration = (TextView)vi.findViewById(R.id); // distance
       ImageView thumb_image=(ImageView)vi.findViewById(R.id.mClogo); // logo
    
        HashMap<String, String> jsn = new HashMap<String, String>();
        jsn = data.get(position);
    
        // Setting all values in listview
       title.setText(jsn.get(Second.Li_nk));
       artist.setText(jsn.get(Second.Image_name));
        //duration.setText(song.get(CustomizedListView.KEY_DURATION));
        imageLoader.DisplayImage(jsn.get(Second.KEY_THUMB_URL), thumb_image);
        return vi;
    }
    

    and finally the class being used for json parsing is

        public class JSONfunctions {
    
    
        public static JSONObject getJSONfromURL(String url){
            InputStream is = null;
            String result = "";
            JSONObject jArray = null;
            String  str1="http://zeesms.info"+url;
    
      // ArrayList<NameValuePair> namevaluepairs = new ArrayList<NameValuePair>();
            Log.v("url result",url);
            //namevaluepairs.add(new BasicNameValuePair("location",str1));
            //http post
            try{   
                HttpClient httpclient= new DefaultHttpClient();
                HttpGet request = new HttpGet();
    
                request.setURI(new URI(str1));
                HttpResponse response = httpclient.execute(request);
    
                is  = response.getEntity().getContent();
                if(is==null){
                     Log.v("url result","is  null");
                }
                else
                {
                    Log.v("url result","is  not null");
                }
    
            /*    BufferedReader buf = new BufferedReader(new InputStreamReader(is,"UTF-8"));
    
                StringBuilder sb = new StringBuilder();
                String s;
                while(true )
                {
                    s = buf.readLine();
                    if(s==null || s.length()==0)
                        break;
                    sb.append(s);
    
                }
                buf.close();
                is.close();
    
                sb.toString();  */
    
    
    
            //  httppost.setEntity(new UrlEncodedFormEntity(namevaluepairs));
                //HttpResponse response=httpclient.execute(httppost);
                //HttpEntity entity=response.getEntity();
                //is=entity.getContent();
    
    
                /*
                    HttpClient httpclient = new DefaultHttpClient();
                    HttpPost httppost = new HttpPost(url);
                    HttpResponse response = httpclient.execute(httppost);
                    HttpEntity entity = response.getEntity();
                    is = entity.getContent();
    */
            }catch(Exception e){
                    Log.v("log_tag", "Error in http connection "+e.toString());
    
                    AlertDialog.Builder alert=new AlertDialog.Builder(null);
                    alert.setMessage("Invalid Keyword").setPositiveButton("Ok", new OnClickListener(){
    
                        @Override
                        public void onClick(DialogInterface arg0, int arg1) {
                            // TODO Auto-generated method stub
    
                        }
    
                    });
            }
    
          //convert response to string
            try{
                Log.v("url result","getting result starts");
    
                    BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
    
                    StringBuilder sb = new StringBuilder();
    
                    String line = null;
                    Log.v("url result","getting result");
                    while ((line = reader.readLine()) != null) {
                        Log.v("url result","getting result");
                            sb.append(line + "\n");
                    }
    
                    is.close();
    
                    result=sb.toString();
                    Log.v("url result",result);
    
            }catch(Exception e){
                    Log.e("log_tag", "Error converting result "+e.toString());
            }
    
            try{
    
                jArray = new JSONObject(result);            
            }catch(JSONException e){
                    Log.e("log_tag", "Error parsing data "+e.toString());
            }
    
            return jArray;
        }
    
    
    
    }
    

    along with this if the data is updated from the webpage, what would be the simplest way to show the updated item on top ??

  • Aalok Sharma
    Aalok Sharma about 12 years
    should I add this after datasetnotify change ?? or in my oncreate??
  • waqaslam
    waqaslam about 12 years
    at very last - when your list has items to scroll about
  • Aalok Sharma
    Aalok Sharma about 12 years
    Just a quick query,if I wish to reverse the order of my list here ,i.e if I want that the last item shows up first and so on,how do I do tht ?
  • waqaslam
    waqaslam about 12 years
    Either reverse your ArrayList and call notifyDataSetChanged() on your adapter, or set setStackFromBottom(true) to your listview before setting adapter.
  • Aalok Sharma
    Aalok Sharma about 12 years
    How do I reverse the array list? I've tried the setStackFromBottom(true),but it simply scrolls down to the last item
  • waqaslam
    waqaslam about 12 years
    Then just reverse the items in your ArrayList and call notifyDataSetChanged() on adapter.
  • Aalok Sharma
    Aalok Sharma about 12 years
    No I meant that without using the stackfrom bottom,what code must I write to reverse the array ??
  • waqaslam
    waqaslam about 12 years
    yes, i'm not either talking about stackfrom bottom. Read this
  • Hugh Jeffner
    Hugh Jeffner about 8 years
    Came to the same conclusion after finding this: stackoverflow.com/a/14719538/383761
  • Harsha
    Harsha over 7 years
    after notifydatasetchanged new page loaded and display view from page one please help every new page loaded and moves to top
  • Sebastian Breit
    Sebastian Breit over 7 years
    You are not using it right. If it moves to top, you are re-inserting all items into the list
  • Vikrant
    Vikrant over 7 years
    @SebastianBreit Im new to this , but can you explain how to use myAdapter.updateData(myNewdata); ? What should be passed in myNewdata ? Elaborate please ?
  • Sebastian Breit
    Sebastian Breit over 7 years
    @Vikrant, normally that would be any kind of list of objects. (array/arraylist/vector). Inside of your adapter, you would have a reference to that list for showing it in your view. I strongly recommend you take a look at any android adapter tutorial
  • fida1989
    fida1989 almost 7 years
    @lenooh: Me too!
  • Sabri Meviş
    Sabri Meviş about 6 years
    Excellent! My list doesn't move anymore. It stays where its on remove and insert.
  • Buntu Linux
    Buntu Linux almost 6 years
    best answer, saved my day
  • Sakiboy
    Sakiboy almost 5 years
    This actually addresses the problem. Thank you! Works great.