Saltar al contenido

Cómo implementar setOnScrollListener en RecyclerView

Solución:

Clase de actividad con recylcerview en archivo de diseño xml

public class WallpaperActivity extends AppCompatActivity implements OnTaskCompleted 


private static final String TAG = "WallpaperActivity";


private Toolbar toolbar;


private RecyclerView mRecyclerView;
private WallPaperDataAdapter mAdapter;
private LinearLayoutManager mLayoutManager;
// to keep track which pages loaded and next pages to load
public static int pageNumber;

private List wallpaperImagesList;


protected Handler handler;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.wallpaper_main);
    toolbar = (Toolbar) findViewById(R.id.toolbar);
    mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
    pageNumber = 1;
    wallpaperImagesList = new ArrayList();
    handler = new Handler();
    if (toolbar != null) 
        setSupportActionBar(toolbar);
        getSupportActionBar().setTitle("WallPapers");

    


    // use this setting to improve performance if you know that changes
    // in content do not change the layout size of the RecyclerView
    mRecyclerView.setHasFixedSize(true);


    mLayoutManager = new LinearLayoutManager(this);


    // use a linear layout manager
    mRecyclerView.setLayoutManager(mLayoutManager);


    // create an Object for Adapter
    mAdapter = new WallPaperDataAdapter(wallpaperImagesList, mRecyclerView);

    // set the adapter object to the Recyclerview
    mRecyclerView.setAdapter(mAdapter);


    getWebServiceData();


    mAdapter.setOnLoadMoreListener(new OnLoadMoreListener() 
        @Override
        public void onLoadMore() 
            //add null , so the adapter will check view_type and show progress bar at bottom
            wallpaperImagesList.add(null);
            mAdapter.notifyItemInserted(wallpaperImagesList.size() - 1);
            ++pageNumber;


            getWebServiceData();


        
    );





public void getWebServiceData() 

    BackGroundTask backGroundTask = new BackGroundTask(this, this, pageNumber);
    backGroundTask.execute();




@Override
public void onTaskCompleted(String response) 


    parsejosnData(response);




public void parsejosnData(String response) 

    try 

        JSONObject jsonObject = new JSONObject(response);

        //    String json = jsonObject.toString();

        JSONArray jsonArray = jsonObject.getJSONArray("wallpapers");


        if (jsonArray != null) 
            // looping through All albums


            if (pageNumber > 1) 
                wallpaperImagesList.remove(wallpaperImagesList.size() - 1);
                mAdapter.notifyItemRemoved(wallpaperImagesList.size());
            

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

                // Storing each json item values in variable
                String id = c.getString("id");
                String orig_url = c.getString("orig_url");
                String thumb_url = c.getString("thumb_url");
                String downloads = c.getString("downloads");
                String fav = c.getString("fav");

                // Creating object for each product
                WallPaper singleWall = new WallPaper(id, orig_url, thumb_url, downloads, fav);

                // adding HashList to ArrayList
                wallpaperImagesList.add(singleWall);


                handler.post(new Runnable() 
                    @Override
                    public void run() 
                       mAdapter.notifyItemInserted(wallpaperImagesList.size());


                    
                );


            


            mAdapter.setLoaded();


         else 
            Log.d("Wallpapers: ", "null");
        

     catch (JSONException e) 
        e.printStackTrace();
    





Clase de adaptador

