Material-Animations(二)--Shared elements between Activities

来源:互联网 发布:iphone相片导入mac 编辑:程序博客网 时间:2024/04/27 13:46

原文:https://github.com/lgvalle/Material-Animations

Activity间共享元素

Activity间共享元素的本质是有两个不同的View在不同的布局(Activity),然后通过某种方式把它们连起来,然后做动画。

Transition framework将会执行从一个View到另外一个View的过渡动画。

有一点需要注意的是:view不是从一个Activity 转移到另外一个Activity中,他们是完全独立的两个View
这里写图片描述

a)允许Window Content Transition

如果想实现Activity间共享元素,那么需要在appstyles.xml文件中配置。

values/styles.xml

<style name="MaterialAnimations" parent="@style/Theme.AppCompat.Light.NoActionBar">    ...    <item name="android:windowContentTransitions">true</item    ...</style>

同时在这里可以为整个app配置缺省的enter,exitshared 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>

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" />

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" />

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());    }});

经过三面几步,漂亮的过渡动画就完成了。
这里写图片描述

如上面所示,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>

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" />

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" />

c) 使用共享元素启动Fragment

FragmentB fragmentB = FragmentB.newInstance(sample);// Defines enter transition for all fragment viewsSlide slideTransition = new Slide(Gravity.RIGHT);slideTransition.setDuration(1000);sharedElementFragment2.setEnterTransition(slideTransition);// Defines enter transition only for shared elementChangeBounds 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();

最终的结果
这里写图片描述

允许重叠过渡

你可以定义进入(enter transitions)和退出(exit transition)的过渡动画是否互相重叠。
根据Android官方文档

如果设置为Ture,enter transition将会立即执行
如果设置为False,enter transition将等到exit transition完全执行完毕才开始执行

上面的设置对于FragmentActivity一样有效

FragmentB fragmentB = FragmentB.newInstance(sample);// Defines enter transition for all fragment viewsSlide slideTransition = new Slide(Gravity.RIGHT);slideTransition.setDuration(1000);sharedElementFragment2.setEnterTransition(slideTransition);// Defines enter transition only for shared elementChangeBounds changeBoundsTransition = TransitionInflater.from(this).inflateTransition(R.transition.change_bounds);fragmentB.setSharedElementEnterTransition(changeBoundsTransition);// Prevent transitions for overlappingfragmentB.setAllowEnterTransitionOverlap(overlap);fragmentB.setAllowReturnTransitionOverlap(overlap);getFragmentManager().beginTransaction()        .replace(R.id.content, fragmentB)        .addSharedElement(blueView, getString(R.string.blue_name))        .commit();

我们能很容易的发现两者的不同

允许覆盖 不允许覆盖 Fragment_2 出现在Fragment_1顶部 直到Fragment_1 消失,Fragment_2才出现 这里写图片描述 这里写图片描述