Martichou
Martichou

Reputation: 133

Recyclerview don't retain my scrolling position

I'm building an app with a StaggeredGridLayout. But once I open a details fragment (handled by Navigation Library) and then come back to the main fragment, my scrolled position is lost.

I've already tried to save instance of the recyclerview to apply it back once we reach onResume, but this technique break my sharedelement transition.

XML of the recyclerview

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/linear_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recentNotesList"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingStart="20dp"
    android:paddingEnd="20dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"/>

<ProgressBar
    android:id="@+id/loading_ui"
    android:layout_width="75dp"
    android:layout_height="75dp"
    app:bindIsGone="@{thisVm.hasNotes}"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<androidx.appcompat.widget.AppCompatImageView
    android:id="@+id/nonethinking"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:paddingStart="20dp"
    android:paddingEnd="20dp"
    android:scaleType="fitCenter"
    android:src="@drawable/thinking"
    android:visibility="gone"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

HomeMainFragment

val lm = StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL)
lm.gapStrategy = StaggeredGridLayoutManager.GAP_HANDLING_NONE
binding.recentNotesList.layoutManager = lm

Expected results: When opening an item -> sharedelement transition (this one work) When closing the opened item -> sharedelement transition

Actual results: When closing the opened item -> sharedelement transition work only if the image visible when the user hadn't scrolled the recyclerview yet.

I think it has something to do with the scrolled position retaining process. But I wasn't able to make this thing working.

Upvotes: 2

Views: 175

Answers (2)

Martichou
Martichou

Reputation: 133

I fixed it by using ConstraintLayout in my recyclerview item's. Just set the aspect ratio to a default of 1:1 and then programatically update this aspect ratio with the aspect ratio of you app in the onBindViewHolder.

Like this:

XML of the item's RV

<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/parentContsraint"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/show_image_note"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:scaleType="centerCrop"
        android:contentDescription="@string/image_of_your_dedicated_note"
        android:transitionName="@{String.valueOf(note.id)}"
        app:imageFromFile="@{note.image}"
        app:srcCompat="@drawable/pool"
        app:layout_constraintDimensionRatio="1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

And in your Adapter

with(set) {
    val posterRatio = String.format("%d:%d", resource.width, resource.height)
    clone(binding.parentContsraint)
    setDimensionRatio(binding.showImageNote.id, posterRatio)
    applyTo(binding.parentContsraint)
}

Upvotes: 1

Muhammad Haroon
Muhammad Haroon

Reputation: 210

Hi please try this when your are setting your adapater to recyclerview .

val lastFirstVisiblePositon= recyclerview.layoutmanager.findFirstCompletelyVisibleItemPosition();
recyclerview.layoutmanager.scrollToPositionWithOffset(lastFirstVisiblePosition, 0);
listdapter.notifyDataSetChanged();
hRecyclerView_OpenOrderListing.setAdapter(listdapter);

Upvotes: 0

Related Questions