Material Design 应用中的操作行为转换透过通用元素之间的移动和转换提供不同状态之间的视觉连接。 您可为进入、退出转换以及操作行为之间的共享元素转换指定定制动画。
活动过渡提供了两种过渡类型:
1,输入(进入):进入一个活动的效果
2,退出(退出):退出一个活动的效果
而这每种类型又分为普通和共享元素的过渡。
普通转型
爆炸 explode:从场景的中心移入或移出
幻灯 slide:从场景的边缘移入或移出
褪色 fade:调整透明度产生渐变效果
共享元素转换共享元素转换
它的作用就是共享两个acitivity中共同的元素,在Android 5.0下支持如下效果:
changeBounds - 改变目标视图的布局边界(针对的是视图)
changeClipBounds - 裁剪目标视图边界(针对的是视图的剪切区域(setClipBound(Rect rect)中的矩形)。如果没有设置则没有动画效果)
changeTransform - 改变目标视图的缩放比例和旋转角度
changeImageTransform - 改变目标图片的大小和缩放比例(这里是专指ImageView)的尺寸,位置以及ScaleType,并创建相应动画)
活动动画过渡使用两种方式,两个步骤
步骤一:设置允许使用的过渡,并且设置过渡。
一,使用xml。
1.在定义您从材料主题继承的风格时,使用 android:windowContentTransitions 属性启用窗口内容转换。您也可在您的风格定义中指定进入、退出以及共享元素转换:
<style name="BaseAppTheme" parent="android:Theme.Material">
<!-- enable window content transitions -->
<item name="android:windowContentTransitions">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>
2.定义过渡动画,如change_image_transform
<!-- res/transition/change_image_transform.xml -->
<!-- (see also Shared Transitions below) -->
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<changeImageTransform/>
</transitionSet>
二,在代码中启用窗口内容转换,设置过渡。
// inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
// set an transition,选择如下
Window.setEnterTransition():普通过渡的进入效果
Window.setExitTransition():普通过渡的退出效果
Window.setSharedElementEnterTransition():共享元素过渡的进入效果
Window.setSharedElementExitTransition():共享元素过渡的退出效果
具体使用逻辑可以参照下文的介绍
步骤二,启动活动。
当你已经设置了允许使用过渡并设置了过渡动画,你就可以通过ActivityOptions.makeSceneTransitionAnimation()方法启动一个新的活动来激活这个过渡:
1.启用普通的转变:
startActivity(intent,ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
2.启用共享元素的过渡:
1).启动共享元素转换和普通的转换稍有不同,在所有需要共享视图的活动中,使用android:transitionName属性对于需要共享的元素分配一个通用的名字。
// get the element that receives the click event
final View imgContainerView = findViewById(R.id.img_container);
// get the common element for the transition in this activity
final View androidRobotView = findViewById(R.id.image_small);
// define a click listener
imgContainerView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(this, Activity2.class);
// create the transition animation - the images in the layouts
// of both activities are defined with android:transitionName="robot"
ActivityOptions options = ActivityOptions
.makeSceneTransitionAnimation(this, androidRobotView, "robot");
// start the new activity
startActivity(intent, options.toBundle());
}
});
对于在您的代码中生成的共享动态视图,请使用 View.setTransitionName() 方法在两个操作行为中指定一个通用元素名称。
2).如果要在两个拥有多个共享元素的操作行为之间安排场景转换动画,请以 android:transitionName 属性(或在两个操作行为中使用 View.setTransitionName() 方法)定义共享元素,并以下列方式创建一个 ActivityOptions 对象:
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
Pair.create(view1, "agreedName1"),
Pair.create(view2, “agreedName2"));
ActivityOptionsCompat activityOptionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(this
,new Pair<View, String>(shared_image,"shared_image_")
,new Pair<View, String>(shared_text,"shared_text_"));
startActivity(intent,activityOptionsCompat.toBundle());
注意:上面是两种写法,导入的Pair的包也不同,注意区分。
如果不想使用transition可以设置选项bundle为null。当需要结束当前Activity并回退这个动画时调用Activity.finishAfterTransition()方法,而非 Activity.finish()
具体使用分析
过渡框架核心就是根据场景(场景,下文解释)的不同自动生成动画通常,主要是通过以下几个方法开启动画。
TransitionManager.go()
beginDelayedTransition()
setEnterTransition()/setSharedElementEnterTransition()
一、TransitionManager.go(Scene scene)一直都是根据xml文件创造起始场景和结束场景。
Scene:表示应用场景时View层次结构中各种属性的值的集合。可以将场景配置为在应用时自动运行转场,这将为场景更改期间发生的各种属性更改生效。
通俗的解释就是这个类存储着一个根视图下的各种视图的属性。由通常getSceneForLayout (ViewGroup sceneRoot,int layoutId,Context context)电子杂志实例。
sceneRoot场景发生改变和动画执行的位置
layoutId即上文所说的根视图
具体使用实例及效果可以参考文章末尾的gitHub工程。
AutoTransition
如果TransitionManager.go(scene)不指定动画,则默认动画是AutoTransition类。它其实是一个动画集合,查看源码可知其实是动画集合中添加了淡入淡出和ChangeBounds类。
private void init() {
setOrdering(ORDERING_SEQUENTIAL);
addTransition(new Fade(Fade.OUT)).
addTransition(new ChangeBounds()).
addTransition(new Fade(Fade.IN));
}
说到动画集合,动画其实类不仅可以通过类似new ChangeBounds()方法创建,也可以通过XML文件创建。且如果对于动画集合,XML方式可能会更加方便。首先要在res创建一个transition的目录,目录下创建对应的xml。
res / transition / changebounds_and_fade.xml:
<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<changeBounds />
<fade />
</transitionSet>
代码中调用:
sets=TransitionInflater.from(this).inflateTransition(R.transition.changebounds_and_fade);
二,beginDelayedTransition()
它通过代码改变属性,然后通过之前介绍的ChangeBounds等类别分析开始场景和结束场景不同来创建动画,可以参照项目中的实例。
Activity界面切换动画
界面切换有两种,一种是不带共享元素的内容转换一种是带有共享元素的共享元素转换。可以参照上面官方文档的介绍。
界面切换动画是建立在能见度的改变的基础上的,所以界面的进出动画(4中)中的参数一般传的是Fade,Slide,Explode类的实例(因为这三个类是通过分析能见度不同创建动画的)。
上面四种动画的执行时机。
// A到B界面,A界面先触发ExitTransition动画。
getWindow().setExitTransition(transition),默认为null;
// A到B界面,A界面触发ExitTransition后,B再触发EnterTransition,getWindow().setEnterTransition(transition),不设置默认为Fade;
//返回键B到A界面, B先触发界面的ReturnTransition动画。getWindow().setReturnTransition(transition),不设置默认为EnterTransition;
//返回键B到A界面,B界面触发ReturnTransition后,A 界面触发ReenterTransition。getWindow().setReenterTransition(transition),不设置默认为ExitTransition;
当然也可以在主题中设置
<item name="android:windowEnterTransition">@transition/slide_and_fade</item>
<item name=“android:windowReturnTransition">@transition/return_slide</item>
确定到这里为止既可以运行活动之间的切换动画了。
但是你会发现,在界面切换的时候,A退出时,过了一小会,B就进入了,(真是过分,不给阿完全展示ExitTransition)如果你是想等甲完全退出后乙再进入可以通过设置setAllowEnterTransitionOverlap(false)(默认是真),同样可以在XML中设置:
<item name="android:windowAllowEnterTransitionOverlap">false</item>
<item name=“android:windowAllowReturnTransitionOverlap">false</item>
活动的切换动画针对的是整个界面的视图的可视性,而有没有什么方法能让过渡框架只关注某一个视图或者不关注某个视图呢。当然,transition.addTarget()状语从句:transition.excludeTarget()可以分别实现上述功能。
方便的是也可以在XML设置该属性,那么我们现在要做的是将状态栏。排除掉,可以在slide.xml这样写:
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<slide android:duration="1000">
<targets >
<!--表示除了状态栏-->
<target android:excludeId="@android:id/statusBarBackground"/>
<!--表示只针对状态栏-->
<!--<target android:targetId="@android:id/statusBarBackground"/>--> </targets>
</slide>
</transitionSet>
补充说明:
//A到B界面,A先执行共享元素的setSharedElementExitTransition的退出效果。。
getWindow().setSharedElementExitTransition(transition):不设置默认transition/move
//A到B界面,A触发setSharedElementExitTransition后,B触发setSharedElementEnterTransition进入动画。
getWindow().setSharedElementEnterTransition(transition):不设置默认transition/move
其实共享元素过渡原理和内容转换类似都是根据始终场景状态的不同创建动画。
不同的是内容转换是通过改变视图的可见性来改变场景状态从而进一步创建动画,而共享元素过渡是分析AB界面共享视图的尺寸,位置,样式的不同创建动画化的。所以前者通常设置淡入等过渡后者通常设置ChangeBoundschangeClipBounds、changTransform、changImageTransform/等过渡。
运行效果,可以下载gitHub上的demo:https://github.com/xianjuren/AndroidMaterialDesignAnimation