public class WallPaperDataAdapter extends RecyclerView.Adapter 
    private final int VIEW_ITEM = 1;
    private final int VIEW_PROG = 0;

    private List imagesList;

    // The minimum amount of items to have below your current scroll position
    // before loading more.
    private int visibleThreshold = 5;
    private int lastVisibleItem, totalItemCount;
    private boolean loading;
    private OnLoadMoreListener onLoadMoreListener;


    public WallPaperDataAdapter(List imagesList1, RecyclerView recyclerView) 
        imagesList = imagesList1;

        if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) 

            final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView
                    .getLayoutManager();


            recyclerView
                    .addOnScrollListener(new RecyclerView.OnScrollListener() 
                        @Override
                        public void onScrolled(RecyclerView recyclerView,
                                               int dx, int dy) 
                            super.onScrolled(recyclerView, dx, dy);

                            totalItemCount = linearLayoutManager.getItemCount();
                            lastVisibleItem = linearLayoutManager
                                    .findLastVisibleItemPosition();
                            if (!loading
                                    && totalItemCount <= (lastVisibleItem + visibleThreshold)) 
                                // End has been reached
                                // Do something
                                if (onLoadMoreListener != null) 
                                    onLoadMoreListener.onLoadMore();
                                
                                loading = true;
                            
                        
                    );
        
    

    @Override
    public int getItemViewType(int position) 
        return imagesList.get(position) != null ? VIEW_ITEM : VIEW_PROG;
    

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                      int viewType) 
        RecyclerView.ViewHolder vh;
        if (viewType == VIEW_ITEM) 
            View v = LayoutInflater.from(parent.getContext()).inflate(
                    R.layout.wallpaper_row, parent, false);

            vh = new WallPaperViewHolder(v);
         else 
            View v = LayoutInflater.from(parent.getContext()).inflate(
                    R.layout.progress_item, parent, false);

            vh = new ProgressViewHolder(v);
        
        return vh;
    

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) 
        if (holder instanceof WallPaperViewHolder) 

            WallPaper singleWallPaper = (WallPaper) imagesList.get(position);


            Glide.with(((WallPaperViewHolder) holder).thumbIcon.getContext())
                    .load(singleWallPaper.getThumbUrl())
                    .centerCrop()
                    .placeholder(R.drawable.bg)
                    .crossFade()
                    .into(((WallPaperViewHolder) holder).thumbIcon);


         else 
            ((ProgressViewHolder) holder).progressBar.setIndeterminate(true);
        
    

    public void setLoaded() 
        loading = false;
    

    @Override
    public int getItemCount() 
        return imagesList.size();
    

    public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) 
        this.onLoadMoreListener = onLoadMoreListener;
    


    //
    public static class WallPaperViewHolder extends RecyclerView.ViewHolder 


        public ImageView thumbIcon;


        public WallPaperViewHolder(View v) 
            super(v);


            thumbIcon = (ImageView) v.findViewById(R.id.thumbIcon);


        
    

    public static class ProgressViewHolder extends RecyclerView.ViewHolder 
        public ProgressBar progressBar;

        public ProgressViewHolder(View v) 
            super(v);
            progressBar = (ProgressBar) v.findViewById(R.id.progressBar1);
        
    

wallpaper_row.xml







progress_item.xml




    


BackGroundTask.java independiente

public class BackGroundTask extends AsyncTask 

    private ProgressDialog pDialog;
    public OnTaskCompleted listener = null;//Call back interface


    Context context;
    int pageNumber;

    public BackGroundTask(Context context1, OnTaskCompleted listener1, int pageNumber) 
        context = context1;
        listener = listener1;   //Assigning call back interface  through constructor
        this.pageNumber = pageNumber;
    

    @Override
    protected void onPreExecute() 
        super.onPreExecute();

    

    @Override
    protected String doInBackground(Object... params) 

        //My Background tasks are written here

        synchronized (this) 

            String url = Const.URL_WALLPAPERS_HD + pageNumber;
            String jsonStr = ServiceHandler.makeServiceCall(url, ServiceHandler.GET);
            Log.i("Url: ", "> " + url);

            Log.i("Response: ", "> " + jsonStr);
            return jsonStr;
        

    

    @Override
    protected void onPostExecute(String result) 
        super.onPostExecute(result);
        listener.onTaskCompleted(result);

    


ServiceHanlder.java

