У меня возникают проблемы с одним из моих адаптеров. У меня есть выбор изображений, которые я показываю в сетке, как следующее:RecyclerView - внеэкранные объекты, пропускающие первый макет пропуска
Это хорошо работает, когда у меня есть один экран стоит пунктов, и все они показывают вверх штраф. Проблема возникает, когда есть больше элементов для прокрутки вниз. Первоначально, когда я прокручиваю вниз дальше элементы оказываются пустыми, то GridLayout
контейнеры там и код для отображения изображений получает бежать, но они не отображаются на экране, как показано здесь:
Если я прокручиваю обратно вверх, а затем прокрутите вниз снова, изображения появляются именно там, где они должны быть:
Похоже, мне нужно обновить макет или сказать рендерер что-то изменилось, но ничего я стараюсь не кажется делать что-либо. Я попытался позвонить requestLayout
и invalidate
, но он, похоже, не решает проблему. Я также зарегистрировал GlobalOnLayoutListener, но это ничуть не лучше.
Вот соответствующий код:
Это из моего 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();
}
});
}
Это метод я использую макет изображения. Это в основном выводит изображения в нерегулярную сетку, поэтому, если есть длинное или высокое изображение, это изображение будет пытаться заняться полной строкой или полным столбцом в зависимости от свободного места. Причина я установить ширину и высоту парам так Picasso не жалуется метода .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);
}
}
}
Почему это, кажется, чтобы пропустить на первый проход рендеринга для элементов, не видимых первоначально?
EDIT: Я немного переработал рефакторинг, чтобы повторно использовать образы изображений вместо удаления/создания новых и обнаружил, что представления, добавляемые для этих элементов, не получают обратного вызова onLayoutChange. Все остальные элементы получают обратный вызов onLayoutChange и, как и прежде, элементы, которые не получают вызов изначально, получают его после прокрутки вверх и прокрутки вниз. См:
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);
}
});
Edit: Nov. 15
Вот XML для viewholder макете
<?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>
Если кто-нибудь может подумать над лучшим заголовком для этого вопроса, не стесняйтесь его редактировать –
Каждый раз, когда вызывается 'onBindViewHolder', вы заменяете все изображения из' GridView'? Зачем? – rubenlop
Ну, может быть где-то от 1-4 изображений в макете для любого элемента, поэтому, когда предметы будут переработаны, это приведет к некоторому выступу. Я думаю, что я мог бы сохранить список ImageViews, а затем просто установить их на видимость, когда они будут переработаны, но производительность прокрутки была достаточно приличной, поэтому мне было меньше беспокоиться об этом, чем проблема рендеринга. –