ventajas usar studio son recyclerview qué que personalizado los libreria elementos ejemplo cuando construyen cardview android android-recyclerview android-gridlayout gridlayoutmanager

android - usar - RecyclerView: elementos fuera de pantalla omitiendo el primer pase de diseño



son los elementos qué construyen un recyclerview (3)

Verifique si ha setHasStableIds(true) ; si lo hace, debe anular el getItemId(int position) para especificar ids para cada vista. Si no lo hace, las siguientes llamadas a onBindViewholders() no se activarán y su vista no se actualizará.

Estoy teniendo problemas con uno de mis adaptadores. Tengo una selección de imágenes que se muestran en una cuadrícula como la siguiente:

Esto funciona bien cuando tengo una pantalla con valor de elementos y todos se muestran bien. El problema aparece cuando hay más elementos para desplazarse hacia abajo. Inicialmente, cuando me desplazo hacia abajo, los elementos aparecen en blanco, los contenedores GridLayout están allí y se ejecuta el código para mostrar las imágenes, pero no aparecen en la pantalla como se muestra aquí:

Si me desplazo hacia atrás, vuelvo a bajar, las imágenes aparecen exactamente donde deberían estar:

Parece que necesito actualizar el diseño o decirle al procesador que algo ha cambiado, pero nada de lo que intento parece hacer nada. Intenté llamar a requestLayout e invalidate pero parece que no resuelve el problema. También registré un GlobalOnLayoutListener, pero no me fue mejor.

Aquí está el código relevante:

Esto es de mi método onBindViewHolder

final GridLayout grid = ((KKAlbumViewHolder) holder).mGridLayout; grid.removeAllViews(); int width = grid.getWidth(); if(width > 0) { albumHolder.setPreviewImages(posts); }else { albumHolder.itemView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { albumHolder.itemView.removeOnLayoutChangeListener(this); albumHolder.setPreviewImages(posts); albumHolder.mGridLayout.invalidate(); } }); }

Este es el método que uso para diseñar las imágenes. Básicamente coloca las imágenes en una cuadrícula irregular, por lo que si hay una imagen larga o alta, esa imagen intentará ocupar una fila completa o una columna completa, dependiendo de qué espacio es libre. La razón por la que configuro el ancho y la altura del .fit() es para que picasso no se queje del método .fit() :

