How to properly scale TextView using Shared Element Transition like in Google I/O 2016 talk?

114 Views Asked by At

I tried to make a transition between the two activities using a shared TextView as shown in Google I/O 2016, but it works strangely since the text doesn't seem to fit into some container and its edges get cut off when the animation plays, though nothing should interfere with its scaling. I was putting it in other containers and tried different combinations, but the result was exactly the same. That said, when I go back from the second activity to the first, everything works as it should. A class for scaling text, TextResize.java, has also been added to the project and included in shared element transition set between two activities.

How can I fix incorrect text scaling animation when navigating to second activity?

Video of how it works now (in slow motion): link

Main Activity:

public class MainActivity extends AppCompatActivity {

    private TextView textView;
    public static final String SHARED_TEXT_SIZE = "textSize";
    public static final String PADDING = "textPadding";
    public static final String TEXT_COLOR = "textColor";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.textView1);

        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Intent sharedIntent = new Intent(MainActivity.this, SharedActivity.class);

                sharedIntent.putExtra(SHARED_TEXT_SIZE, textView.getTextSize());
                sharedIntent.putExtra(PADDING,
                        new Rect(textView.getPaddingLeft(),
                                textView.getPaddingTop(),
                                textView.getPaddingRight(),
                                textView.getPaddingBottom()));
                sharedIntent.putExtra(TEXT_COLOR, textView.getCurrentTextColor());

                Pair[] pairs = new Pair[1];
                pairs[0] = new Pair<View, String>(textView, "textTransition");

                ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, pairs);

                startActivity(sharedIntent, activityOptions.toBundle());
            }
        });
    }
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView1"
        android:layout_alignParentTop="true"
        android:transitionName="textTransition"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_marginStart="20dp"
        android:text="Hello World!" />

</RelativeLayout>

Second Activity:

public class SharedActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_shared);

        final TextView textView = findViewById(R.id.textView1);

        setEnterSharedElementCallback(new SharedElementCallback() {

            private float targetTextSize;
            private ColorStateList targetTextColors;
            private Rect targetPadding;

            @Override
            public void onSharedElementStart(List<String> sharedElementNames, List<View> sharedElements, List<View> sharedElementSnapshots) {
                super.onSharedElementStart(sharedElementNames, sharedElements, sharedElementSnapshots);

                targetTextSize = textView.getTextSize();
                targetTextColors = textView.getTextColors();
                targetPadding = new Rect(textView.getPaddingLeft(),
                        textView.getPaddingTop(),
                        textView.getPaddingRight(),
                        textView.getPaddingBottom());

                textView.setTextColor(getIntent().getIntExtra(MainActivity.TEXT_COLOR, Color.BLACK));
                float textSize = getIntent().getFloatExtra(MainActivity.SHARED_TEXT_SIZE, targetTextSize);
                textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
                Rect padding = getIntent().getParcelableExtra(MainActivity.PADDING);
                assert padding != null;
                textView.setPadding(padding.left, padding.top, padding.right, padding.bottom);
            }

            @Override
            public void onSharedElementEnd(List<String> sharedElementNames, List<View> sharedElements, List<View> sharedElementSnapshots) {
                super.onSharedElementEnd(sharedElementNames, sharedElements, sharedElementSnapshots);

                textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, targetTextSize);
                if (targetTextColors != null) {
                    textView.setTextColor(targetTextColors);
                }
                if (targetPadding != null) {
                    textView.setPadding(targetPadding.left, targetPadding.top,
                            targetPadding.right, targetPadding.bottom);
                }
            }
        });
    }
}

activity_shared.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SharedActivity">

    <TextView
        android:id="@+id/textView1"
        android:transitionName="textTransition"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:layout_centerHorizontal="true"
        android:layout_centerInParent="true"
        android:textSize="36sp" />

</RelativeLayout>

styles.xml:

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>

        <item name="android:windowSharedElementEnterTransition">
            @transition/shared_main_detail
        </item>
    </style>

</resources>

shared_main_detail.xml:

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <transitionSet>
        <targets>
            <target android:targetId="@id/textView1" />
        </targets>
        <transition class="com.example.sharedanimation.TextResize" />
        <changeBounds />
    </transitionSet>
    <recolor>
        <targets>
            <target android:targetId="@android:id/statusBarBackground" />
            <target android:targetId="@android:id/navigationBarBackground" />
        </targets>
    </recolor>
</transitionSet>
0

There are 0 best solutions below