Search code examples
androidandroid-transitionsshared-element-transitionandroid-mvvm

Activity shared element transition using MVVM architecture


I'm learning MVVM pattern and have an issue right now. I have an activity A with imageview on it, and an activity B with same imageview but in another place and bigger. When in activity A i click on imageview, i want to start activity B and imageview should be shared element to achieve what i want with nice animation.

Using databinding i handle click on imageview in my view model:

<de.hdodenhof.circleimageview.CircleImageView
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    android:onClick="@{(v) -> user.onAvatarClick(v)}"
                    android:scaleType="centerCrop"
                    android:src="@{user.photoUrl}"
                    android:transitionName="@string/avatar_transition" />

And in my viewmodel i should wrote something like this:

public void onAvatarClick(View view) {
    Intent intent = new Intent(context, AvatarActivity.class);
    ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, view, view.getTransitionName());
    context.startActivity(intent, options.toBundle());
}

But, the problem is that my viewmodel knows nothing about activity. And i have no idea how to do what i want.

One possible solution is create interface with method like startActivityB(View view) and implement it in activity and set it to field for example viewModelListener. And then i can wrote something like:

public void onAvatarClick(View view) {
    viewModelListener.startActivityB(view);
}

But in this case my viewmodel will have reference to view, and it broke MVVM main idea, right?

So, what the right way to start new activity with shared element using MVVM architecture?


Solution

  • This can be done through Live Data in Android. As you can observe the changes in live data and navigate to other activity accordingly.

    Example here

    In your xml file where you clicked the button

    android:onClick="@{()->homeActivityViewModel.openNewActivity()}"
    

    In your viewModel class

    private final MutableLiveData<Boolean> openNewScreen = new MutableLiveData<>();
    
     //function that is binded to xml
    public void openNewActivity() {
        openNewScreen.setValue(true);
    }
    
    public MutableLiveData<Boolean> getNewScreen() {
        return openNewScreen;
    }
    

    In your activity

     homeActivityViewModel.getNewScreen().observe(this,
                start -> {
                    if (start) {
                        Intent intent = new Intent(this, NewActivity.class);
                        startActivity(intent);
                    } });