Как отслеживать выбранный элемент просмотра ресайклера?
У меня есть recyclerview с адаптером RecyclerView.Adapter. Элементы заполняются из базы данных комнат с помощью PagedList.
Я реализовал наложение режима контекстных действий на свою панель инструментов при долгом нажатии на элемент, точно так же, как это делает WhatsApp.
В держателе просмотра написано следующее OnLongClickEvent:
@Override
public boolean onLongClick(View v) {
final int previousSelected = selectedPos;
selectedPos = getAdapterPosition();
if(previousSelected!=RecyclerView.NO_POSITION){
notifyItemChanged(previousSelected); // Now deselect previously selected item
}
notifyItemChanged(selectedPos); // Select new item
longClickCallback.onLongClick(binding.getMessage(),selectedPos);
return true;
}
и selectedPos инициализируется в адаптере следующим образом:
public static int selectedPos = RecyclerView.NO_POSITION;
Событие длительного щелчка отправляет обратно для фрагментации подробные сведения о выбранных элементах в методе longClickCallback и позиции выбранных элементов.
Событие длительного щелчка также включает механизм отмены выделения / выбора. Это в основном для случая, когда элемент и выбирается с помощью длительного нажатия, а режим действия включен. Затем пользователь долго нажимает другой элемент в списке, чтобы отменить выбор более старого и выбрать вновь нажатый элемент. (В настоящее время я выбираю только отдельные элементы, я имею в виду, что одновременно можно выбрать только один элемент). Мне нужно отменить выбор элемента либо при нажатии кнопки возврата, либо при нажатии действия возврата в режиме действия, либо при длительном нажатии нового элемента.
Механизм выбора / отмены выбора работает нормально, пока положения элементов адаптера не меняются. Действительно, если элемент добавлен в конец списка, он также работает нормально. (переход к более старым сообщениям).
Однако когда новое сообщение получено и добавлено в самый верх списка, моя позиция selectedItem больше не соответствует действительности. Сдвигается вместе с количеством новых добавленных сообщений.
Я думаю, что лучшим способом было бы сохранить идентификатор элемента, поскольку он уникален для всех элементов адаптера. Однако notifyItemChanged использует позицию элемента, а не сам элемент. Кроме того, затем мне нужно выполнить поиск по всем элементам, чтобы получить выбранный элемент с помощью специального метода, который я должен написать, но в списке сообщений, который я использую, нет getItem с идентификатором элемента:
private final AsyncPagedListDiffer<MessageUIEntity> mDiffer
= new AsyncPagedListDiffer(this, DIFF_CALLBACK);
public static final DiffUtil.ItemCallback<MessageUI> DIFF_CALLBACK =
new DiffUtil.ItemCallback<MessageUI>() {
@Override
public boolean areItemsTheSame(
@NonNull MessageUI oldMessage, @NonNull MessageUI newMessage) {
// User properties may have changed if reloaded from the DB, but ID is fixed
return oldMessage.getId() == newMessage.getId();
}
@Override
public boolean areContentsTheSame(
@NonNull MessageUI oldMessage, @NonNull MessageUI newMessage) {
// NOTE: if you use equals, your object must properly override Object#equals()
// Incorrectly returning false here will result in too many animations.
boolean isContentSame = newMessage.getId() == oldMessage.getId()
&& Objects.equals(newMessage.getMessageText(), oldMessage.getMessageText())
&& Objects.equals(newMessage.getPostedAt(), oldMessage.getPostedAt())
&& Objects.equals(newMessage.getStatus(), oldMessage.getStatus())
&& Objects.equals(newMessage.getChatId(), oldMessage.getChatId())
&& Objects.equals(newMessage.getLocalUrl(), oldMessage.getLocalUrl());
return isContentSame;
}
};
Я немного застрял здесь. Позвольте мне подвести итог; Мне нужно получить конкретный элемент в моем адаптере recyclerview, но использование информации о местоположении бесполезно.