Tenho um longo tempo para ListView
que o usuário possa rolar antes de retornar à tela anterior. Quando o usuário abrir ListView
novamente, desejo que a lista seja rolada para o mesmo ponto em que estava anteriormente. Alguma idéia de como conseguir isso?
android
android-listview
scroll
scroll-position
rantravee
fonte
fonte
Respostas:
Tente o seguinte:
Explicação:
ListView.getFirstVisiblePosition()
retorna o item da lista visível no topo. Mas esse item pode ser parcialmente rolado para fora da vista e, se você quiser restaurar a posição exata da rolagem da lista, precisará obter esse deslocamento. Portanto,ListView.getChildAt(0)
retorna oView
item da lista superior e, em seguida,View.getTop() - mList.getPaddingTop()
retorna seu deslocamento relativo da parte superior daListView
. Então, para restaurar aListView
posição de rolagem, chamamosListView.setSelectionFromTop()
com o índice do item que queremos e um deslocamento para posicionar sua borda superior a partir da parte superior doListView
.fonte
int index = mList.getFirstVisiblePosition();
e apenas uma linha para restaurar:mList.setSelectionFromTop(index, 0);
. Ótima resposta (+1)! Eu tenho procurado uma solução elegante para este problema.fonte
Adotei a solução sugerida por @ (Kirk Woll), e ela funciona para mim. Também vi no código-fonte Android do aplicativo "Contatos" que eles usam uma técnica semelhante. Gostaria de adicionar mais alguns detalhes: No topo da minha classe derivada de ListActivity:
Em seguida, algum método substitui:
É claro que "loadData" é minha função de recuperar dados do banco de dados e colocá-los na lista.
No meu dispositivo Froyo, isso funciona quando você altera a orientação do telefone e quando edita um item e volta à lista.
fonte
mListState = getListView().onSaveInstanceState().
Principalmente na rotação do dispositivo.onRestoreInstanceState
nunca é chamado :(Uma maneira muito simples:
O método setSelection redefinirá a lista para o item fornecido. Se não estiver no modo de toque, o item será realmente selecionado se, no modo de toque, o item será posicionado apenas na tela.
Uma abordagem mais complicada:
fonte
Encontrei algo interessante sobre isso.
Tentei setSelection e scrolltoXY, mas não funcionou, a lista permaneceu na mesma posição, após algumas tentativas e erros, obtive o seguinte código que funciona
Se, em vez de postar o Runnable, você tentar o runOnUiThread, ele também não funcionará (pelo menos em alguns dispositivos)
Essa é uma solução alternativa muito estranha para algo que deve ser direto.
fonte
setSelectionFromTop()
não funciona.CUIDADO!! Há um erro no AbsListView que não permite que o onSaveState () funcione corretamente se o ListView.getFirstVisiblePosition () for 0.
Portanto, se você tiver imagens grandes que ocupam a maior parte da tela e rolar para a segunda imagem, mas um pouco da primeira estiver sendo exibida, a posição de rolagem não será salva ...
de AbsListView.java:1650 (comentários meus)
Mas nessa situação, o 'top' no código abaixo será um número negativo que causa outros problemas que impedem a restauração correta do estado. Então, quando o 'top' for negativo, pegue o próximo filho
fonte
É o bastante
fonte
Para quem procura uma solução para esse problema, a raiz do problema pode estar no local em que você está configurando o adaptador de exibições de lista. Depois de definir o adaptador na vista de lista, ele redefine a posição de rolagem. Apenas algo a considerar. Mudei a configuração do adaptador para o meu onCreateView depois de pegarmos a referência ao listview e ele resolveu o problema para mim. =)
fonte
Estou postando isso porque estou surpreso que ninguém tenha mencionado isso.
Depois que o usuário clicar no botão Voltar, ele retornará à exibição de lista no mesmo estado em que saiu dela.
Este código substituirá o botão "para cima" para se comportar da mesma forma que o botão Voltar. Portanto, no caso de Listview -> Detalhes -> Voltar para o Listview (e nenhuma outra opção), este é o código mais simples para manter a posição de rolagem e o conteúdo na lista.
Cuidado: Se você puder ir para outra atividade a partir da atividade de detalhes, o botão para cima retornará a ela para que você tenha que manipular o histórico do botão de volta para que isso funcione.
fonte
Simplesmente não é
android:saveEnabled="true"
suficiente na declaração xml do ListView?fonte
A MELHOR SOLUÇÃO É:
VOCÊ DEVE LIGAR NO PÓS E NA LINHA!
fonte
Você pode manter o estado de rolagem após uma recarga se salvar o estado antes de recarregá-lo e restaurá-lo depois. No meu caso, fiz uma solicitação de rede assíncrona e recarreguei a lista em um retorno de chamada após a conclusão. É aqui que eu restauro o estado. A amostra do código é Kotlin.
fonte
Se você estiver usando fragmentos hospedados em uma atividade, poderá fazer algo assim:
fonte
Se você está salvando / restaurando a posição de rolagem de
ListView
si mesmo, está basicamente duplicando a funcionalidade já implementada na estrutura do Android. AListView
restauração restaura a posição de rolagem fina por si só, exceto uma ressalva: como @aaronvargas mencionou, há um erroAbsListView
que não permite restaurar a posição de rolagem fina para o primeiro item da lista. No entanto, a melhor maneira de restaurar a posição de rolagem não é restaurá-la. A estrutura do Android fará melhor para você. Apenas verifique se você atendeu às seguintes condições:setSaveEnabled(false)
método e não configurou oandroid:saveEnabled="false"
atributo para a lista no arquivo de layout xmlExpandableListView
substituir olong getCombinedChildId(long groupId, long childId)
método para que ele retorne um número longo positivo (a implementação padrão na classeBaseExpandableListAdapter
retorna um número negativo). Aqui estão alguns exemplos:.
ListView
ouExpandableListView
for usado em um fragmento, não o recrie na recreação da atividade (após rotação da tela, por exemplo). Obtenha o fragmento com ofindFragmentByTag(String tag)
métodoListView
possuiandroid:id
e é exclusivo.Para evitar a advertência acima mencionada com o primeiro item da lista, você pode criar seu adaptador da maneira que ele retorna uma exibição especial de altura zero de pixels dummy para a
ListView
posição 0. Aqui está um exemplo de projeto simples que mostraListView
eExpandableListView
restaura suas posições de rolagem fina, enquanto suas posições de rolagem não são salvas explicitamente /restaurado. A posição de rolagem fina é restaurada perfeitamente, mesmo para os cenários complexos, com mudança temporária para outro aplicativo, rotação dupla da tela e retorno ao aplicativo de teste. Observe que, se você sair explicitamente do aplicativo (pressionando o botão Voltar), a posição de rolagem não será salva (assim como todas as outras exibições não salvarão seu estado). https://github.com/voromto/RestoreScrollPosition/releasesfonte
Para uma atividade derivada de ListActivity que implementa LoaderManager.LoaderCallbacks usando um SimpleCursorAdapter, não funcionou para restaurar a posição em onReset (), porque a atividade era quase sempre reiniciada e o adaptador era recarregado quando a exibição de detalhes era fechada. O truque era restaurar a posição em onLoadFinished ():
em onListItemClick ():
em onLoadFinished ():
em onBackPressed ():
fonte
Nenhuma das soluções oferecidas aqui parecia funcionar para mim. No meu caso, eu tenho um
ListView
em umFragment
que estou substituindo em umFragmentTransaction
, portanto, uma novaFragment
instância é criada cada vez que o fragmento é mostrado, o que significa que oListView
estado não pode ser armazenado como um membro doFragment
.Em vez disso, acabei armazenando o estado no meu costume
Application
classe . O código abaixo deve lhe dar uma idéia de como isso funciona:A ideia básica é que você armazene o estado fora da instância do fragmento. Se você não gosta da ideia de ter um campo estático em sua classe de aplicativo, acho que você poderia fazê-lo implementando uma interface de fragmento e armazenando o estado em sua atividade.
Outra solução seria armazená-lo
SharedPreferences
, mas fica um pouco mais complicado, e você deve limpá-lo no início do aplicativo, a menos que queira que o estado persista durante o lançamento de aplicativos.Além disso, para evitar a "posição de rolagem não salva quando o primeiro item estiver visível", você pode exibir um primeiro item fictício com
0px
altura. Isso pode ser conseguido substituindogetView()
seu adaptador, desta forma:fonte
Minha resposta é para Firebase e a posição 0 é uma solução alternativa
e convertView
posição 0 a adicione um item em branco que você não está usando
Vi esse trabalho temporariamente sem incomodar o usuário, espero que funcione para você
fonte
use este código abaixo:
e sempre que você atualizar seus dados, use este código abaixo:
fonte
Estou usando o FirebaseListAdapter e não consegui fazer nenhuma das soluções funcionar. Acabei fazendo isso. Acho que existem maneiras mais elegantes, mas essa é uma solução completa e funcional.
Antes do onCreate:
Dentro do FirebaseListAdapter:
onStart:
onStop:
Desde que eu também tive que resolver isso para FirebaseRecyclerAdapter também estou postando a solução aqui:
Antes do onCreate:
Dentro do FirebaseRecyclerAdapter:
onStart:
onStop:
fonte
Para esclarecer a excelente resposta de Ryan Newsom e ajustá-la para fragmentos e para o caso usual em que queremos navegar de um fragmento ListView "mestre" para um fragmento "detalhes" e depois voltar para o "mestre"
A "mágica" aqui é que, quando retornamos do fragmento de detalhes para o fragmento de ListView, a visualização não é recriada, não configuramos o adaptador do ListView, para que tudo permaneça como o deixamos!
fonte