13

I have a problem with my recyclerViev, specifically with the scrolling. I have some list, which is updated in real time, some item is added, some removed, and everything is sorted by some parameter. So the item which was initially first on the list, can have its parameter changed, which will be in different position after the sorting.

So my recyclerView is for example focusing on the initial item, and after change, when some item has "better" parameter is changing position with that initial item.

Problem is, i want to focus on the new item, with "better" parameter when I'm not scrolling, but i don't want to focusing on it when i scroll by touch(so my touch will not be interrupted by scrolling to current first item on the list).

So i don't want to force this code after every change in my recyclerView data:

recyclerView.scrollToPosition(0);

because as i said, i will be interrupted by this scroll when i am touching my recyclerView list and go down to see other items and in the same time there will be a change in my list.

Is there a way to accomplish this?

To be specific, i am using DiffCallback from the DiffUtil, to support animations when there is a change in my current recyclerView list - it compares the old list with another new list and apply all the wanted animations and notifications(item added, removed, changed position). So i never call

notifyDataSetChanged

or anything like that

Here is my DiffUtil callback:

  public static class DevicesDiffCallback extends DiffUtil.Callback{

    List<DeviceInfo> oldDevices;
    List<DeviceInfo> newDevices;

    public DevicesDiffCallback(List<NexoDeviceInfo> newDevices, List<NexoDeviceInfo> oldDevices) {
        this.newDevices = newDevices;
        this.oldDevices = oldDevices;
    }

    @Override
    public int getOldListSize() {
        return oldDevices != null ? oldDevices.size() : 0;
    }

    @Override
    public int getNewListSize() {
        return newDevices != null ?  newDevices.size() : 0;
    }

    @Override
    public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
        return oldDevices.get(oldItemPosition).getNexoIdentifier().getSerialNumber().equals(newDevices.get(newItemPosition).getNexoIdentifier().getSerialNumber());
    }

    @Override
    public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
        return oldDevices.get(oldItemPosition).equals(newDevices.get(newItemPosition));
    }

    @Override
    public Object getChangePayload(int oldItemPosition, int newItemPosition) {
        return super.getChangePayload(oldItemPosition, newItemPosition);
    }
}

And i set it like this in my adapter, when i get the list of new data to be populated and replace the old data:

 public void setData(List<DeviceInfo> data) {
    DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DevicesDiffCallback(this.mData, data), false);
    diffResult.dispatchUpdatesTo(this);

        mData = data;

}
K.Os
  • 5,123
  • 8
  • 40
  • 95
  • 1
    So you want to scroll to the top of the list when new data comes, but not when the user is manually scrolling? Can you show the code that scrolls to new item that is not working properly? – elmorabea Dec 04 '17 at 12:56
  • I updated my question. I actually do nothing with manually scrolling. It scrolls automatically to bottom, when there is a different order in my new list Callback, and the item, that initialy was first goes "off screen" to the bottom, and the recyclerView scrolls to that posisition also. I don't want to scroll to the bottom, but just focus on the current or new first position in the list, but not scroll to the top when user is scrolling down. – K.Os Dec 04 '17 at 13:01
  • Check out [that answer](https://stackoverflow.com/questions/43458146/diffutil-in-recycleview-making-it-autoscroll-if-a-new-item-is-added), maybe it helps. – elmorabea Dec 04 '17 at 13:09
  • I don't want to auto scroll to the top when user is scrolling – K.Os Dec 04 '17 at 13:14
  • Where do you want to scroll to then? :D – elmorabea Dec 04 '17 at 13:15
  • Did you read my question? I want to disable auto scrolling. It should stay in the same position always. However, currently when i am at the top of the list and there is a new item at the top i need to manually scroll up to see the new item, so i also want to prevent this. In this scenario it should stay focus in the new first item. When i am scrolling by hand there should be no auto scroll. – K.Os Dec 04 '17 at 13:19
  • @elmorabea here is what i am looking for to be more specific https://issuetracker.google.com/issues/70149059 – K.Os Dec 04 '17 at 13:22
  • Well, your definition of "same place" is inconsistent with no scrolling. If i see the 3rd item in a list, and 5 new items are added on top of this item, then seeing the "same place" would mean seeing 8th item. So in some cases, same place actually means auto scroll. And you say you want to scroll to "the new first item" which i think that's what the answer I linked to you does. – elmorabea Dec 04 '17 at 13:24
  • Yes, but as the person commented to that answer, it will always scrolls to the new position. I want to avoid that when user is scrolling down to see other items – K.Os Dec 04 '17 at 13:26
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/160429/discussion-between-elmorabea-and-okset). – elmorabea Dec 04 '17 at 13:29

1 Answers1

2

I'm not sure about this answer but, I think your code to call DiffUtil is not proper. Try using this :

public void addItems(List<Recipe> recipeList) {

    List<Recipe> newRecipeList = new ArrayList<>();
    newRecipeList.addAll(this.recipeList);
    newRecipeList.addAll(recipeList);

    DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new RecipeDiffUtilCallback(this.recipeList, newRecipeList));
    this.recipeList.addAll(recipeList);
    diffResult.dispatchUpdatesTo(this);
}
tir38
  • 9,810
  • 10
  • 64
  • 107
Vicky
  • 1,807
  • 5
  • 23
  • 34