public class ServiceHandler 

    static String response = null;
    public final static int GET = 1;
    public final static int POST = 2;


    public ServiceHandler() 

    

    /**
     * Making service call
     *
     * @url - url to make request
     * @method - http request method
     */
    public static String makeServiceCall(String url, int method) 
        return makeServiceCall(url, method, null);
    

    /**
     * Making service call
     *
     * @url - url to make request
     * @method - http request method
     * @params - http request params
     */
    public static String makeServiceCall(String url, int method,
                                  List params) 
        try 
            // http client
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpEntity httpEntity = null;
            HttpResponse httpResponse = null;

            // Checking http request method type
            if (method == POST) 
                HttpPost httpPost = new HttpPost(url);
                // adding post params
                if (params != null) 
                    httpPost.setEntity(new UrlEncodedFormEntity(params));
                
                Log.e("Selltis Request URL", url);
                httpResponse = httpClient.execute(httpPost);

             else if (method == GET) 
                // appending params to url
                if (params != null) 
                    String paramString = URLEncodedUtils
                            .format(params, "utf-8");
                    url += paramString;

                    Log.i("Request URL", url);
                
                HttpGet httpGet = new HttpGet(url);

                httpResponse = httpClient.execute(httpGet);

            
            httpEntity = httpResponse.getEntity();
            response = EntityUtils.toString(httpEntity);

         catch (UnsupportedEncodingException e) 
            e.printStackTrace();
            return "Fail";
         catch (ClientProtocolException e) 
            e.printStackTrace();
            return "Fail";
         catch (IOException e) 
            e.printStackTrace();
            return "Fail";
        

        return response;

    



Interfaz para cargar más

public interface OnLoadMoreListener 
     void onLoadMore();

Interfaz para conocer los datos del servicio web cargados desde asynctask

public interface OnTaskCompleted

    void onTaskCompleted(String response);

Por favor, avíseme si esto funciona o si tiene algún problema. Es mejor usar las bibliotecas Volley u okHttp para redes.

Para ImageLoading utilicé Glide Library.

Así es como detecto si RecyclerView debería actualizar por OnScrollListener, mira esto:

recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() 
    int ydy = 0;
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) 
        super.onScrollStateChanged(recyclerView, newState);

    

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) 
        super.onScrolled(recyclerView, dx, dy);
        int offset = dy - ydy;
        ydy = dy;
        boolean shouldRefresh = (linearLayoutManager.findFirstCompletelyVisibleItemPosition() == 0)
                && (recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) && offset > 30;
        if (shouldRefresh) 
            //swipeRefreshLayout.setRefreshing(true);
            //Refresh to load data here.
            return;
        
        boolean shouldPullUpRefresh = linearLayoutManager.findLastCompletelyVisibleItemPosition() == linearLayoutManager.getChildCount() - 1
                && recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING && offset < -30;
        if (shouldPullUpRefresh) 
            //swipeRefreshLayout.setRefreshing(true);
            //refresh to load data here.
            return;
        
        swipeRefreshLayout.setRefreshing(false);
    
);

Espero que se sienta inspirado. Buena suerte ~

Otro ejemplo. Configure su barra de progreso en la parte inferior y cambie su visibilidad de acuerdo con el desplazamiento / carga y sus registros. Nota: debe llamar a notifyDataSetChanged (); método para agregar / actualizar datos al adaptador

  recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() 
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) 
                super.onScrolled(recyclerView, dx, dy);

                int total = linearLayoutManager.getItemCount();
                int firstVisibleItemCount = linearLayoutManager.findFirstVisibleItemPosition();
                int lastVisibleItemCount = linearLayoutManager.findLastVisibleItemPosition();

                //to avoid multiple calls to loadMore() method
                //maintain a boolean value (isLoading). if loadMore() task started set to true and completes set to false
                if (!isLoading)  
                    if (total > 0) 
                        if ((total - 1) == lastVisibleItemCount)
                           loadMore();//your HTTP stuff goes in this method 
                           loadingProgress.setVisibility(View.VISIBLE);
                        else
                           loadingProgress.setVisibility(View.GONE);
                
            

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) 
                super.onScrollStateChanged(recyclerView, newState);

            

    );

Puntuaciones y comentarios

Más adelante puedes encontrar las ilustraciones de otros programadores, tú aún eres capaz mostrar el tuyo si te gusta.

¡Haz clic para puntuar esta entrada!
(Votos: 2 Promedio: 3)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *