web-dev-qa-db-fra.com

comment maintenir la position de défilement de la liste lors de sa mise à jour

J'ai lu de nombreux exemples, mais si je souhaite conserver ma position de défilement après la mise à jour de ListView à partir de JSON, puis-je le faire sans utiliser une instance AsyncTask? ??

le code de ma liste est

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

et mon adaptateur est

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

et enfin la classe utilisée pour l'analyse json est

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



}

avec cela, si les données sont mises à jour à partir de la page Web, quel serait le moyen le plus simple d'afficher l'élément mis à jour en haut?

22
Aalok Sharma

Il est plus facile de maintenir la position de défilement en appelant notifydatasetchanged () uniquement. Le problème, c'est que vous créez un nouvel adaptateur chaque fois que les données sont mises à jour ... vous devriez faire quelque chose comme ceci:

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

De cette façon, votre listview conservera la position de défilement.

Si vous souhaitez faire défiler jusqu'à une nouvelle position, utilisez:

list.smoothScrollToPosition(int position);
27
Sebastian Breit

Si, pour une raison quelconque, vous ne souhaitez pas appeler notifyDataSetChanged (), vous pouvez maintenir la position en utilisant setSelectionFromTop ()

Avant de mettre à jour l'adaptateur:

lastViewedPosition = listView.getFirstVisiblePosition();

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

Après la mise à jour de l'adaptateur:

listView.setSelectionFromTop(lastViewedPosition, topOffset);
7
Sudhasri
list.smoothScrollToPosition(int position);     //my favorite :)

Cela peut également vous aider à faire défiler Nice'n'smooth jusqu'à un élément particulier

6
waqaslam
listview.setSelection( i );

cela vous aidera à définir une ligne particulière en haut

5
MAC

Si vous utilisez un ArrayAdapter (ou une sous-classe de celui-ci), le problème peut être dû au fait que l'adaptateur met à jour la liste lorsque vous la nettoyez avant d'ajouter les nouveaux éléments:

adapter.clear();
adapter.addAll(...);

Vous pouvez le résoudre en enveloppant le code qui modifie l'adaptateur comme ceci:

adapter.setNotifyOnChange(false); // Disable calling notifyDatasetChanged() on modification
adapter.clear();
adapter.addAll(...); // Notify the adapter about that data has changed. Note: it will re-enable notifyOnChange
adapter.notifyDataSetChanged();
2
Aron Lorincz

Pour une vue d'ensemble:

Dans votre rappel de réponse API, appelez cette fonction (exemple) ci-dessous:

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();
}
2
felixwcf