Como atualizar os dados exibidos em RecyclerView
(chamando notifyDataSetChanged
seu adaptador) e certificar-se de que a posição de rolagem seja redefinida exatamente onde estava?
No caso do bom e velho ListView
, basta recuperar getChildAt(0)
, verificar getTop()
e chamar setSelectionFromTop
com os mesmos dados exatos depois.
Não parece ser possível no caso de RecyclerView
.
Acho que devo usar seu, LayoutManager
que realmente fornece scrollToPositionWithOffset(int position, int offset)
, mas qual é a maneira correta de recuperar a posição e o deslocamento?
layoutManager.findFirstVisibleItemPosition()
e layoutManager.getChildAt(0).getTop()
?
Ou existe uma maneira mais elegante de fazer o trabalho?
android
android-recyclerview
Konrad Morawski
fonte
fonte
Respostas:
Eu uso este. ^ _ ^
É mais simples, espero que ajude você!
fonte
Eu tenho um problema bastante semelhante. E eu vim com a seguinte solução.
Usar
notifyDataSetChanged
é uma má ideia. Você deve ser mais específico, entãoRecyclerView
salvará o estado de rolagem para você.Por exemplo, se você só precisa atualizar, ou em outras palavras, deseja que cada visualização seja religada, basta fazer o seguinte:
fonte
notifyDataSetChanged
a posição de rolagem mudaria mostrando os novos itens. No entanto, se usarnotifyItemRangeInserted(0, newItems.size() - 1)
o,RecyclerView
mantém o estado de rolagem.EDITAR: Para restaurar exatamente a mesma posição aparente , como em, fazer com que pareça exatamente como estava, precisamos fazer algo um pouco diferente (veja abaixo como restaurar o valor exato de scrollY):
Salve a posição e desloque assim:
E então restaure o pergaminho assim:
Isso restaura a lista à sua posição aparente exata . Aparente porque terá a mesma aparência para o usuário, mas não terá o mesmo valor scrollY (devido a possíveis diferenças nas dimensões do layout paisagem / retrato).
Observe que isso só funciona com LinearLayoutManager.
--- Abaixo, como restaurar o scrollY exato, o que provavelmente fará a lista parecer diferente ---
Aplique um OnScrollListener assim:
Isso armazenará a posição de rolagem exata o tempo todo em mScrollY.
Armazene essa variável em seu pacote e restaure-a na restauração do estado para uma variável diferente , vamos chamá-la de mStateScrollY.
Após a restauração do estado e depois que o RecyclerView redefinir todos os seus dados, redefina a rolagem com isto:
É isso aí.
Cuidado, que você restaure a rolagem para uma variável diferente, isso é importante, porque o OnScrollListener será chamado com .scrollBy () e, subsequentemente, definirá mScrollY com o valor armazenado em mStateScrollY. Se você não fizer isso, mScrollY terá o dobro do valor de rolagem (porque OnScrollListener funciona com deltas, não com rolagens absolutas).
A economia de estado em atividades pode ser alcançada desta forma:
E para restaurar, chame isso em seu onCreate ():
O salvamento do estado em fragmentos funciona de maneira semelhante, mas o salvamento do estado real precisa de um pouco mais de trabalho, mas há muitos artigos que tratam disso, então você não deve ter problemas para descobrir como, os princípios de salvar o pergaminho. e restaurá-lo permanece o mesmo.
fonte
Sim, você pode resolver esse problema tornando o construtor do adaptador apenas uma vez. Estou explicando a parte de codificação aqui:
Agora você pode ver que verifiquei se o adaptador é nulo ou não e só inicializo quando ele é nulo.
Se o adaptador não for nulo, tenho certeza de que inicializei meu adaptador pelo menos uma vez.
Portanto, irei apenas adicionar a lista ao adaptador e chamar notificardatasetchanged.
O RecyclerView sempre mantém a última posição rolada, portanto, você não precisa armazenar a última posição, apenas chame notifikdatasetchanged, o recycler view sempre atualiza os dados sem ir para o topo.
Obrigado Happy Coding
fonte
Mantenha a posição de rolagem usando a resposta @DawnYu para embrulhar
notifyDataSetChanged()
assim:fonte
A primeira resposta de @DawnYu funciona, mas a visualização de reciclagem primeiro rola para o topo, depois volta para a posição de rolagem pretendida, causando uma reação de "tremulação" que não é agradável.
Para atualizar o recyclerView, especialmente depois de sair de outra atividade, sem piscar e manter a posição de rolagem, você precisa fazer o seguinte.
Espero que isto ajude.
fonte
Eu não usei o Recyclerview, mas fiz isso no ListView. Amostra de código em Recyclerview:
É o ouvinte quando o usuário está rolando. A sobrecarga de desempenho não é significativa. E a primeira posição visível é precisa dessa maneira.
fonte
findFirstVisibleItemPosition
retorna "a posição do adaptador da primeira visão visível", mas e o deslocamento.A solução aqui é continuar rolando a exibição de reciclagem quando uma nova mensagem chegar.
O método onChanged () detecta a ação executada em recyclerview.
fonte
Isso está funcionando para mim em Kotlin.
O deslocamento de rolagem não muda.
fonte
Tive esse problema com uma lista de itens em que cada um tinha um tempo em minutos até que estivessem "vencidos" e precisassem ser atualizados. Eu atualizaria os dados e depois ligaria
e sempre rolaria para o topo. Eu substituí isso por
e foi bom. Nenhum dos outros métodos neste tópico funcionou para mim. No entanto, ao usar esse método, ele fez cada item individual piscar quando foi atualizado, então eu também tive que colocar isso no onCreateView do fragmento pai
fonte
Se você tiver um ou mais EditTexts dentro de itens de uma visualização de reciclagem , desative o foco automático deles, colocando esta configuração na visualização pai de uma visualização de reciclagem:
Tive esse problema quando comecei outra atividade lançada a partir de um item de visualização de reciclagem, quando voltei e configurei uma atualização de um campo em um item com notificarItemChanged (posição) a rolagem de movimentos de RV e minha conclusão foi que, o autofoco de EditText Itens, o código acima resolveu meu problema.
melhor.
fonte
Apenas retorne se a posição e posição antigas forem iguais;
fonte