I want to use the new Activity Transitions of Android Lollipop. But currently I am seeing very weird hickups during the animations. I hacked together the smallest sample I could think of.
This is what I did in a very short version:
- Enabled window content transitions in my
styles.xml
- Referenced a very simple
slide.xml
as exit transition in my style - Provided a
android:transitionName
for a shared element in both layouts - Called
ActivityOptions.makeSceneTransitionAnimation()
with that name and the view I want to share - Passed the resulting bundle to
startActivity()
This is the behavior I see (try 10x slower animation speed to see what I mean): Right before the slide animation slides down the views that are not shared, those views jump down a little. They actually move a little apart.
But: This only happens the second time I run that animation (and every time afterwards). The first pass looks just fine. And also this only happens if I want to share an element with the next activity. Everything works fine if I don't try to share an element.
Here is my code:
values/styles.xml
<resources>
<style name="AppTheme" parent="android:Theme.Material.Light">
<!-- enable window content transitions -->
<item name="android:windowContentTransitions">true</item>
<!-- specify exit transition -->
<item name="android:windowExitTransition">@transition/slide</item>
</style>
</resources>
transition/slide.xml
<slide />
Layout for the main activity
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#0000ff" />
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#00ff00" />
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#0000ff" />
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#00ff00" />
</LinearLayout>
<!-- the actual element I want to share -->
<View
android:id="@+id/view"
android:layout_width="56dp"
android:layout_height="56dp"
android:background="#ff0000"
android:elevation="8dp"
android:transitionName="view" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends Activity implements View.OnClickListener {
View mView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mView = findViewById(R.id.view);
mView.setOnClickListener(this);
}
@Override
public void onClick(View view) {
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, mView, "view");
Intent intent = new Intent(this, SecondaryActivity.class);
startActivity(intent, options.toBundle());
}
}
It is possible that you are hitting a bug in the transitions library that, for some reason, wasn't discovered until after L was locked down.
In the bug, you must have a reenter transition and a shared element reenter transition. The default reenter transition is the same as the exit transition for both.
If, during the return transition, the shared element is transferred back to the calling Activity while the views are still entering, you will see a hiccup when it interrupts the return call. With the slide and explode transitions, you will also see that the next time you exit, they will start from where the hiccup happened, so you get a nice double-wammy.
So you have a few options to work around this bug until MR1:
android:windowSharedElementReenterTransition
to@null
. Most of the time you don't need a shared element reenter transition because the called Activity will place the shared element in the right location for you.android:windowReenterTransition
to@null
)android:windowSharedElementReturnTransition
is large enough so that the calling Activity'swindowReenterTransition
finishes first. This can be tricky because it can depend on device state -- the calling Activity may have been removed from memory and need to be restarted.android:windowAllowReturnTransitionOverlap
tofalse
.