简体   繁体   中英

Android Listview Scroll position

I have a ListView and a list view adapter. The adapter populates the ListView from a List . The list view has a onScrollListener . The problem I have is when on scroll new data are loaded to the view but the scroll bar jumps to the top of the view.

What I want is to keep the scroll position where it was!

Any help? Thanks

List View class:

private class GetItems extends AsyncTask<Void, Void, Void>
{
    @Override
    protected void onPreExecute() {
        super.onPreExecute();

        // Create a progressdialog
        mProgressDialog = new ProgressDialog(AppList.this);
        // Set progressdialog title
        mProgressDialog.setTitle("Loading more");
        mProgressDialog.setMessage("loading);
        mProgressDialog.setIndeterminate(false);
        // Show progressdialog
        mProgressDialog.show();
    }

    @Override
    protected Void doInBackground(Void... params)
    {
        applicationList = new ArrayList();

         try
        {
            GetDataAppList getDataAppList = new GetDataAppList();
            JSONArray jsonData = getDataAppList.getJSONData(webfileName, limit, offset);

            for (int i = 0; i <= jsonData.length() - 2; i++)
            {
                JSONObject c = jsonData.getJSONObject(i);

                id = c.getString("id");
                name = c.getString("name");
                logo = c.getString("logo");
                developer = c.getString("developer");
                rate = c.getInt("rates");
                category = c.getInt("category");
                fileName = c.getString("filename");
                path = c.getString("path");
                appSize = c.getDouble("size");

                if(category == 1001)
                {
                    String gCat = c.getString("game_category");
                    applicationList.add(new ApplicationPojo(id,name,logo,developer,appSize,category,fileName,path,gCat));
                }
                else
                {
                    applicationList.add(new ApplicationPojo(id,name,logo,developer,appSize,category,fileName,path));

                }
            }
            JSONObject sizeObj = jsonData.getJSONObject(jsonData.length() - 1);
            size = sizeObj.getInt("size");


        }
        catch (Exception ex)
        {
            Log.d("Thread:", ex.toString());
        }

        return null;
    }

    @Override
    protected void onPostExecute(Void result)
    {
        // Locate the ListView in listview.xml
        listview = (ListView) findViewById(R.id.listView);
        // Pass the results into ListViewAdapter.java
        adapter = new ListViewAdapter(AppList.this, applicationList,listview);
        // Binds the Adapter to the ListView
        listview.setAdapter(adapter);
        // Close the progressdialog
        mProgressDialog.dismiss();
        // Create an OnScrollListener

        listview.setOnScrollListener(new OnScrollListener() {

            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                int threshold = 1;
                int count = listview.getCount();

                if (scrollState == SCROLL_STATE_IDLE) {
                    if (listview.getLastVisiblePosition() >= count - threshold) {
                        if (size >= offset)
                        {
                            new LoadMoreDataTask().execute();
                            offset = offset + 15;
                        }
                        else
                        {
                            Toast.makeText(getApplicationContext(), "ختم لست!", Toast.LENGTH_LONG).show();

                        }
                    }
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                // TODO Auto-generated method stub

            }

        });

        RatingBar bar = (RatingBar) findViewById(R.id.ratingBarShow);

    }
}

private class LoadMoreDataTask extends AsyncTask<Void, Void, Void> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mProgressDialog = new ProgressDialog(AppList.this);
        mProgressDialog.setTitle("Loading more");
        mProgressDialog.setMessage("loading);
        mProgressDialog.setIndeterminate(false);
        mProgressDialog.show();
    }