public void setPreviewImages(ArrayList<KKPost> posts) { Picasso picasso = Picasso.with(itemView.getContext()); int space = 0; int tl = 1 << 0; int tr = 1 << 1; int bl = 1 << 2; int br = 1 << 3; int lCol = tl | bl; int rCol = tr | br; int tRow = tl | tr; int bRow = bl | br; int full = lCol | rCol; boolean hasLongImage = false; for(KKPost post : posts) { if(space == full){ break; } int margin = 2; ImageView view = new ImageView(itemView.getContext()); GridLayout.LayoutParams param = new GridLayout.LayoutParams(); view.setBackgroundColor(Color.LTGRAY); if(posts.size() < 4){ param.columnSpec = GridLayout.spec(0, 2); param.rowSpec = GridLayout.spec(0, 2); param.width = mGridLayout.getWidth(); param.height = mGridLayout.getHeight(); mGridLayout.addView(view, param); picasso.load(post.url).fit().centerCrop().into(view); break; } if (post.aspectRatio >= 1.2 && !hasLongImage) { //landscape if((space & tRow) == 0){ param.rowSpec = GridLayout.spec(0, 1); param.columnSpec = GridLayout.spec(0, 2); param.height = mGridLayout.getHeight()/2; param.width = mGridLayout.getWidth(); param.bottomMargin = margin; space |= tRow; mGridLayout.addView(view, param); picasso.load(post.url).fit().centerCrop().into(view); hasLongImage = true; continue; } if((space & bRow) == 0){ param.rowSpec = GridLayout.spec(1, 1); param.columnSpec = GridLayout.spec(0, 2); param.height = mGridLayout.getHeight()/2; param.width = mGridLayout.getWidth(); param.topMargin = margin; space |= bRow; mGridLayout.addView(view, param); picasso.load(post.url).fit().centerCrop().into(view); hasLongImage = true; continue; } } else if (post.aspectRatio <= 0.8 && post.aspectRatio > 0 && !hasLongImage) { //portrait if((space & lCol) == 0){ param.columnSpec = GridLayout.spec(0, 1); param.rowSpec = GridLayout.spec(0, 2); param.height = mGridLayout.getHeight(); param.width = mGridLayout.getWidth()/2; param.rightMargin = margin; space |= lCol; mGridLayout.addView(view, param); picasso.load(post.url).fit().centerCrop().into(view); hasLongImage = true; continue; } if((space & rCol) == 0){ param.columnSpec = GridLayout.spec(1, 1); param.rowSpec = GridLayout.spec(0, 2); param.height = mGridLayout.getHeight(); param.width = mGridLayout.getWidth()/2; param.leftMargin = margin; space |= rCol; mGridLayout.addView(view, param); picasso.load(post.url).fit().centerCrop().into(view); hasLongImage = true; continue; } } //square or no space or unknown if((space & tl) == 0){ param.columnSpec = GridLayout.spec(0,1); param.rowSpec = GridLayout.spec(0,1); space |= tl; param.bottomMargin = margin; param.rightMargin = margin; }else if((space & tr) == 0) { param.columnSpec = GridLayout.spec(1,1); param.rowSpec = GridLayout.spec(0,1); space |= tr; param.bottomMargin = margin; param.leftMargin = margin; }else if((space & bl) == 0){ param.columnSpec = GridLayout.spec(0,1); param.rowSpec = GridLayout.spec(1,1); space |= bl; param.rightMargin = margin; param.topMargin = margin; }else if((space & br) == 0){ param.columnSpec = GridLayout.spec(1,1); param.rowSpec = GridLayout.spec(1,1); space |= br; param.leftMargin = margin; param.topMargin = margin; } param.height = mGridLayout.getHeight()/2; param.width = mGridLayout.getWidth()/2; mGridLayout.addView(view, param); picasso.load(post.url).fit().centerCrop().into(view); } } }

¿Por qué parece que esto se salta en el primer pase de representación para los artículos que no son visibles inicialmente?

EDITAR: Hice un poco de refactorización para poder volver a utilizar las vistas de imagen en lugar de eliminar / crear nuevas y he descubierto que las vistas que se agregan para esos elementos no reciben una devolución de llamada en curso. Todos los demás elementos obtienen la devolución de llamada onLayoutChange, y como antes, los elementos que no reciben la llamada inicialmente, la obtienen después de que me desplazo hacia arriba y me desplazo hacia abajo nuevamente. Ver:

view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { view.removeOnLayoutChangeListener(this); picasso.load(post.url).into(view); } });

Edición: 15 de noviembre

Aquí está el xml para el diseño del usuario

<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView android:id="@+id/album_card_view" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" card_view:cardCornerRadius="@dimen/feed_card_corner_radius" card_view:cardElevation="@dimen/cardview_default_elevation" card_view:cardMaxElevation="@dimen/cardview_default_elevation" card_view:cardUseCompatPadding="true" xmlns:autofit="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <android.support.percent.PercentRelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/percent_layout"> <GridLayout android:background="@color/white" android:id="@+id/preview_grid_layout" android:columnCount="2" android:rowCount="2" android:alignmentMode="alignBounds" android:layout_height="0dp" android:layout_width="0dp" app:layout_widthPercent="100%" app:layout_aspectRatio="100%"> </GridLayout> </android.support.percent.PercentRelativeLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="@dimen/card_padding_4dp" android:orientation="vertical"> <TextView android:id="@+id/album_title" android:layout_width="match_parent" android:layout_height="wrap_content" tools:text="Family Photos"/> </LinearLayout> </LinearLayout> </android.support.v7.widget.CardView>


Como intenta hacer una lista, quizás deba considerar utilizar la clase RecyclerView . De esta forma, podrá utilizar LayoutManager para diseñar sus imágenes más fácilmente. Esto podría ser mejor ya que su diseño no es una grilla estándar (que tiene columnas de ancho y altura constantes). Un ejemplo interesante a mirar para un LayoutManager personalizado se puede encontrar aquí .


Como el código completo no está allí, entonces puedo adivinar. Parece que cuando se desplaza por primera vez, el adaptador de reciclado crea las vistas antes de que la grilla tenga la oportunidad de crear y agregar vistas. Supongo que si usas otro adaptador, es decir, un adaptador de red para rellenar tus vistas de cuadrícula, debería funcionar bien.

Estoy entusiasmado de que está usando onScrollListener para su vista de reciclador para detectar el desplazamiento y luego cargar más cuadrículas que a su vez cargan más elementos de cuadrícula a través del adaptador de cuadrícula para cada cuadrícula.