Eu tenho um DialogFragment
que contém um RecyclerView
(uma lista de cartões).
Dentro disso, RecyclerView
há um ou mais CardViews
que podem ter qualquer altura.
Quero dar a essa DialogFragment
a altura correta com base nas CardViews
que estão contidas.
Normalmente isso seria simples, gostaria de definir wrap_content
sobre a RecyclerView
assim.
<android.support.v7.widget.RecyclerView ...
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:scrollbars="vertical" >
</android.support.v7.widget.RecyclerView>
Porque eu estou usando um RecyclerView
isto não funciona ver:
https://issuetracker.google.com/issues/37001674
e
A altura da visualização do Recolhedor aninhado não quebra seu conteúdo
Em ambas as páginas, as pessoas sugerem estender LinearLayoutManager
e substituironMeasure()
Eu usei o LayoutManager que alguém forneceu no primeiro link:
public static class WrappingLayoutManager extends LinearLayoutManager {
public WrappingLayoutManager(Context context) {
super(context);
}
private int[] mMeasuredDimension = new int[2];
@Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
int widthSpec, int heightSpec) {
final int widthMode = View.MeasureSpec.getMode(widthSpec);
final int heightMode = View.MeasureSpec.getMode(heightSpec);
final int widthSize = View.MeasureSpec.getSize(widthSpec);
final int heightSize = View.MeasureSpec.getSize(heightSpec);
measureScrapChild(recycler, 0,
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension);
int width = mMeasuredDimension[0];
int height = mMeasuredDimension[1];
switch (widthMode) {
case View.MeasureSpec.EXACTLY:
case View.MeasureSpec.AT_MOST:
width = widthSize;
break;
case View.MeasureSpec.UNSPECIFIED:
}
switch (heightMode) {
case View.MeasureSpec.EXACTLY:
case View.MeasureSpec.AT_MOST:
height = heightSize;
break;
case View.MeasureSpec.UNSPECIFIED:
}
setMeasuredDimension(width, height);
}
private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
int heightSpec, int[] measuredDimension) {
View view = recycler.getViewForPosition(position);
if (view != null) {
RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
getPaddingLeft() + getPaddingRight(), p.width);
int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
getPaddingTop() + getPaddingBottom(), p.height);
view.measure(childWidthSpec, childHeightSpec);
measuredDimension[0] = view.getMeasuredWidth();
measuredDimension[1] = view.getMeasuredHeight();
recycler.recycleView(view);
}
}
}
No entanto, isso não funcionou porque
heightSize = View.MeasureSpec.getSize(heightSpec);
retorna um valor muito grande que parece estar relacionado match_parent
.
Ao comentar height = heightSize;
(no segundo caso de troca), eu consegui fazer a altura funcionar, mas apenas se uma TextView
criança dentro CardView
dela não envolver seu próprio texto (uma frase longa).
Assim que isso TextView
envolve seu próprio texto, a altura DEVE aumentar, mas não aumenta. Ele calculou a altura dessa frase longa como uma única linha, não uma linha quebrada (2 ou mais).
Algum conselho sobre como eu deveria melhorar isso LayoutManager
para que eu RecyclerView
trabalhe WRAP_CONTENT
?
Editar: este gerenciador de layout pode funcionar para a maioria das pessoas, mas ainda tem problemas com a rolagem e o cálculo das alturas de quebra de visualizações de texto
public class MyLinearLayoutManager extends LinearLayoutManager {
public MyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
private int[] mMeasuredDimension = new int[2];
@Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
int widthSpec, int heightSpec) {
final int widthMode = View.MeasureSpec.getMode(widthSpec);
final int heightMode = View.MeasureSpec.getMode(heightSpec);
final int widthSize = View.MeasureSpec.getSize(widthSpec);
final int heightSize = View.MeasureSpec.getSize(heightSpec);
int width = 0;
int height = 0;
for (int i = 0; i < getItemCount(); i++) {
measureScrapChild(recycler, i,
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension);
if (getOrientation() == HORIZONTAL) {
width = width + mMeasuredDimension[0];
if (i == 0) {
height = mMeasuredDimension[1];
}
} else {
height = height + mMeasuredDimension[1];
if (i == 0) {
width = mMeasuredDimension[0];
}
}
}
switch (widthMode) {
case View.MeasureSpec.EXACTLY:
width = widthSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
switch (heightMode) {
case View.MeasureSpec.EXACTLY:
height = heightSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
setMeasuredDimension(width, height);
}
private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
int heightSpec, int[] measuredDimension) {
View view = recycler.getViewForPosition(position);
if (view != null) {
RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
getPaddingLeft() + getPaddingRight(), p.width);
int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
getPaddingTop() + getPaddingBottom(), p.height);
view.measure(childWidthSpec, childHeightSpec);
measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
recycler.recycleView(view);
}
}
}
fonte
Jan 22, 2016: This has been merged into the internal tree, should be available with the next version of support library.
Respostas:
Na atualização da Biblioteca de suporte Android 23.2.1 , todos os WRAP_CONTENT devem funcionar corretamente.
Atualize a versão de uma biblioteca no
gradle
arquivo OU para:resolveu um problema, como bugs corrigidos relacionados a vários métodos de medição-especificação
Verifique http://developer.android.com/tools/support-library/features.html#v7-recyclerview
você pode verificar o histórico de revisões da Biblioteca de Suporte
fonte
23.2.0
ele começa a travar meu aplicativo. Então, eu segui sua resposta e minhaRecyclerView
não está quebrando. Por quê?mRecyclerView.setNestedScrollingEnabled(false);
caso contrário, a exibição do reciclador ainda manipulará a rolagem em si para transmitir os eventos aos pais.ATUALIZAÇÃO 02.07.2020
Esse método pode impedir a reciclagem e não deve ser usado em grandes conjuntos de dados .
ATUALIZAÇÃO 05.07.2019
Se você estiver usando
RecyclerView
dentro de aScrollView
, mudeScrollView
paraandroidx.core.widget.NestedScrollView
. Dentro dessa visão, não há necessidade de empacotarRecyclerView
dentro de aRelativeLayout
.Finalmente encontrei a solução para este problema.
Tudo o que você precisa fazer é envolver o arquivo
RecyclerView
emRelativeLayout
. Talvez haja outras visualizações que também possam funcionar.fonte
Aqui está a versão refinada da classe que parece funcionar e carece de problemas que outras soluções têm:
Isso também está disponível como uma biblioteca . Link para a classe relevante .
fonte
onBindViewHolder()
ser chamado. Isso é ruim porque, nesse momento, eu chamo, por exemplo,holder.textView.setText(longText)
para que a criança fique mais alta, mas não se reflete na altura da recicladora. Se você tem alguma idéia (como mudanças rápidas no adaptador), ficaria grato.RecyclerView
dentro da verticalRecyclerView
.ATUALIZAR
Pela atualização da Biblioteca de suporte Android 23.2, todos os WRAP_CONTENT devem funcionar corretamente.
Atualize a versão de uma biblioteca no arquivo gradle.
Resposta original
Conforme respondido em outra pergunta, você precisa usar o método onMeasure () original quando a altura da visualização do reciclador for maior que a altura da tela. Esse gerenciador de layout pode calcular ItemDecoration e pode rolar com mais.
resposta original: https://stackoverflow.com/a/28510031/1577792
fonte
gridlayoutmanager
estaggeredgridlayoutmanager
considerando contagem espaço na menteAqui está a versão c # para mono android
fonte
var p = (RecyclerView.LayoutParams) child.LayoutParameters
porvar p = child.LayoutParameters.JavaCast<RecyclerView.LayoutParams>()
RecyclerView
suporte adicional parawrap_content
a23.2.0
qual foi de buggy, 23.2.1 foi apenas estável, de modo que você pode usar:Você pode ver o histórico de revisões aqui:
https://developer.android.com/topic/libraries/support-library/revisions.html
Nota:
Observe também que após a atualização biblioteca de suporte a
RecyclerView
respeitaráwrap_content
, bem comomatch_parent
então se você tem um item de exibição de umRecyclerView
conjunto comomatch_parent
o único modo de exibição irá preencher a tela inteirafonte
Esse comentário me ajudou.
Put the recyclerview in any other layout (Relative layout is preferable). Then change recyclerview's height/width as match parent to that layout and set the parent layout's height/width as wrap content.
fonte
O problema com rolagem e quebra de texto é que esse código pressupõe que a largura e a altura estão definidas como
wrap_content
. No entanto, éLayoutManager
necessário saber que a largura horizontal está restrita. Portanto, em vez de criar o seu própriowidthSpec
para cada exibição filho, basta usar o originalwidthSpec
:fonte
Tente isto (é uma solução desagradável, mas pode funcionar): No
onCreate
método do seuActivity
ou noonViewCreated
método do seu fragmento. Defina um retorno de chamada pronto para ser acionado quando aRecyclerView
primeira renderização, assim:No
calculeRecyclerViewFullHeight
calcular aRecyclerView
altura total com base na altura de seus filhos.No meu caso, meu
RecyclerView
é conter umSwipeRefreshLayout
por esse motivo, estou definindo a altura paraSwipeRefreshView
e não paraRecyclerView
mas, se você não tiverSwipeRefreshView
, pode definir a altura comoRecyclerView
lugar.Deixe-me saber se isso ajudou ou não.
fonte
RecyclerView
instância.Isso agora funciona como eles lançaram na versão 23.2, conforme declarado neste post . Citando o post oficial do blog
fonte
Basta colocar seu RecyclerView dentro de um NestedScrollView. Funciona perfeitamente
fonte
Eu tinha usado algumas das soluções acima, mas estava funcionando para
width
masheight
.compileSdkVersion
maior que 23 , você poderá usar diretamente o RecyclerView fornecido em suas respectivas bibliotecas de suporte da visualização do reciclador, como para 23 será'com.android.support:recyclerview-v7:23.2.1'
. Essas bibliotecas de suporte suportam atributos dewrap_content
largura e altura.Você precisa adicioná-lo às suas dependências
compileSdkVersion
menos de 23 anos , pode usar a solução abaixo mencionada.Encontrei este tópico do Google sobre esse problema. Nesta discussão, há uma contribuição que leva à implementação do LinearLayoutManager .
Eu testei para altura e largura e funcionou bem para mim em ambos os casos.
fonte
Em vez de usar qualquer biblioteca, a solução mais fácil até a nova versão é abrir b.android.com/74772 . Você encontrará facilmente a melhor solução conhecida até hoje.
PS: b.android.com/74772#c50 funcionou para mim
fonte
sugiro que você coloque a reciclagem em qualquer outro layout (o layout relativo é preferível). Altere a altura / largura da vista da reciclagem como pai correspondente para esse layout e defina a altura / largura do layout pai como conteúdo de quebra automática. funciona para mim
fonte
Substitua
measureScrapChild
para seguir o código:Eu uso o xamarin, então esse é o código c #. Eu acho que isso pode ser facilmente "traduzido" para Java.
fonte
Atualize sua visualização com valor nulo, em vez de grupo de visualizações pai, no método Adapter viewholder onCreateViewHolder.
fonte
Você deve colocar um FrameLayout como visualização principal e, em seguida, colocar dentro de um RelativeLayout com o ScrollView e, pelo menos, o seu RecyclerView, funciona para mim.
O verdadeiro truque aqui é o RelativeLayout ...
Feliz por ajudar.
fonte
Eu não trabalhei na minha resposta, mas do jeito que eu sei StaggridLayoutManager sem. da grade 1 pode resolver seu problema, pois o StaggridLayout ajustará automaticamente sua altura e largura no tamanho do conteúdo. Se funcionar, não se esqueça de verificá-lo como uma resposta correta.
fonte