    @Override
    protected Void doInBackground(Void... params)
    {
        try
        {
            GetDataAppList getDataAppList = new GetDataAppList();

            JSONArray jsonData = getDataAppList.getJSONData(webfileName, limit, offset);

            for (int i = 0; i <= jsonData.length(); i++) {
                JSONObject c = jsonData.getJSONObject(i);

                id = c.getString("id");
                name = c.getString("name");
                logo = c.getString("logo");
                developer = c.getString("developer");
                rate = c.getInt("rates");
                category = c.getInt("category");
                fileName = c.getString("filename");
                path = c.getString("path");
                appSize = c.getDouble("size");

                if(category == 1001)
                {
                    String gCat = c.getString("game_category");
                    applicationList.add(new ApplicationPojo(id,name,logo,developer,appSize,category,fileName,path,gCat));
                }
                else
                {
                    applicationList.add(new ApplicationPojo(id,name,logo,developer,appSize,category,fileName,path));

                }

            }
        }
        catch (Exception ex)
        {

        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result)
    {

        int position = listview.getLastVisiblePosition();

        adapter = new ListViewAdapter(AppList.this, applicationList,listview);


        listview.setAdapter(adapter);

        listview.setSelectionFromTop(position, 0);

        mProgressDialog.dismiss();
    }
}

The Adpater class:

    public ListViewAdapter(Activity activity, ArrayList<ApplicationPojo> applicationList, ListView listView)
    {
        this.activity = activity;
        this.applicationList = applicationList;
        this.inflater = LayoutInflater.from(activity);
        downloader = new ApkFileDownloader(activity);
        this.listView = listView;
    }

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

    @Override
    public ApplicationPojo getItem(int position) {
        return applicationList.get(position);
    }

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

