Transition using the header image of CardView as it is

Introduction

It's been a long time, Zion. I've been developing an Android app for the first time in a while and I'm stuck, so I'd like to share a solution. Material Design has been revamped at Google I / O 2018, and the guide for Material.io has changed considerably.

Meanwhile, there was the following animation in Component Cards.

Cool ... I want to do it ...! I thought, but I was wondering how to implement the transition while keeping this image. I don't even know the name of the animation in the first place: sob: Google says

A card expands to fill the full screen using a parent-child transition. Expand the card to full screen using parent-child transitions.

No, I don't understand the meaning. I couldn't help it, so I found a name like that while searching for it myself.

It seems to be called ** Shared Element Transition **. Transitions with common elements, this is exactly: sunglasses:

So in this article, we will use this transition I would like to implement an animation like the image above.

: beginner: Sample code can be found on Github

Implementation

Preparation

I want to use Material Components, so add the latest support library.

build.gradle


dependencies {
    ...
    implementation 'com.android.support:design:28.0.0-alpha3'
    implementation 'com.android.support:appcompat-v7:28.0.0-alpha3'
}

Create the transition source Activity

Create an Activity that will be the transition source. This is the screen in the previous animation.

animation1

Use MaterialCardView to get as close as possible. I use LinerLayout because it's easy. (I think there is a better way to write it, so I'd appreciate it if you could give me a pull request or comment: no_mouth :)

<android.support.design.card.MaterialCardView
        android:id="@+id/user_cardView"
        android:layout_width="match_parent"
        android:layout_height="266dp"
        app:cardCornerRadius="4dp">


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <ImageView
                android:id="@+id/header_imageView"
                android:layout_width="match_parent"
                android:layout_height="194dp"
                android:scaleType="centerCrop"
                app:srcCompat="@drawable/header" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:layout_margin="16dp"
                android:orientation="horizontal">

                <ImageView
                    android:id="@+id/icon_imageView"
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:layout_marginRight="16dp"
                    android:layout_weight="1"
                    app:srcCompat="@drawable/icon" />

                <LinearLayout
                    android:layout_width="240dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:orientation="vertical">

                    <TextView
                        android:id="@+id/user_name_textView"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="@string/user_name"
                        android:textColor="@color/colorHeaderText"
                        android:textSize="20dp"
                        android:textStyle="bold" />

                    <TextView
                        android:id="@+id/user_profession_textView"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:text="@string/user_profession"
                        android:textColor="@color/colorSubheadText"
                        android:textSize="14dp" />
                </LinearLayout>

            </LinearLayout>
        </LinearLayout>
</android.support.design.card.MaterialCardView>

The actual screen looks like this.

MainActivity

Create the activity of the transition destination

Next, create an Activity that will be the transition destination. This screen.

animation2

I made it based on the layout I mentioned earlier. The implemented screen looks like this.

UserActivity

Set common elements

Set common elements to share between the transition source and the transition destination. The specification method is specified by transitionName in the layout file. transitionName must be common to both the transition source and the transition destination.

This time, it is the transition from MainActivity to UserActivity. The four elements in common are: Specify the same transitionName for each.

By specifying in this way, it can be treated as a common element.

For example, for the user's header image, specify:

activity_main.xml


...

<ImageView
    android:id="@+id/header_imageView"
    ...
    android:transitionName="userHeader"
    ...
 />

...

Specify the same for the header image of the transition destination.

activity_user.xml


<ImageView
    android:id="@+id/user_header_imageView"
    ...
    android:transitionName="userHeader"
    ...
 />

Now you are ready to treat each part of the transition source and destination as a common element. Next, I will write the process of transitioning based on this setting.

Transition Activity

Get common elements in the transition source Activity.

MainActivity.java


userHeader = (ImageView) findViewById(R.id.header_imageView);
userIcon = (ImageView) findViewById(R.id.icon_imageView);
userName = (TextView) findViewById(R.id.name_textView);
userProfession = (TextView) findViewById(R.id.profession_textView);

Use ʻOnClickListener in CardViewto write the processing when clicked. First, create a pair from the common element andtransitionName`. For the header image, create a pair as follows.

Pair.create((View) userHeader, "userHeader")

Set the created pair as an option at the time of transition.

ActivityOptions options = ActivityOptions.
                              makeSceneTransitionAnimation(MainActivity.this,
                                  Pair.create((View) userHeader, "userHeader")
                              );

By giving this option to startActivity as Bundle You can do ** Shared Element Transition **!

Intent intent = new Intent(MainActivity.this, UserActivity.class);
                startActivity(intent, options.toBundle());

The final process when clicking on a card is as follows:

MainAcitivty.java


...

@Override
public void onClick(View view) {
    ActivityOptions options = ActivityOptions.
                                  makeSceneTransitionAnimation(MainActivity.this,
                                      Pair.create((View) userHeader, "userHeader"),
                                      Pair.create((View) userIcon, "userIcon"),
                                      Pair.create((View) userName, "userName"),
                                      Pair.create((View) userProfession, "userProfession")
                                  );

    Intent intent = new Intent(MainActivity.this, UserActivity.class);
    startActivity(intent, options.toBundle());
}

Summary

The final animation looks like this! There are many ways to use it. The sample code is on Github, so if you have any suggestions, please leave a comment or issue: bow_tone1: shion1118/CardTransition - Github

Please read to the end Thank you: wave_tone1:

Recommended Posts

Transition using the header image of CardView as it is
It was the Title of NavigationItem instead of the header of TableView
Is the version of Elasticsearch you are using compatible with Java 11?
Which is faster, size or 0, as the argument of List # toArray?
What is it? ~ 3 types of "no" ~
How to switch the display of the header menu for each transition page
Get the type of an array element to determine if it is an array
Since the image of the lock screen of Windows 10 is beautiful, I wanted to make it a slide show of wallpaper
Display text on top of the image
Try using || instead of the ternary operator
About the version of Docker's Node.js image
What is testing? ・ About the importance of testing
Test the integrity of the aggregation using ArchUnit ②
What is the data structure of ActionText?
Test the integrity of the aggregation using ArchUnit ③
[Java] Is it unnecessary to check "identity" in the implementation of the equals () method?
Retrieve the first day of week in current locale (what day of the week is it today?)
Is it mainstream not to write the closing tag of <P> tag in Javadoc?
A quick note on using jshell with the official Docker image of the JDK