Activity间共享元素
Activity间共享元素的本质是有两个不同的View
在不同的布局(Activity
),然后通过某种方式把它们连起来,然后做动画。
Transition framework
将会执行从一个View
到另外一个View
的过渡动画。
有一点需要注意的是:view
不是从一个Activity
转移到另外一个Activity
中,他们是完全独立的两个View
a)允许Window Content Transition
如果想实现Activity
间共享元素,那么需要在app
的styles.xml
文件中配置。
values/styles.xml
<style name="MaterialAnimations" parent="@style/Theme.AppCompat.Light.NoActionBar">
...
<item name="android:windowContentTransitions">true</item
...
</style>
- 1
- 2
- 3
- 4
- 5
同时在这里可以为整个app
配置缺省的enter
,exit
和shared element transitions
<style name="MaterialAnimations" parent="@style/Theme.AppCompat.Light.NoActionBar">
...
<!-- specify enter and exit transitions -->
<item name="android:windowEnterTransition">@transition/explode</item>
<item name="android:windowExitTransition">@transition/explode</item>
<!-- specify shared element transitions -->
<item name="android:windowSharedElementEnterTransition">@transition/changebounds</item>
<item name="android:windowSharedElementExitTransition">@transition/changebounds</item>
...
</style>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
(自我补充)重点:@transition/changebounds的实现:
内容如下:
<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<changeBounds android:interpolator="@android:interpolator/accelerate_decelerate"
/>
</transitionSet>
b)定义一个相同的过渡名字(transition name
)
实现Activity
间共享元素,需要给源View
和目标View
设置相同的 android:transitionName
,他们的其他的属性可以不同,但唯独android:transitionName
必须相同。
layout/activity_a.xml
<ImageView
android:id="@+id/small_blue_icon"
style="@style/MaterialAnimations.Icon.Small"
android:src="@drawable/circle"
android:transitionName="@string/blue_name" />
- 1
- 2
- 3
- 4
- 5
layout/activity_b.xml
<ImageView
android:id="@+id/big_blue_icon"
style="@style/MaterialAnimations.Icon.Big"
android:src="@drawable/circle"
android:transitionName="@string/blue_name" />
- 1
- 2
- 3
- 4
- 5
c) 使用共享元素启动Activity
使用ActivityOptions.makeSceneTransitionAnimation()
方法定义共享元素源View
和过渡的名字transitionName
MainActivity.java
blueIconImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this, SharedElementActivity.class);
View sharedView = blueIconImageView;
String transitionName = getString(R.string.blue_name);
ActivityOptions transitionActivityOptions = ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, sharedView, transitionName);
startActivity(i, transitionActivityOptions.toBundle());
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
经过三面几步,漂亮的过渡动画就完成了。
如上面所示,Transition framework
创建并执行动画,而这些动画使我们感到错觉,认为这个View
是从一个Activity
一边改变形状一边移动到另外一个Activity
。
Fragment间共享元素
Fragment
间共享元素和Activity
间共享元素非常相像,步骤a)和步骤b)一样,只是步骤c)改变。
a)允许Window Content Transition
values/styles.xml
<style name="MaterialAnimations" parent="@style/Theme.AppCompat.Light.NoActionBar">
...
<item name="android:windowContentTransitions">true</item>
...
</style>
- 1
- 2
- 3
- 4
- 5
b)定义一个相同的过渡名字(transition name
)
layout/fragment_a.xml
<ImageView
android:id="@+id/small_blue_icon"
style="@style/MaterialAnimations.Icon.Small"
android:src="@drawable/circle"
android:transitionName="@string/blue_name" />
- 1
- 2
- 3
- 4
- 5
layout/fragment_b.xml
<ImageView
android:id="@+id/big_blue_icon"
style="@style/MaterialAnimations.Icon.Big"
android:src="@drawable/circle"
android:transitionName="@string/blue_name" />
- 1
- 2
- 3
- 4
- 5
c) 使用共享元素启动Fragment
FragmentB fragmentB = FragmentB.newInstance(sample);
// Defines enter transition for all fragment views
Slide slideTransition = new Slide(Gravity.RIGHT);
slideTransition.setDuration(1000);
sharedElementFragment2.setEnterTransition(slideTransition);
// Defines enter transition only for shared element
ChangeBounds changeBoundsTransition = TransitionInflater.from(this).inflateTransition(R.transition.change_bounds);
fragmentB.setSharedElementEnterTransition(changeBoundsTransition);
getFragmentManager().beginTransaction()
.replace(R.id.content, fragmentB)
.addSharedElement(blueView, getString(R.string.blue_name))
.commit();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
最终的结果
允许重叠过渡
(补充)activity1退出的时候有两种情况
1.退出时同时执行activity2的进入
2.在activity1完全退出之后再执行activity2的进入
你可以定义进入(enter transitions
)和退出(exit transition
)的过渡动画是否互相重叠。
Android
官方文档
如果设置为
Ture
,enter transition
将会立即执行
如果设置为False
,enter transition
将等到exit transition
完全执行完毕才开始执行
上面的设置对于Fragment
和Activity
一样有效
FragmentB fragmentB = FragmentB.newInstance(sample);
// Defines enter transition for all fragment views
Slide slideTransition = new Slide(Gravity.RIGHT);
slideTransition.setDuration(1000);
sharedElementFragment2.setEnterTransition(slideTransition);
// Defines enter transition only for shared element
ChangeBounds changeBoundsTransition = TransitionInflater.from(this).inflateTransition(R.transition.change_bounds);
fragmentB.setSharedElementEnterTransition(changeBoundsTransition);
// Prevent transitions for overlapping
fragmentB.setAllowEnterTransitionOverlap(overlap);
fragmentB.setAllowReturnTransitionOverlap(overlap);
getFragmentManager().beginTransaction()
.replace(R.id.content, fragmentB)
.addSharedElement(blueView, getString(R.string.blue_name))
.commit();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
我们能很容易的发现两者的不同
允许覆盖 | 不允许覆盖 |
---|---|
Fragment_2 出现在Fragment_1 顶部 | 直到Fragment_1 消失,Fragment_2 才出现 |
![]() | ![]() |