3

I am using androidx navigation component. In FragmentA, I have a recycler view with cards. These cards contain an image an a like button. When the users likes the content, the like button asset changes. This card content is a separate layout which is included in the RecyclerViews.ViewHolder layout:

<MaterialCardView>
    <include layout="@layout/item_main_content_layout" />
</MaterialCardView>

and the item_layout included above:

    <merge>
        <LinearLayout
            android:id="@+id/content"
            android:transitionName="content">
            <ImageView
                android:id="@+id/image"/>
            <ImageView
                android:id="@+id/like"/>
        </LinearLayout>
    </merge>

During binding view holder in adapter I dynamically update the transitionName with unique id. FragmentB has included the same layout and on view creation I update the transition name with the item being passed on. When navigating from FragmentA -> FragmentB by clicking on a item the shared transition works as expected. When I pop back stack it falls back to its original position in the list as expected.

The problem As said earlier. When I like/dislike content, the asset of the like button changes. This asset in the like ImageView is preserved when I open FragmentB. But when I change the state, so I change the asset of the like button in FragmentB and pop back stack, the transition happens but the button asset is switched back to the starting asset in FragmentA. How can I retain the src drawable in shared element when popping back stack?

parohy
  • 2,070
  • 2
  • 22
  • 38

2 Answers2

2

I have forgot to mention that FragmentA is MVI and FragmentB is MVVM. This means that FragmentA is rendered based on a view state I am reducing in its presenter. The adapter receiving the data is not tightly coupled with the fragment so it doesn't know about the data change. I have added an extra event to my presenter to update the view state when some update happens on the item in the DB. When user resumes FragmentA, it renders view state. ViewState now contains the updated item and I handle that case accordingly by passing the updated item to the adapter (similar when passing new data). Now the data of the both ViewHolders are same and when going back from FragmentB -> FragmentA my like state is persisted.

parohy
  • 2,070
  • 2
  • 22
  • 38
0

Had a similar problem yesterday, but with the like button being on the toolbar. I used a static array list in the main activity, with each like button adding the component's ID to the array and the dislike removing that ID from the said array. So I handle the "like" pressings as such:

    case R.id.action_favorite:
                pressed = !pressed;
                // user pressed the heart icon
                if(pressed)
                {
                    item.setIcon(R.drawable.liked);
                    MainActivity.favs.add(ID);
                }
                else if(!pressed)
                {
                    item.setIcon(R.drawable.unliked);
                    MainActivity.favs.remove(Integer.valueOf(ID));
                }
                return true;

At the beginning of rendering each activity (a component that can be liked or unliked), I checked if the component ID is in that static array as such:

if(!MainActivity.favs.isEmpty())
        {
            if (MainActivity.favs.contains(ID))
            {
                pressed = true;
            }
        }

So that way the liked component activity is always resumed with the proper "liked" icon. Hope this helps in any way...

Sylum
  • 1
  • So if I understand it correctly, you are updating the views when you resume your `MainActivity`? My `ViewModel` is receiving the update inside of its rx callback but it understandably does not update the views, because they are on the background and no longer observing `ViewModel`. Me thinking out loud, seems like when I resume I would need to update the `RecyclerView` ? OnResume/OnResult I think updating the item on the position it was open and notifying item change should do the trick ? I would really love to avoid such static param passing. – parohy Jul 09 '20 at 07:09
  • Yeah, I guess if you would've wanted to avoid static params in my case, you could utilize the onPause and onResume functions. – Sylum Jul 10 '20 at 17:27