0

Я в настоящее время использую scrollListener, чтобы включить бесконечный свиток - вы можете найти мой вопрос и ответ Вилена здесь:Бесконечные прокрутки RecyclerView с разнородными размерами массива из API

Adding items to Endless Scroll RecyclerView with ProgressBar at bottom

Это творит чуда, когда у вас есть одинаковый размер каждый раз, когда вы активируете свой адаптер при прокрутке. Например, в коде Вилена он увеличивает размер набора данных на одинаковое количество, 15, каждый раз, когда он прокручивает.

Однако в реальном мире это часто бывает не так. У вас есть различный размер. В моем примере я хотел бы сделать следующее:

Я хотел бы реализовать геопространственный поиск, чтобы он вернул список ближайших ко мне мест. Теперь, если я буду сидеть в пустыне, мой вызов REST API вернет места в пределах 10 км от меня, и это может быть только 4 места (хижина верблюда, пирамиды, водопой и кокосовое дерево).

Нанесение 4 элементов в recyclerview не сделает recyclerview достаточно длинным, чтобы позволить ему прокручивать дальше, чтобы мое приложение снова вызывало вызов API, чтобы найти больше мест ближе ко мне. Следующие 10 км (20 км от моего нынешнего местоположения) могут быть городом с большим количеством мест, чтобы вернуться, но поскольку пересмотр занимает недостаточно времени для прокрутки, вызов API не производится.

Я также сделал крошечный репо, чтобы продемонстрировать, что слушатель прокрутки не срабатывают, когда recyclerview слишком короток:

https://github.com/Winghin2517/DissimilarDataSetSizeRV.git

Как я могу обойти эту проблему?

Я почти чувствую, что scrolllistener должен запускаться до тех пор, пока recyclerview не заполнит экран, но как я могу определить, когда экран будет заполнен, так как нет обратного вызова для recyclerview-fill-up-screen, насколько я знать.

Я пытался остановить изменения boolean loading видеть, что помогло бы, но без логического значения проверки состояния нагрузки, ProgressBar не обязательно будут удалены ведущие к этому типу эффекта:

enter image description here

ответ

0

Благодаря этой теме мне удалось определить, достаточно ли переучивания для прокрутки: How to know if a RecyclerView has enough content to scroll?

Я тогда немного сыграл с кодом и, похоже, работает таким образом.

создать две новые переменные:

final static String PROGRESS_BAR = "progressBar"; //this will be the unique object that will be added to the arraylist when you want to display the progress bar 
boolean progressBarAdded; //the progressbar must only be added once so this will keep track of it when it is added. 

    //adapter code is changed to take into account when the recyclerview can/cannot scroll 
    mAdapter.setOnLoadMoreListener(new MyAdapter.OnLoadMoreListener() { 
     @Override 
     public void onLoadMore() { 
      //add progress item 
      //we can scroll and progress bar is not yet added 
      if (!progressBarAdded && llm.findLastCompletelyVisibleItemPosition() != mAdapter.getItemCount() - 1) { 
       progressBarAdded = true; 
       myDataset.add(PROGRESS_BAR); 
       mAdapter.notifyItemInserted(myDataset.size() - 1); 
      } 

      Handler handler = new Handler(); 
      handler.postDelayed(new Runnable() { 
       @Override 
       public void run() { 
        //remove progress item 
        boolean removed = myDataset.remove(PROGRESS_BAR); 
        if (removed) { 
         mAdapter.notifyItemRemoved(myDataset.size()); 
         progressBarAdded = false; //progress bar is now removed 
        } 
        //add items one by one 
        for (int i = 0; i < 3; i++) { 
         myDataset.add("Item" + (myDataset.size() + 1)); 
         mAdapter.notifyItemInserted(myDataset.size()); 
        } 
       //we can scroll 
       if(llm.findLastCompletelyVisibleItemPosition()!=mAdapter.getItemCount()-1) { 
        mAdapter.setLoaded(); 
       } 
      } 
     }, 500); 

Я тогда изменить scrolllistener так:

if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) { 

     final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); 
     recyclerView.setOnScrollListener(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 (totalItemCount <= (lastVisibleItem + visibleThreshold)) { 
        // End has been reached 
        // Do something 
        if (onLoadMoreListener != null) { 
         onLoadMoreListener.onLoadMore(); 
        } 
        if (linearLayoutManager.findLastCompletelyVisibleItemPosition() != MyAdapter.this.getItemCount() - 1) { //determines whether the recyclerview is full or not. If not full, this will cause it to continue to load 
         loading = true; 
        } 
       } 
      } 
     }); 
    } 

Также убедитесь, что вы принимаете во внимание новую GetItemType, как каждый раз, когда он обнаруживает строку " progressBar ", он должен загрузить наблюдателя для progressBar:

@Override 
public int getItemViewType(int position) { 
    return mDataset.get(position) != MainActivity.PROGRESS_BAR ? VIEW_ITEM : VIEW_PROG; 
} 
+0

Итак, вы решили проблему или вам все еще нужна помощь? –

+0

решена. Не могу поверить, что мне удалось это быстро решить. Потребовалось меньше времени, чем я думал, что это займет. Я не могу отметить свой ответ как правильный, но я сделаю это через 2 часа в соответствии с правилами SO. – Simon

+0

Ну, если у вас есть лучший способ сделать это, вы можете опубликовать свое решение. Я чувствую, что мой путь немного взломан, но, похоже, он работает. – Simon

0

Вы можете попробовать t его подход (код ниже от одного из моих приложений, так что вы должны будете заполнить пробелы, я просто добавил те части, которые должны решить вашу проблему)>

public class MainActivity extends AppCompatActivity implements AbsListView.OnScrollListener 
// Or use yourListView.setOnScrollListener(this); 
{ 

    int preLast = -1; 

    @Override 
    public void onScroll(AbsListView lw, final int aFirstVisibleItemIndex, final int aVisibleItemCount, final int aTotalItemsCount) { 
     int id = mListView.getId(); // Or use case android.R.id.list:  

     if(lw.getId() == id) { 
        // Sample calculation to determine if the last item is fully visible. 
      final int lastItem = aFirstVisibleItemIndex + aVisibleItemCount; 
      if(lastItem > 0 && lastItem == aTotalItemsCount) // lastItem > 0 helps to avoid continuous call if the list is empty. 
      { 
       if(preLast != lastItem) { //to avoid multiple calls for last item 
        preLast = lastItem; 

       } 
       } 
     } 
     } 
} 

@Override //it will be called before any calls to Adapter.getView(.....) 
public void onScrollStateChanged(AbsListView view, int scrollState) { 

} 

А теперь и всякий раз, когда вы решили, что есть нет больше данных для извлечения из вашего ранга (чтобы заполнить больше элементов в вашем списке), и вы хотите, чтобы listview не вызывал/активировал ваш (при загрузке анимации), вы можете просто установить значение preLast для значения lastItem.

+0

Я ищу recyclerview, а не listview. – Simon

Смежные вопросы