4

Я знаю, что этот вопрос похож на других на StackOverflow, но это касается того, что происходит после изменения ориентации.Как предотвратить переупорядочение элементов в StaggeredGridLayoutManager после изменения ориентации?

У меня есть работа с панелью инструментов и RecyclerView. Я использую StaggeredGridLayoutManager с вертикальной ориентацией и 3 столбца для заполнения RecyclerView. Макет элемента - это LinearLayout, содержащий ImageView и TextView.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:layout_margin="@dimen/grid_item_margin" 
android:orientation="vertical"> 

<ImageView 
    android:id="@+id/image" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:scaleType="centerCrop" /> 

<TextView 
    android:id="@+id/text" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:paddingBottom="2dp" 
    android:paddingTop="2dp" /> 
</LinearLayout> 

Изображения загружаются из Интернета. Я знаю размеры изображения перед привязкой ViewHolders. Так что я установить высоту изображения в onBindViewHolder, чтобы предотвратить элемент переупорядочения и загрузить изображение с помощью Пикассо:

@Override 
public void onBindViewHolder(ViewHolder holder, int position) { 
    ViewGroup.LayoutParams lp = holder.imageView.getLayoutParams(); 
    lp.height = imageInfos.get(position).imageHeight; 
    holder.imageView.setLayoutParams(lp); 

    mPicasso.load(url) 
     .noFade() 
     .into(holder.imageView); // imageView scaleType=centerCrop 
} 

Скажем, у меня есть 50 пунктов в моем адаптере. Я в портретном режиме и прокручиваю 20 предметов. Затем я перехожу в альбомный режим. Теперь я создаю новый StaggeredGridLayoutManager с 4 столбцами, поэтому еще один, чем в портретном режиме. Я пересчитать высоту изображения, чтобы соответствовать новой целевой ширине и установить сохраненное состояние на макете, как так:

ArrayList<ImageInfo> imageInfos = savedInstanceState 
    .getParcelableArrayList(IMG_INFOS_KEY); 
setNewImgTargetDimensions(imageInfos, columns); 
mAdapter = new ImageGridAdapter(mPicasso, imageInfos); 
mRecyclerView.setAdapter(mAdapter); 
mRecyclerView.setLayoutManager(layoutMgr); 
Parcelable sglmState = savedInstanceState 
    .getParcelable(LAYOUT_MGR_STATE_KEY); 
mRecyclerView.getLayoutManager() 
    .onRestoreInstanceState(sglmState); 

Сетка автоматически прокручивается в сложенном положение, которое желательно. Теперь я прокручиваю вверх. Из-за новых размеров изображения «пробел над прокрученной позицией» не может быть полностью заполнен изображениями. Таким образом, элементы получаются переупорядоченными, но большую часть времени в верхней части сетки по-прежнему находится более или менее большой разрыв (см. Ссылки на скриншоты внизу). Это худшее, когда я бросаюсь на вершину. Так есть ли способ предотвратить переупорядочение и пробелы в этом случае?

portrait mode показывает экран, только что загруженный в первый раз.

landscape mode показывает экран при прокрутке после изменения ориентации. Изображение слева почти прозрачно из-за пользовательского угасания в анимации, я думаю. Я удалил это из кода примера, чтобы уменьшить его.

Edit:

Я просто понял, что все элементы выравниваются по верхней части экрана, после изменения ориентации. Хотя это выглядит красиво, я бы предпочел, чтобы выравнивание на самом верху ресайклера было правильным.

+0

Вы решили эту проблему? У меня такая же проблема. Я загружаю много изображений из внутреннего хранилища с помощью Glide. Затем я прокручиваю вниз до центра представления или до конца, поворачиваю устройство, и когда я прокручиваю вверх, я вижу пробелы. Вместо изображений в 3 столбцах я вижу только один столбец (2 пустые). Любая помощь в этом? – rdkit

ответ

2

Итак, я придумал обходной путь. Короче говоря, когда сетка прокручивается до самого верха, я установил стратегию разрыва в GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS, чтобы элементы были перегруппированы.

Вот более подробное описание. Когда вызывается onActivityCreated с сохраненным состоянием экземпляра, я проверяю, изменилась ли ориентация. Если он есть, я устанавливаю флаг. В обратном вызове onScrollStateChanged я проверяю, является ли одно из первых видимых позиций позиций 0. Это то, что я считаю «прокрученным вверх». Поэтому, если пользователь прокручивается вверх, а ориентация меняется, я вызываю layoutMgr.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS); и layoutMgr.invalidateSpanAssignments(); (и сбросьте флаг).

Смежные вопросы