Using SharedElement Activity transitions with a custom View
Asked Answered
C

2

12

I am working on a proof-of-concept where I have a few custom views in a TableLayout. When one of the Views is clicked I want to animate the view expanding into a new Activity. The effect I want to achieve is similar to what is seen here.

From my research, it seems the way to do this is with shared element Transitions. However, I can't get it to work correctly and I am wondering if it is because I am using my own custom View.

Specifically, the fades are happening, but the scaling and translating motions are not. Check the GIF below to see where I am. In the example I click the upper left circle, which I want to transform to the full circle in the new activity. The issue can also be seen when the back button is pressed.

enter image description here

I believe it is incorrect because the View must be drawn, but is there a way to customize my View further to make this work? All of the examples I have found of this type of transition have consisted of ImageViews, Buttons, and TextViews.

Below is the relevant source. My custom view is large and doesn't contain any special code, just overrides onDraw() and onMeasure().

MainActivity.java

package com.rscottcarson.circleschedulertest;

import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Intent;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Toast;
public class MainActivity extends Activity {

    private View view1;

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

        view1 = findViewById(R.id.circle1);

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

                Intent intent = new Intent(MainActivity.this, DetailActivity.class);
                // create the transition animation - the images in the layouts
                // of both activities are defined with android:transitionName="profile"
                ActivityOptions options = ActivityOptions
                        .makeSceneTransitionAnimation(MainActivity.this, view1, "profile");
                // start the new activity
                startActivity(intent, options.toBundle());
            }
        });

    }
}

DetailActivity.java

package com.rscottcarson.circleschedulertest;

import android.app.Activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class DetailActivity extends Activity {

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

    }
}

change_image_trans.xml

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <changeTransform />
</transitionSet>

styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
        <item name="android:windowActivityTransitions">true</item>
        <item name="android:windowContentTransitions">true</item>

        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>


        <!-- specify shared element transitions -->
        <item name="android:windowSharedElementEnterTransition">
            @transition/change_image_trans</item>
        <!-- specify shared element transitions -->
        <item name="android:windowSharedElementExitTransition">
            @transition/change_image_trans</item>
    </style>

</resources>
Conrado answered 11/1, 2017 at 23:11 Comment(0)
A
5

Just try with postponeEnterTransition() and startPostponedEnterTransition() in your DetailActivity

postponeEnterTransition() used to temporarily delay the transition until the shared elements have been properly measured and laid out.

startPostponedEnterTransition() Schedules the shared element transition to be started immediately after the shared element has been measured and laid out within the activity's view hierarchy.

DetailActivity.java

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

private void scheduleStartPostponedTransition(final View sharedElement) {
    sharedElement.getViewTreeObserver().addOnPreDrawListener(
        new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                sharedElement.getViewTreeObserver().removeOnPreDrawListener(this);
                startPostponedEnterTransition();
                return true;
            }
        });
}
Avisavitaminosis answered 18/1, 2017 at 18:42 Comment(0)
L
-1

I don't think that your problem is that you have a custom view... I always make those transitions with my custom views and they work ok.

I can see that this code:

ActivityOptions options = ActivityOptions
                        .makeSceneTransitionAnimation(MainActivity.this, view1, "profile");
                // start the new activity 
                startActivity(intent, options.toBundle());

Does't do what you want.

Here is what you need to do:

First, create your xml with the transition:

First Activity

<YouCustomView
     android:id="@+id/someId"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:transitionName="@string/someTransition">

Second Activity:

<YouCustomView
         android:id="@+id/someOtherId"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:transitionName="@string/someTransition">

Second, when you you start your second activity, do it like this:

        ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(
    this, new Pair<>(findViewById(R.id.someId), getString(R.string.someTransition))

startActivity(intent, activityOptions.toBundle());

You forgot to add the Pair with the View and the name of the transition. Add that and your transition will work just fine. The fact that your View is a custom view doesn't change the animation.

Happy coding!

Lavern answered 25/1, 2017 at 16:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.