    public View getView(final int position, View view, ViewGroup parent)
    {
        if (view == null)
        {
            holder = new ViewHolder();
            view = inflater.inflate(R.layout.singleapp, null);

            holder.openInstalledAppBtn = (ImageView) view.findViewById(R.id.openInstalledApp);
            holder.downloadBtn = (ImageView) view.findViewById(R.id.updateApp);
            holder.progressBar = (ProgressBar)view.findViewById(R.id.updateProgress);
            holder.cancelBtn = (ImageView) view.findViewById(R.id.cancel);
            holder.appName = (TextView) view.findViewById(R.id.appName);
            holder.developer = (TextView) view.findViewById(R.id.developer);
            holder.size = (TextView) view.findViewById(R.id.size);
            holder.appCat = (TextView) view.findViewById((R.id.appCat));
            holder.installBtn = (ImageView) view.findViewById(R.id.install);
            holder.catlogo = (ImageView) view.findViewById(R.id.catlogo);


            view.setTag(holder);
        }
        else
        {
            holder = (ViewHolder) view.getTag();
        }

        try
        {
            final View finalView = view;

            holder.logo = (ImageView) finalView.findViewById(R.id.appLogo);
            logoName = applicationList.get(position).getLogo();

            Picasso.with(activity)
                    .load(IPClass.SERVERIP + logoName)
                    .into(holder.logo);

//            holder.logo.setOnClickListener(new View.OnClickListener() {
//                @Override
//                public void onClick(View arg0) {
//
//                }
//            });

            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                    String appid = applicationList.get(position).getId();
                    int category = applicationList.get(position).getCategory();

                    Intent rec1Intent = new Intent(activity, AppView.class);
                    activity.startActivity(rec1Intent);

                    AppView appView = new AppView();
                    appView.setParameters(appid, category);

                    AppList.adapter.notifyDataSetChanged();
                }
            });

            final String id = applicationList.get(position).getId();
            final String path = applicationList.get(position).getPath();
            final String fileName = applicationList.get(position).getFileName();
            final String name = applicationList.get(position).getName();
            final String developer = applicationList.get(position).getDeveloper();
            final double size = applicationList.get(position).getSize();
            final String logo = applicationList.get(position).getLogo();
            final int category = applicationList.get(position).getCategory();

            final String appName = applicationList.get(position).getFileName();
            String checkAppInstalled = appName.substring(0,appName.length() - 4);

            //------------CHECK IF APPLICATION IS INSTALLED ----------------------------------------

            if(appInstalled(checkAppInstalled))
            {
                holder.downloadBtn.setVisibility(View.GONE);
                holder.cancelBtn.setVisibility(View.GONE);
                holder.progressBar.setVisibility(View.GONE);
                holder.installBtn.setVisibility(View.GONE);

                holder.openInstalledAppBtn.setVisibility(View.VISIBLE);
                holder.openInstalledAppBtn.setOnClickListener(new View.OnClickListener()
                {
                    @Override
                    public void onClick(View v) {

                        String fileName = (applicationList.get(position).getFileName());
                        String appToOpen = fileName.substring(0,fileName.length() - 4);

                        Context ctx = activity.getApplicationContext();
                        Intent mIntent = ctx.getPackageManager().getLaunchIntentForPackage(appToOpen);
                        String mainActivity = mIntent.getComponent().getClassName();

                        Intent intent = new Intent("android.intent.category.LAUNCHER");
                        intent.setClassName(appToOpen, mainActivity);
                        activity.startActivity(intent);
                    }
                });
            }

            //------------- IF APPLICATION IS NOT ALREADY INSTALLED --------------------------------

            else
            {
                //------------------------ CHECK IF APK EXISTS -------------------------------------

                String filePath = Environment.getExternalStorageDirectory().toString();
                File file = new File(filePath + "/appsaraai/" + fileName);

                if(file.exists())
                {
                    holder.downloadBtn.setVisibility(View.GONE);
                    holder.cancelBtn.setVisibility(View.GONE);
                    holder.openInstalledAppBtn.setVisibility(View.GONE);
                    holder.progressBar.setVisibility(View.GONE);

                    holder.installBtn.setVisibility(View.VISIBLE);
                    holder.installBtn.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Intent intent = new Intent(Intent.ACTION_VIEW);
                            intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/appsaraai/" + fileName)), "application/vnd.android.package-archive");
                            activity.startActivity(intent);

                            for (int i = 0; i < DownloadLists.list.size(); i++) {

                                if (DownloadLists.list.get(i).getName().equals(name)) {
                                    DownloadLists.list.remove(i);
                                }
                            }
                        }
                    });

                    AppList.adapter.notifyDataSetChanged();
                }

                //------------------ IF APK DOES NOT EXIST -----------------------------------------
                else
                {
                    //-----CHECK IF DOWNLOAD IS IN PROGRESS ----------------------------------------

                    if (ApkFileDownloader.applicationList.containsKey(name))
                    {
                        holder.downloadBtn.setVisibility(View.GONE);
                        holder.installBtn.setVisibility(View.GONE);
                        holder.openInstalledAppBtn.setVisibility(View.GONE);

                        new ApkFileDownloader(activity).getDownloadStatus(holder.progressBar, name, holder.installBtn, holder.cancelBtn);

                        holder.progressBar.setVisibility(View.VISIBLE);
                        holder.cancelBtn.setVisibility(View.VISIBLE);

                        holder.cancelBtn.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                downloader.cancelDownload(name);
                                holder.cancelBtn.setVisibility(View.GONE);
                                holder.downloadBtn.setVisibility(View.VISIBLE);
                                DownloadLists dlist = new DownloadLists(activity);
                                dlist.deleteData(name);

                                try {
                                    AppList.adapter.notifyDataSetChanged();
                                } catch (Exception ex) {
                                    System.out.println(ex);

                                }

                                try
                                {
                                    SearchResult.adapter.notifyDataSetChanged();
                                }
                                catch (Exception ex)
                                {
                                    System.out.println(ex);
                                }
                            }
                        });
                    }

                    //-------------- IF DOWNLOAD IS NOT IN PROGRESS START NEW DOWNLOAD -------------
                    else
                    {
                        holder.progressBar.setVisibility(View.GONE);
                        holder.cancelBtn.setVisibility(View.GONE);
                        holder.installBtn.setVisibility(View.GONE);
                        holder.openInstalledAppBtn.setVisibility(View.GONE);

                        holder.downloadBtn.setVisibility(view.VISIBLE);
                        holder.downloadBtn.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View arg0) {

                                holder.downloadBtn.setVisibility(View.GONE);
                                holder.cancelBtn.setVisibility(View.VISIBLE);
                                holder.cancelBtn.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        downloader.cancelDownload(name);
                                        holder.cancelBtn.setVisibility(View.GONE);
                                        holder.downloadBtn.setVisibility(View.VISIBLE);

                                        try {
                                            AppList.adapter.notifyDataSetChanged();
                                        } catch (Exception ex) {
                                            System.out.println(ex);

                                        }
                                        try {
                                            SearchResult.adapter.notifyDataSetChanged();
                                        } catch (Exception ex) {
                                            System.out.println(ex);
                                        }
                                    }
                                });

                                new Thread(new Runnable() {
                                    @Override
                                    public void run() {

                                        try {
                                            Bitmap logoImg = Picasso.with(activity).load(IPClass.SERVERIP + logo).get();
                                            DownloadLists.list.add(new ApplicationPojo(id, name, developer, size, logoImg, holder.progressBar));
                                            DownloadLists dlist = new DownloadLists(activity);
                                            dlist.insertData(id, name, developer, size, fileName, logoImg);
                                            UpdateServerDownload d = new UpdateServerDownload();
                                            d.updateDownloadNo(id, category);
                                        } catch (IOException e) {
                                            e.printStackTrace();
                                        }
                                    }
                                }).start();

                                new ApkFileDownloader(activity).setParameters(path, fileName, name);

                                try {
                                    AppList.adapter.notifyDataSetChanged();
                                } catch (Exception ex) {
                                    System.out.println(ex);
                                }

                                try {
                                    SearchResult.adapter.notifyDataSetChanged();
                                } catch (Exception ex) {
                                    System.out.println(ex);
                                }
                            }
                        });
                    }
                }
            }

            holder.appName.setText(applicationList.get(position).getName());
            holder.developer.setText(applicationList.get(position).getDeveloper());
            String sizeText = " میگابایت ";
            String appSize =String.valueOf(applicationList.get(position).getSize()) + sizeText;
            holder.size.setText(appSize);

            if(category == 1001)
            {
                String cat = applicationList.get(position).getgCat();
                holder.appCat.setText(" " + returnGameCat(cat));
                holder.catlogo.setImageResource(R.drawable.gamecatlogo);
            }



        }
        catch (Exception ex)
        {
            Log.d("Adapter Exception", ex.toString());
        }

        return view;
    }

    //--------------- A METHOD TO CHECK IF APPLICATION IS ALREADY INSTALLED ------------------------
    public boolean appInstalled(String checkApp)
    {
        pm = activity.getPackageManager();

        try
        {
            pm.getPackageInfo(checkApp, PackageManager.GET_ACTIVITIES);
            isAppInstalled = true;
        }
        catch (PackageManager.NameNotFoundException e)
        {
            isAppInstalled = false;
        }

        return isAppInstalled;
    }

You are doing wrong in your GetItems and LoadMoreDataTask AsyncTask . you are setting new adapter each time when you scroll down so when new data are loaded to the view the scroll bar jumps to the top of the view.

You need to call

adapter = new ListViewAdapter(AppList.this, applicationList,listview);
listview.setAdapter(adapter);

only first time then you have to only call

adapter.notifyDataSetChanged()

to update your ListView no need to set adapter each time when making new request and also you have to set OnScrollListener to ListView only one time currently new OnScrollListener is set each time when making new request.

您需要在适配器为null时第一次设置setAdapter或者仅在调用notifyDataSetChanged()之后第一次获取数据

Save state of listview before updating and then restore:

// save index and top position
int index = mListView.getFirstVisiblePosition();
View v = mListView.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();

// notify dataset changed or re-assign adapter here

// restore the position of listview
mListView.setSelectionFromTop(index, top);

The most Optimal Solution will be

// Save the ListView state (= includes scroll position) as a Parceble
Parcelable state = listView.onSaveInstanceState();

// e.g. set new items
listView.setAdapter(adapter);

// Restore previous state (including selected item index and scroll position)
listView.onRestoreInstanceState(state);

Reference : Retain Scroll Position Android ListView

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM