Eu procurei por soluções para esse problema, e a única resposta que posso encontrar parece ser " não coloque um ListView em um ScrollView ". Ainda não vi nenhuma explicação real para o porquê . A única razão pela qual consigo encontrar é que o Google não acha que você deva fazer isso. Bem, eu faço, então eu fiz.
Portanto, a pergunta é: como você pode colocar um ListView em um ScrollView sem que ele desmorone à sua altura mínima?
ListView
.ListView
pode ter vários estilos de linha, além de linhas não selecionáveis.Respostas:
Usar um
ListView
para fazê-lo não rolar é extremamente caro e vai contra todo o propósito deListView
. Você não deve fazer isso. Basta usar umLinearLayout
.fonte
How can I put a ListView into a ScrollView without it collapsing?
... Você pode dizer que não deve fazê-lo, mas também dar uma resposta sobre como fazê-lo, é uma boa resposta. Você sabe que um ListView tem outros recursos interessantes além da rolagem, recursos que o LinearLayout não possui.Aqui está a minha solução. Sou bastante novo na plataforma Android e tenho certeza de que isso é um pouco tolo, especialmente na parte de chamar .measure diretamente e definir o
LayoutParams.height
propriedade diretamente, mas funciona.Tudo o que você precisa fazer é ligar
Utility.setListViewHeightBasedOnChildren(yourListView)
e será redimensionado para acomodar exatamente a altura de seus itens.fonte
LinearLayout
que a não possui todas as características inerentes aListView
- não possui divisórias, exibições de cabeçalho / rodapé, um seletor de lista que corresponda às cores do tema da interface do usuário do telefone etc. Honestamente, não há razão para que você não possa rolar o contêiner interno até chegar ao fim e interrompa a interceptação de eventos de toque para que o contêiner externo role. Todo navegador de desktop faz isso quando você está usando sua roda de rolagem. O próprio Android pode lidar com rolagem aninhada se você estiver navegando pelo trackball, por que não usar o touch?listItem.measure(0,0)
lançará um NPE se listItem for uma instância do ViewGroup. Eu adicionei o seguinte anteslistItem.measure
:if (listItem instanceof ViewGroup) listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
ListView
pode conter itens de altura variável. A chamada paragetMeasuredHeight()
retorna apenas a altura mínima desejada, em oposição à altura real. Tentei usargetHeight()
, mas isso retorna 0. Alguém tem alguma idéia de como abordar isso?Isto vai certamente funcionar ............
Você só tem que substituir o seu
<ScrollView ></ScrollView>
no layout do arquivo XML com esteCustom ScrollView
como<com.tmd.utils.VerticalScrollview > </com.tmd.utils.VerticalScrollview >
fonte
Em vez de colocar
ListView
dentro de aScrollView
, podemos usarListView
como aScrollView
. Coisas que precisam estar dentroListView
podem ser colocadas dentro doListView
. Outros layouts na parte superior e inferiorListView
podem ser colocados adicionando layouts ao cabeçalho e rodapé deListView
. Assim, o todoListView
lhe dará uma experiência de rolagem.fonte
Existem muitas situações em que faz muito sentido ter os ListViews em um ScrollView.
Aqui está o código baseado na sugestão do DougW ... funciona em um fragmento, consome menos memória.
chame setListViewHeightBasedOnChildren (listview) em cada listview incorporada.
fonte
Na verdade, o ListView já é capaz de se medir para ser alto o suficiente para exibir todos os itens, mas não o faz quando você simplesmente especifica wrap_content (MeasureSpec.UNSPECIFIED). Isso será feito quando houver uma altura com MeasureSpec.AT_MOST. Com esse conhecimento, você pode criar uma subclasse muito simples para resolver esse problema, que funciona muito melhor do que qualquer uma das soluções postadas acima. Você ainda deve usar wrap_content com esta subclasse.
Manipular o heightMeasureSpec como AT_MOST com um tamanho muito grande (Integer.MAX_VALUE >> 4) faz com que o ListView meça todos os seus filhos até a altura (muito grande) especificada e defina sua altura de acordo.
Isso funciona melhor que as outras soluções por alguns motivos:
No lado negativo, você pode argumentar que fazer isso depende de um comportamento não documentado no SDK que pode mudar. Por outro lado, você pode argumentar que é assim que o wrap_content realmente deve funcionar com o ListView e que o comportamento atual do wrap_content está quebrado.
Se você está preocupado que o comportamento possa mudar no futuro, você deve simplesmente copiar a função onMeasure e as funções relacionadas do ListView.java e para sua própria subclasse, e fazer com que o caminho AT_MOST através do onMeasure seja executado também como NÃO ESPECIFICADO.
A propósito, acredito que essa é uma abordagem perfeitamente válida quando você trabalha com um pequeno número de itens da lista. Pode ser ineficiente quando comparado ao LinearLayout, mas quando o número de itens é pequeno, o uso do LinearLayout é otimização desnecessária e, portanto, complexidade desnecessária.
fonte
Há uma configuração embutida para isso. No ScrollView:
Em Java,
Romain Guy explica em detalhes aqui: http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/
fonte
Você cria um ListView personalizado que não é rolável
No arquivo de recursos de layout
No arquivo Java
Crie um objeto do seu customListview em vez do ListView, como: NonScrollListView non_scroll_list = (NonScrollListView) findViewById (R.id.lv_nonscroll_list);
fonte
Não podemos usar duas rolagens simultaneamente. Teremos o comprimento total do ListView e expandiremos o listview com a altura total. Copie o método setListViewHeightBasedOnChildren (lv) no seu código e expanda o listview e use o listview dentro do scrollview. arquivo \ layout xml
Método onCreate na classe Activity:
fonte
Essa é uma combinação das respostas de DougW, Good Guy Greg e Paul. Descobri que tudo era necessário ao tentar usar isso com um adaptador de listview personalizado e itens de lista não padrão, caso contrário, o listview travou o aplicativo (também travou com a resposta do Nex):
fonte
Você não deve colocar um ListView em um ScrollView porque um ListView já é um ScrollView. Então, seria como colocar um ScrollView em um ScrollView.
O que você está tentando realizar?
fonte
Eu converti @ DougW
Utility
em C # (usado no Xamarin). O seguinte funciona bem para itens de altura fixa na lista e será muito bom, ou pelo menos um bom começo, se apenas alguns dos itens forem um pouco maiores que o item padrão.Obrigado @DougW, isso me tirou de uma situação difícil quando tive que trabalhar com o OtherPeople'sCode. :-)
fonte
setListViewHeightBasedOnChildren()
método? Porque não funciona o tempo todo para mim.Esta é a única coisa que funcionou para mim:
no pirulito em diante, você pode usar
Isso habilita ou desabilita a rolagem aninhada para esta exibição. Se você precisar de compatibilidade com versões anteriores do sistema operacional, precisará usar o RecyclerView.
fonte
Antes não era possível. Porém, com o lançamento das novas bibliotecas Appcompat e Design, isso pode ser alcançado.
Você só precisa usar o NestedScrollView https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html
Não sei que funcionará com o Listview ou não, mas funciona com o RecyclerView.
Fragmento de código:
fonte
Ei, eu tive um problema semelhante. Eu queria exibir uma exibição de lista que não rolasse e descobri que manipular os parâmetros funcionava, mas era ineficiente e se comportaria de maneira diferente em dispositivos diferentes. Como resultado, esse é um pedaço do meu código de programação que realmente faz isso com muita eficiência .
Nota: se você usar isso,
notifyDataSetChanged();
não funcionará como pretendido, pois as visualizações não serão redesenhadas. Faça isso se precisar de uma solução alternativafonte
Há dois problemas ao usar um ListView dentro de um ScrollView.
1- O ListView deve expandir totalmente para a altura dos filhos. este ListView resolva isso:
A altura do divisor deve ser 0, use preenchimento em linhas.
2- O ListView consome eventos de toque, para que o ScrollView não possa ser rolado normalmente. Este ScrollView resolve este problema:
Esta é a melhor maneira que encontrei para fazer o truque!
fonte
Uma solução que uso é adicionar todo o conteúdo do ScrollView (o que deve estar acima e abaixo do listView) como headerView e footerView no ListView.
Por isso, funciona como, também, o convertview é redimensionado como deveria ser.
fonte
graças ao código de Vinay, aqui está o meu código para quando você não pode ter um listview dentro de um scrollview, mas precisa de algo assim
o relativeLayout permanece dentro de um ScrollView, para que tudo se torne rolável :)
fonte
Aqui é pequena modificação na @djunod 's resposta que eu preciso para fazê-lo funcionar perfeitamente:
fonte
tente isso, isso funciona para mim, esqueci onde o encontrei, em algum lugar no estouro da pilha, não estou aqui para explicar por que não funciona, mas esta é a resposta :).
EDIT !, finalmente descobri onde obtive o código. aqui ! : ListView dentro do ScrollView não está rolando no Android
fonte
Embora os métodos setListViewHeightBasedOnChildren () sugeridos funcionem na maioria dos casos, em alguns casos, especialmente com muitos itens, notei que os últimos elementos não são exibidos. Então, decidi imitar uma versão simples do comportamento do ListView para reutilizar qualquer código do adaptador, aqui está a alternativa do ListView:
fonte
Todas essas respostas estão erradas !!! Se você estiver tentando colocar uma exibição de lista em uma exibição de rolagem, deve repensar seu design. Você está tentando colocar um ScrollView em um ScrollView. Interferir com a lista prejudicará o desempenho da lista. Foi projetado para ser assim pelo Android.
Se você realmente deseja que a lista esteja no mesmo pergaminho que os outros elementos, tudo o que você precisa fazer é adicionar os outros itens ao topo da lista, usando uma instrução switch simples no seu adaptador:
O adaptador de lista pode lidar com tudo, pois apenas renderiza o que é visível.
fonte
Todo esse problema desapareceria se LinearLayout tivesse um método setAdapter, porque, quando você dissesse a alguém para usá-lo, a alternativa seria trivial.
Se você realmente deseja um ListView de rolagem dentro de outra exibição de rolagem, isso não ajudará, mas, caso contrário, isso lhe dará uma idéia.
Você precisa criar um adaptador personalizado para combinar todo o conteúdo que você deseja rolar e definir o adaptador do ListView para isso.
Não tenho código de exemplo à mão, mas se você quiser algo parecido.
Então você precisa criar um adaptador que represente todo esse conteúdo. Os ListView / Adaptadores também são inteligentes o suficiente para lidar com diferentes tipos, mas você mesmo deve escrever o adaptador.
A API da interface do usuário do Android não é tão madura quanto praticamente tudo o que existe, por isso não tem as mesmas gentilezas que outras plataformas. Além disso, ao fazer algo no android, você precisa estar em uma mentalidade android (unix), na qual espera que, para fazer qualquer coisa, você provavelmente precisará montar a funcionalidade de partes menores e escrever um monte de seu próprio código para obtê-lo. trabalhos.
fonte
Quando colocamos
ListView
dentro,ScrollView
dois problemas surgem. UmScrollView
mede seus filhos no modo NÃO ESPECIFICADO, entãoListView
define sua própria altura para acomodar apenas um item (não sei por quê); outro éScrollView
intercepta o evento de toque paraListView
não rolar.Mas nós pode colocar
ListView
dentroScrollView
com alguma solução alternativa. Este post , por mim, explica a solução alternativa. Por essa solução alternativa, também podemos reterListView
o recurso de reciclagem.fonte
Em vez de colocar a visualização de lista dentro do Scrollview, coloque o restante do conteúdo entre o visualizador de listas e a abertura do Scrollview como uma exibição separada e defina essa exibição como o cabeçalho da exibição da lista. Por fim, você acabará apenas na exibição de lista, encarregando-se do Scroll.
fonte
Essa biblioteca é a solução mais fácil e rápida para o problema.
fonte
Aqui está minha versão do código que calcula a altura total da exibição em lista. Este funciona para mim:
fonte