本文内容概要
Tween Animation(补间动画)
补间动画,在视图容器内执行一系列变换:缩放,位移,透明度,旋转
- TranslateAnimation 位置移动动画
- ScaleAnimation 大小缩放动画
- RotateAnimation 旋转动画
- AlphaAnimation 透明度动画
- AnimationSet 可以组合多个动画的集合一起执行
使用xml创建动画
定义单个动画:test_scale.xml
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/linear_interpolator"
android:fromXScale="1.0"
android:toXScale="3.0"
android:fromYScale="1.0"
android:toYScale="3.0"
<!-- 缩放的轴点,50%相对自身的位置 -->
android:pivotX="50%"
android:pivotY="50%"
android:duration="700" />
// AnimationUtils.loadAnimation() 加载动画
Animation scaleAnim = AnimationUtils.loadAnimation(this, R.anim.test_scale);
// View.startAnimation() 启动动画
mView.startAnimation(scaleAnim)
定义动画集合AnimationSet
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:shareInterpolator="@android:anim/linear_interpolator">
<!-- pivotX pivotY 可以为百分比,也可以为具体像素值 -->
<rotate
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="90" />
<!-- fromXDelta,fromYDelta,toXDelta,toYDelta 都是相对View于初始位置的x,y的距离;delta就是初中数学中的德尔塔Δ,一般指相对值-->
<translate
android:duration="1000"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="200"
android:toYDelta="200" />
<!-- alpha值:0为全透明 1为不透明 -->
<alpha
android:fromAlpha="0"
android:toAlpha="1" />
<!-- scale值为相对自身缩放比例,1为默认初始View的大小,1.2就是1.2倍 -->
<scale
android:fromXScale="1"
android:fromYScale="1"
android:toXScale="1.2"
android:toYScale="1.2" />
</set>
使用Java代码创建动画
AnimationSet animationSet = new AnimationSet(false);
// 新建位移动画
TranslateAnimation translateAnimation = new TranslateAnimation(0, 100, 0, 100);
// 新建旋转动画
RotateAnimation rotateAnimation = new RotateAnimation(0, 90, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
// 添加动画到集合
animationSet.addAnimation(rotateAnimation);
animationSet.addAnimation(translateAnimation);
// 设置集合动画时长
animationSet.setDuration(500);
animationSet.setFillAfter(false);
// 开启动画
mView.startAnimation(animationSet);
注意事项
- xml中set标签或者AnimationSet对象的属性对他所包含的所有动画都有效,比如在set标签设置了duration,内部的动画再设置duration是无效的
- set标签(AnimationSet)repeatMode和repeatCount无效
- rotate 和 translate先后顺序需注意,通常把rotate放前面
- 如果AnimationSet中同时包含scale和translate,那么scale会影响translate的x,y的值
Frame Animation(帧动画)
帧动画,顾名思义就是一帧一帧播放视图形成动画效果;对应动画类有两个:AnimationDrawable 和 AnimatedVectorDrawable
AnimationDrawable
AnimationDrawable继承自DrawableContainer,而DrawableContainer继承自Drawable,在定义xml的时候应放在drawable目录下面
这里说个题外话,其实android的资源文件放那个目录(res/下合法的任意目录)都可以,实际资源对象初始化是根据xml文件的内容而定,只是无规矩不成方圆,按约束放置资源文件便于管理维护
在xml定义AnimationDrawable
<!-- 定义:animation_drawable.xml -->
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">
<!-- oneshot属性为true表示只执行一次,false表示无限循环; duration表示当前帧显示的时间 -->
<item android:drawable="@drawable/frame1" android:duration="100"/>
<item android:drawable="@drawable/frame2" android:duration="100"/>
<item android:drawable="@drawable/frame3" android:duration="100"/>
</animation-list>
<!-- 在View中引用 animation_drawable.xml -->
<View
id="@+id/animation_view"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@drawable/animation_drawable" />
// 获取View的Background,开启或停止动画
View mView = findViewById(R.id.animation_view);
AnimationDrawable drawable = (AnimationDrawable) mView.getBackground();
drawable.start();
drawable.stop();
java实现AnimationDrawable
AnimationDrawable animationDrawable = new AnimationDrawable();
animationDrawable.addFrame(getResources().getDrawable(R.drawable.frame1), 100);
animationDrawable.addFrame(getResources().getDrawable(R.drawable.frame2), 100);
animationDrawable.addFrame(getResources().getDrawable(R.drawable.frame3), 100);
view.setBackgroundDrawable(animationDrawable);
// 开始动画
animationDrawable.start();
// 停止动画
animationDrawable.stop();
注意事项
AnimationDrawable.start()方法不要在onCreate里面调用,因为这时AnimationDrawable可能还没有attach到Window上,如果需要在Activity打开就立刻播放动画,可以在:onStart() 或者 onWindowFocusChanged方法里面调用该方法
AnimatedVectorDrawable
待完善...
Property Animation API >= 11 (属性动画)
属性动画提供了一系列强大的功能,它可以用在任何对象上!简单的说就是:在动画时间里内通过回调方法不断更新View的属性从而实现动画效果!属性动画包含:ValueAnimator,ObjectAnimator,TimeAnimator,AnimatorSet
可通过Animator可修改View的常见属性如下
name | desc |
---|---|
translationX translationY | 距离View初始位置的x轴,y轴的距离,默认为0 |
rotationX rotationY | rotationX 2D旋转,rotationY 3D旋转 |
scaleX scaleY | x,y轴方向上的缩放 |
x y | x = mLeft + translationX,y = mTop + translationY |
alpha | 透明度 |
属性动画原理
下面两个图是将View在40ms内向右移动40像素,每隔单位时间将view的x属性更新一下从而实现动画效果
- 匀速移动(x的值跟时间t成直线函数关系:x = a * t, a为常量)
- 加速移动(注意观察x值的变化)
-
具体实现流程:都是通过设置AnimatorUpdateListener监听,在回调方法中更新View的属性
ValueAnimator
用Java创建Animator
// 从0到100 再从100到2 再从2到300 再从300到500
ValueAnimator animator = ValueAnimator.ofFloat(0, 100, 2, 300, 500);
// 设置插值器,如过不设置,默认插值器为:AccelerateDecelerateInterpolator
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = animation.getAnimatedValue()
// use value update view property
view.setTranslationX(value)
}
});
animator.setDuration(5000);
animator.start();
ValueAnimator提供了以下方法
- (API21) ValueAnimator.ofArgb(int... values) : 传入几个颜色值,可以实现颜色渐变切换
- ValueAnimator.ofFloat(float... values) : float值根据时间变化而变化
- ValueAnimator.ofInt(int... values) : int值根据时间变化而变化
ObjectAnimator
ObjectAnimator继承自ValueAnimator,把上面ValueAnimation.AnimatorUpdateListener.onAnimationUpdate()方法里面需要干的事情封装好了,只需要将需要动画的View和对应属性传递给ObjectAnimator,它会自动完成属性更新,从而实现动画!
比如下面代码修改:textView的translationX值
ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f);
animation.setDuration(1000);
animation.start();
这里textView为需要修改属性的对象,translationX为被修改的属性,这里需要textView对象拥有名称为set+TranslationX的方法,方法名的set后面第一个字符必须为大写,方法输入参数也应该为float,上面例子对应的set方法为:setTranslationX(float translationX);至于方法的访问域private还是public都无所谓,反正都是通过反射调用!
AnimatorSet
AnimatorSet跟AnimationSet不同,AnimationSet用于将多个动画合并一起执行,而AnimatorSet用于管理多个Animator执行的顺序。它可以并行执行,也可以设定依赖关系按一定顺序执行
* 并行执行:play(anim1).with(anim2) 或者 playTogether(Animator... items)
* 先后执行:playSequentially(Animator... items)
* 依赖执行:play(anim1).before(anim2).after(anim3).with(anim4)
通过play,widh,before,after,playSequentially,playTogether的组合可以创建各种执行顺序,形成不同的动画效果
示例如下
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
animatorSet.start();
PropertyValuesHolder 和 ViewPropertyAnimator
一个ObjectAnimator只能修改一个属性,如果需要同时修改多个属性需要创建多个ObjectAnimator,再通过AnimatorSet.playTogether(Animator... items)执行!通过PropertyValuesHolder可以只创建一个ObjectAnimator来实现
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 300f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 200f);
ObjectAnimator.ofPropertyValuesHolder(textView, pvhX, pvhY)
.setDuration(3000)
.start();
使用ViewPropertyAnimator就更简单了
// 这里我们没有手动调用start()方法,他会在合适时机自动执行
textView.animate().x(300f).y(400).setDuration(3000);
Keyframe
关键帧,有时你需要在特定时间点指定特定的状态,比如用1000ms将View向右移动300px,但是在100ms时移动到150px,200ms时移动到200px,最终1000ms时移动到300px
//创建关键帧
Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(0.1f, 150f);
Keyframe kf2 = Keyframe.ofFloat(0.2f, 200f);
Keyframe kf3 = Keyframe.ofFloat(1.0f, 300f);
//创建动画
PropertyValuesHolder pvhTranslationX = PropertyValuesHolder.ofKeyframe("translationX", kf0, kf1, kf2, kf3);
ObjectAnimator transAnim = ObjectAnimator.ofPropertyValuesHolder(textView, pvhTranslationX);
transAnim.setInterpolator(new LinearInterpolator());
transAnim.setDuration(5000);
transAnim.start();
Keyframe.ofFloat(float, float)方法,第一个参数是整个动画时间的分子数,取值为0-1;0表示起始时间点,1表示结束时间点,第二个参数表示在第一个参数时间点上Animator对应的Value值
PropertyValuesHolder保存了动画要操作的属性和关键帧数据,用于创建ObjectAnimator
StateListAnimator
StateListAnimator可以在View状态改变时启动动画,比如在Button按下时,让Button放大一点,透明度变为80%;当按钮恢复时,大小和透明度恢复原状。
res/xml/animate_scale.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- the pressed state; increase x and y size to 120%, alpha to 0.7 -->
<item android:state_pressed="true">
<set>
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="alpha"
android:valueTo="0.8f"
android:valueType="floatType" />
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="scaleX"
android:valueTo="1.2"
android:valueType="floatType" />
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="scaleY"
android:valueTo="1.2"
android:valueType="floatType" />
</set>
</item>
<!-- the default, non-pressed state; set x and y size to 100%, alpha to 1.0 -->
<item android:state_pressed="false">
<set>
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="alpha"
android:valueTo="1.0f"
android:valueType="floatType" />
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="scaleX"
android:valueTo="1"
android:valueType="floatType" />
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="scaleY"
android:valueTo="1"
android:valueType="floatType" />
</set>
</item>
</selector>
通过stateListAnimator属性引用animate_scale.xml
<Button
android:layout_width="match_parent"
android:layout_height="50dp"
android:stateListAnimator="@xml/animate_scale"
android:text="Login" />
或者使用AnimatorInflater.loadStateListAnimator()和View.setStateListAnimator()方法使用StateListAnimator
TimeAnimator(API Level 16)
提供了一个简单的回调机制,通过 TimeAnimator.TimeListener,在动画的每一帧处通知你。它没有持续时间,插值器或是对象值设定。回调监听器为每一帧动画接受信息,包括总运行时间和从前一帧到现在的运行时间
相关方法
- setTimeListener(TimeAnimator.TimeListener listener) 设置监听器
使用xml定义Animator
在Android 3.1(API 12)及以上可以通过xml定义animator,存放在res/animator目录下
如下:property_animator.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially">
<!-- ordering执行顺序,together或sequentially,默认为together-->
<!-- 这里需注意valueType不要搞错了,可选值有:floatType,intType,colorType-->
<set>
<objectAnimator
android:duration="500"
android:propertyName="x"
android:valueTo="400"
android:valueType="floatType" />
<objectAnimator
android:duration="500"
android:propertyName="y"
android:valueTo="300"
android:valueType="floatType" />
</set>
<objectAnimator
android:duration="500"
android:propertyName="alpha"
android:valueTo="0.3f"
android:valueType="floatType" />
</set>
通过AnimatorInflater加载Animator
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(mContext, R.animator.property_animator);
set.setTarget(textView);
set.start();
ValueAnimator也可以用xml定义
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueType="floatType"
android:valueFrom="0f"
android:valueTo="-100f" />
在Java中使用
ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this,R.animator.animator);
xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator updatedAnimation) {
float animatedValue = (float) updatedAnimation.getAnimatedValue();
textView.setTranslationX(animatedValue);
}
});
xmlAnimator.start();
Dynamic Animation(动态动画)
DynamicAnimation是由support包提供的动画工具,使用需添加如下依赖
implementation 'com.android.support:support-dynamic-animation:28.0.0'
// or
implementation 'androidx.dynamicanimation:dynamicanimation:1.0.0'
DynamicAnimation有两个实现类:
- FlingAnimation 用于速度手势动画
- SpringAnimation 弹性动画
由于比较简单,直接上代码
FlingAnimation
LinearLayout linearLayout = findViewById(R.id.layout);
// linearLayout为目标动画对象,DynamicAnimation.SCROLL_X为scrollX属性
FlingAnimation fling = new FlingAnimation(linearLayout, DynamicAnimation.SCROLL_X);
// 可操作的最小单位
fling.setMinimumVisibleChange(DynamicAnimation.MIN_VISIBLE_CHANGE_PIXELS);
// 滑动起始速度
fling.setStartVelocity(4000)
// 最小距离
.setMinValue(0)
// 最大距离
.setMaxValue(1000)
// 滑动摩擦系数,相当于加速度
.setFriction(1.1f)
.start();
SpringAnimation
View ball = findViewById(R.id.ball);
// 构造函数最后一个参数是最终的位置
SpringAnimation spring = new SpringAnimation(ball, DynamicAnimation.X, 0);
// 设置起始速度
spring.setStartVelocity(3000);
// 设置弹性的强度,参考SpringForce对象内部定义的常量
spring.getSpring().setStiffness(SpringForce.STIFFNESS_HIGH);
// 设置弹性比例,参考SpringForce对象内部定义的常量
spring.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY);
// 设置起始位置,如果不设置就为View初始位置
spring.setStartValue(500);
spring.start();
Scene Animation (API Level 19)
场景动画又可以称作为过渡动画,就是在同一个Layout容器中切换不同布局文件时的过渡动画,比如淡入淡出效果,如果两个布局文件里面包含相同id的View,系统会把他们的位置,大小,旋转,透明度等属性关联起来,形成过渡的动画效果!
先看个示例
在使用场景动画之前,我们先看几个类:
Scene
一个scene包含了场景切换的根容器ViewGroup,以及一个对应场景的ViewGroup
Transition
Transition包含了动画的相关信息,他主要负责2件事情:一是获取始末场景的属性的值(比如:位置,大小,透明度等);二是根据始末场景属性值计算并播放动画。主要的实现类有:
- ChangeBounds 负责View的位置属性
- ChangeTransform 负责缩放和旋转属性
- ChangeClipBounds 负责mClipBounds属性
- ChangeScroll 负责scroll属性
- Fade 负责透明度
- Slide 负责添加或者移除时,滑入添加,滑出删除效果
- ChangeImageTransform 负责ImageView的matrix属性
- TransitionSet 多个Transition集合,可以一起执行:ORDERING_TOGETHER,也可以串行执行:ORDERING_SEQUENTIAL
TransitionManager
TransitionManager则包含了一系列Transition,并且在场景切换时执行这些Transition。以下两个方法实现了场景切换:
- TransitionManager.go(Scene scene)
- TransitionManager.go(Scene scene, Transition transition)
TransitionManager.go(Scene scene)方法,内部自定义了AutoTransition对象,它是TransitionSet的子类,内部添加了Fade和ChangeBounds两个过渡动画,并且是串行执行的!
TransitionManager.go(Scene scene, Transition transition)方法则可以传入自定义的Transition,自定义需要的动画效果,以及串行还是并行执行!
Layout,Scene,Transition,TransitionManager之间的关系图
使用方法
综上几个类的说明,基本使用方法也比较明确了
- 第一步:定义Scene
- 第二步:定义Transition
- 第三部:调用TransitionManager的go方法切换场景
定义Scene
mSceneRoot = (ViewGroup) view.findViewById(R.id.scene_root);
mScene1 = new Scene(mSceneRoot, (ViewGroup) mSceneRoot.findViewById(R.id.container));
// 通过layout xml文件创建scene
mScene2 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene2, getActivity());
mScene3 = Scene.getSceneForLayout(mSceneRoot, R.layout.scene3, getActivity());
定义Transition
public class MyTransition extends TransitionSet {
public MyTransition() {
init();
}
public MyTransition(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// 串行执行
setOrdering(ORDERING_SEQUENTIAL);
// 添加淡出效果
Fade fadeOut = new Fade(Fade.OUT);
fadeOut.setDuration(1000);
addTransition(fadeOut);
// 位置迁移动画
ChangeBounds changeBounds = new ChangeBounds();
changeBounds.setDuration(1000);
// 缩放,旋转动画
ChangeTransform transform = new ChangeTransform();
transform.setDuration(1000);
// 将位置迁移和缩放旋转放到一个set里面,并行执行
TransitionSet set = new TransitionSet();
set.setOrdering(TransitionSet.ORDERING_TOGETHER);
set.addTransition(changeBounds);
set.addTransition(transform);
addTransition(set);
// 添加淡入效果
Fade fadeIn = new Fade(Fade.IN);
fadeIn.setDuration(1000);
addTransition(fadeIn);
}
}
切换场景
// 使用默认AutoTransition
TransitionManager.go(mScene2)
TransitionManager.go(mScene3)
// 使用自定义Transition
TransitionManager.go(mScene2, new MyTransition())
TransitionManager.go(mScene3, new MyTransition())
xml也可以定义场景动画,放在res/transition目录下面
scene3_transition_manager.xml
<?xml version="1.0" encoding="utf-8"?>
<transitionManager xmlns:android="http://schemas.android.com/apk/res/android">
<transition
android:toScene="@layout/scene3"
android:transition="@transition/changebounds_fadein_together"/>
</transitionManager>
changebounds_fadein_together.xml
<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 位置信息动画 -->
<changeBounds
android:duration="1000"/>
<fade android:fadingMode="fade_in"
android:duration="300">
<targets>
<!-- 这里可以自定义添加需要动画的View,对应Java方法Transition.addTarget(View target)-->
<target android:targetId="@id/transition_title" />
</targets>
</fade>
</transitionSet>
在java中调用
mTransitionManagerForScene3 = TransitionInflater.from(getActivity())
.inflateTransitionManager(R.transition.scene3_transition_manager, mSceneRoot);
mTransitionManagerForScene3.transitionTo(mScene3)
Layout Animation (API Level 11)
在ViewGroup添加或者移除子View时的动画效果
使用很简单在xml中将android:animateLayoutChanges属性设置为true即可
<LinearLayout android:id="@+id/container"
android:animateLayoutChanges="true"
...
/>
也可以通过代码设置Transition
viewGroup.setLayoutTransition(new LayoutTransition())
LayoutTransition提供了一些set方法可以修改一些动画信息,比如:
- setDuration(int transitionType, long duration)
- setInterpolator(int transitionType, TimeInterpolator interpolator)
- setAnimator(int transitionType, Animator animator)
- .......
上面这些方法有个共同的参数transitionType,有以下5个值:
- APPEARIN:元素在容器中显现时需要动画显示。
- CHANGE_APPEARING:由于容器中要显现一个新的元素,其它元素的变化需要动画显示。
- DISAPPEARING:元素在容器中消失时需要动画显示。
- CHANGE_DISAPPEARING:由于容器中某个元素要消失,其它元素的变化需要动画显示。
- CHANGING:当元素本身某个属性发生变化,但元素并没有添加和移除时需要动画的显示
添加删除动画效果
Activity Animation (API Level 21)
Activity切换动画跟上面的场景动画其实差不多,只不过场景动画是在一个视图容器中切换View,Activity动画是在页面切换时播放动画。
Activity支持页面切换整体动画效果:
- explode 爆破进入
- slide 滑入滑出
- fade 淡入淡出
同时也支持两个Activity中相关联的View的过渡动画,关联View支持以下属性:
- changeBounds 位置属性
- changeClipBounds ClipBounds属性
- changeTransform 缩放和旋转属性
- changeImageTransform ImageView的matrix属性
在xml中定义Activity过渡动画
<style name="BaseAppTheme" parent="android:Theme.Material">
<!-- enable window content transitions -->
<item name="android:windowActivityTransitions">true</item>
<!-- 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/change_image_transform</item>
<item name="android:windowSharedElementExitTransition">
@transition/change_image_transform</item>
</style>
change_image_transform.xml
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<changeImageTransform/>
</transitionSet>
也可以通过Java代码设置
- getWindow().setEnterTransition(Transition transition);
- getWindow().setEnterTransition(Transition transition);
在两个Activity中创建View关联动画
FirstActivity.java 中将
// 通过makeSceneTransitionAnimation方法创建动画,将需要关联动画的View和一个TransitionName关联起来,
// 同时在第二个Activity中通过ViewCompat.setTransitionName(View view, String transitionName)也将动画名和View关联起来
ActivityOptionsCompat activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(this,
new Pair<View, String>(view.findViewById(R.id.imageview_item), DetailActivity.VIEW_NAME_HEADER_IMAGE),
new Pair<View, String>(view.findViewById(R.id.textview_name), DetailActivity.VIEW_NAME_HEADER_TITLE));
ActivityCompat.startActivity(this, intent, activityOptions.toBundle());
DetailActivity.java
public class DetailActivity extends Activity {
public static final String VIEW_NAME_HEADER_IMAGE = "detail:header:image";
public static final String VIEW_NAME_HEADER_TITLE = "detail:header:title";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.details);
mHeaderImageView = (ImageView) findViewById(R.id.imageview_item);
mHeaderTitle = (TextView) findViewById(R.id.textview_title);
// 将view和TransitionName绑定
ViewCompat.setTransitionName(mHeaderImageView, VIEW_NAME_HEADER_IMAGE);
ViewCompat.setTransitionName(mHeaderTitle, VIEW_NAME_HEADER_TITLE);
}
}