I know this question sounds similar to the others in StackOverflow, but this is about what happens after the orientation changes.
I have an Activity with a toolbar and a RecyclerView. I use a StaggeredGridLayoutManager with a vertical orientation and 3 columns to populate a RecyclerView. The element layout is a LinearLayout containing an ImageView and a 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>
Images are downloaded from the Internet. I know the size of the image before snapping ViewHolders. Therefore, I set the height of the image in onBindViewHolder to prevent reordering the elements and loading the image through Picasso:
@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);
Say I have 50 elements in my adapter. I am in portrait mode and scroll through 20 items. Then I go into landscape mode. Now I am creating a new StaggeredGridLayoutManager with 4 columns, so one more than in portrait mode. I recalculate the height of the image according to the new target width and set the saved state on the layout as follows:
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);
The grid automatically scrolls to the desired saved position. Now I scroll up. Due to the new size of the image, the โspace over the scroll positionโ cannot be completely filled with images. Thus, the elements are reordered, but most of the time in the upper part of the grid there is still a more or less large gap (see links to screenshots below). This is the worst when I rush to the top. So, is there a way to prevent reordering and spaces in this case?
Portrait mode shows the screen on first boot.
landscape mode shows the screen when scrolling after changing orientation. The image on the left is almost transparent due to custom fading in the animation, I think. I removed this from the sample code to reduce it.
Edit:
I just realized that all the elements are aligned at the top of the screen after changing the orientation. Although this looks beautiful, I would prefer the alignment at the very top of the recycler window to be correct.