Glitch when animating nested views in a shared ele

2020-02-25 23:04发布

问题:

I've been messing around with the new APIs in Android 5.0 and have been trying to figure out whether or not it is possible to animate both a ViewGroup and one of its children separately as shared elements during an Activity transition.

The screenshots below gives a simplified example of what I am trying to achieve:

In the first activity, the dark gray box is a ViewGroup centered in the screen and the red box is its child View (the layout XML code I am using can be found here). When the user clicks on the dark gray box, the dark gray box should gradually scale up to fill the second activity's background. At the same time, the red box should gradually scale and reposition itself in the top left corner of the second activity.

The Activity & Animation Code

The Activity code I am using to perform the transition is simple:

/** FirstActivity.java */
public class FirstActivity extends Activity implements View.OnClickListener {
    private View mOuterBox, mInnerBox;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
        getWindow().setSharedElementExitTransition(new ChangeBounds());
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);
        mOuterBox = findViewById(R.id.outer_box);
        mInnerBox = findViewById(R.id.inner_box);
        mOuterBox.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        Pair<View, String> outerBox = Pair.create(mOuterBox, mOuterBox.getTransitionName());
        Pair<View, String> innerBox = Pair.create(mInnerBox, mInnerBox.getTransitionName());
        Bundle bundle = ActivityOptions.makeSceneTransitionAnimation(this, outerBox, innerBox).toBundle();
        startActivity(new Intent(this, SecondActivity.class), bundle);
    }
}

/** SecondActivity.java */
public class SecondActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
        getWindow().setSharedElementEnterTransition(new ChangeBounds());
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
    }
}

The Problem

When I click on the dark gray box in the first activity, the shared element transition begins and the dark gray box scales up nicely to fill the second activity's background. However, the red box does not appear to animate at all. As soon as the transition starts, the red box abruptly resizes and positions itself in its final location within the second activity before the gray box has even finished animating.

My Question

Is it possible to animate both a ViewGroup and one/some/all of its children views independently as shared elements in an Activity transition? If so, what am I doing wrong and what can I do to ensure the children views are animated as well?

If you had trouble following my descriptions, the full source code for this example project is available on GitHub and a runnable APK is available for download here (you'll need a physical device or emulator running Android 5.0 to run the APK).

回答1:

Yes, you can transition a group and its contents separately. But you just found a bug that will be fixed in L MR1.

It appears that this is not well supported in L. I recommend that you make the shared elements siblings in the second Activity:

<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/dark_gray"
        android:transitionName="outer_box"/>

    <RelativeLayout
        android:id="@+id/outer_box"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <View
            android:id="@+id/inner_box"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="50dp"
            android:layout_marginTop="50dp"
            android:background="@color/red"
            android:transitionName="inner_box" />
    </RelativeLayout>
</FrameLayout>