英文原文 https://github.com/lgvalle/Material-Animations
这是GitHub上的一个开源项目( 点击传送门 ), 演示View的平移、缩放动画,activity进入和退出动画,界面间元素共享。
了解 Transition Framework
可以在activity之间跳转的时候添加动画
动画共享元素之间的转换活动
activity中布局元素的过渡动画。
Explode | Slide | Fade |
---|---|---|
实现这些效果可以通过xml方式或者在直接在类中实现,下面是Fade的实现方式。
### 说明:Fade
res/transition/slide_from_right
<?xml version = 1.0 encoding = "utf-8"?> <transitionSet xmls:android = "http://schemas.android.com/apk/res/android"> <slide duration = "500" slideEage = "left"/> </transitionSet>
2.如果直接用代码实现,可以如下实现
MainActivity
Slide slideTracition = newSlide(); slideTracition.setSlideEdge(Gravity.LEFT); slideTracition.setDuration(getResources().getInteger(R.integer.anim_duration_long));
MianActivity.onCreat();
设置MainActivty的进出动画代码如下
private void setupWindowAnimations() { Transition slideTracition = TransitionInflater.from(this).inflateTransition(R.transition.slide_from_left); getWindow().setEnterTransition(slideTracition); getWindow().setExitTransition(slideTracition); //getWindow().setReenterTransition(buildExitTransition()); }
返回和重新输入转换分别是Enter和Exit的反向动画。
如果未定义返回或重新输入,Android将按照你之前设定的默认的版本。但是如果你定义它们,你可以有不同的转换进入和退出活动。(如下图)
Visiable slide = new Slide(); slide.setDuraing(500); getWindow.setReturnTransition(slide); //别直接调用finish(); finshAfterTransition();
Without Return Transition | With Return Transition |
---|---|
需要在/res/style.xml添加
<item name="android:windowContentTransitions">true</item>
res/layout/activity
<ImageView android:id="@+id/square_blue" style="@style/MaterialAnimations.Icon.Big" android:src="@drawable/circle_24dp" android:transitionName="@string/square_blue_name" />
<TextView android:id="@+id/title" style="@style/MaterialAnimations.TextAppearance.Title.Invers" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical|start" android:text="@{sharedSample.name}" android:transitionName="@string/sample_blue_title" />
Intent intent = new Intent(activity,target); ActivityOptionCompat option = ActiviyoptionCampat.makeSceneTransitionAnimation(activity, new Pair<View, String>(viewHolder.binding.sampleIcon, activity.getString(R.string.square_blue_name)), new Pair<View, String>(viewHolder.binding.sampleName, activity.getString(R.string.sample_blue_title))); startActivity(intent,option.toBundle());
需要在/res/style.xml添加
<item name="android:windowContentTransitions">true</item>
之前的俩个步骤和Activity之间共享元素的没有太大差别。
private void addNextFragment(Sample sample, ImageView blue, boolean b) { SharedElementFragment2 elementFragment2 = SharedElementFragment2.newInstance(sample); Slide slide = new Slide(); slide.setDuration(getResources().getInteger(R.integer.anim_duration_medium)); slide.setSlideEdge(Gravity.RIGHT); ChangeBounds changeBounds = new ChangeBounds(); changeBounds.setDuration(getResources().getInteger(R.integer.anim_duration_medium)); elementFragment2.setEnterTransition(slide); elementFragment2.setAllowEnterTransitionOverlap(b); elementFragment2.setAllowReturnTransitionOverlap(b); elementFragment2.setSharedElementEnterTransition(changeBounds); getFragmentManager().beginTransaction().replace(R.id.sample2_content, elementFragment2).addToBackStack(null).addSharedElement(blue, getString(R.string.square_blue_name)).commit(); }
上面俩种方式都是运用于过度动画,那Transition FrameWork也可以被用做于改变布局中的某个特定的View,比如修改View的位置或者大小。我们需要确定想改变的结果即可。
TransitionManager.beginDelayedTransition(viewRoot);
ViewGroup.LayoutParams params = view.getLayoutParams(); params.witdh = 200; view.setlayoutParams(params);
ViewGroup.LayoutParams params = view.getLayoutParams(); params.gravity = Gravity.Left; view.setlayoutParams(params);
Size | Position |
---|---|
循环显示只是一个动画显示或隐藏一组UI元素。它可以自API21或以上使用。
那我们应该如何监听共享元素的动画结束的时刻。
private void setupEnterAnimations() { Transition transtion = TransitionInflater.from(this).inflateTransition(R.transition.changebounds_with_arcmotion); getWindow().setSharedElementEnterTransition(transtion); transtion.addListener(new Transition.TransitionListener() { @Override public void onTransitionEnd(Transition transition) { transition.removeListener(this); hideTarget(); animateRevealShow(toolbar); animateButtonIn(); } }); }
res/transition/changebounds_with_arcmotion.xml
<?xml version="1.0" encoding="utf-8"?> <transitionSet xmlns:android="http://schemas.android.com/apk/res/android" android:duration="@integer/anim_duration_long" android:interpolator="@android:interpolator/decelerate_cubic" > <changeBounds> <arcMotion android:maximumAngle="90" android:minimumHorizontalAngle="90" android:minimumVerticalAngle="0"/> </changeBounds> </transitionSet>
ToolBar Animation
private void animateRevealShow(View viewRoot) { int cx = (viewRoot.getLeft() + viewRoot.getRight()) / 2; int cy = (viewRoot.getTop() + viewRoot.getBottom()) / 2; int finalRadius = Math.max(viewRoot.getWidth(), viewRoot.getHeight()); Animator anim = ViewAnimationUtils.createCircularReveal(viewRoot, cx, cy, 0, finalRadius); viewRoot.setVisibility(View.VISIBLE); anim.setDuration(1000); anim.setInterpolator(new AccelerateInterpolator()); anim.start(); }
四个小球的浮现的动画
private void animateButtonIn() { for (int i = 0; i < bgViewGroup.getChildCount(); i++) { View child = bgViewGroup.getChildAt(i); child.animate() .setStartDelay(100 + i * DELAY) .setInterpolator(new AccelerateInterpolator()) .alpha(1) .scaleX(1) .scaleY(1); } }
红色小球的效果
res/transition/changebounds_with_arcmotion.xml
<?xml version="1.0" encoding="utf-8"?> <transitionSet xmlns:android="http://schemas.android.com/apk/res/android" android:duration="@integer/anim_duration_long" android:interpolator="@android:interpolator/decelerate_cubic" > <changeBounds> <arcMotion android:maximumAngle="90" android:minimumHorizontalAngle="90" android:minimumVerticalAngle="0"/> </changeBounds> </transitionSet>
点击红色小球时 执行 revealRed()
private void revealRed() { final ViewGroup.LayoutParams params = btnRed.getLayoutParams(); Transition transition = TransitionInflater.from(this).inflateTransition(R.transition.changebounds_with_arcmotion); transition.addListener(new Transition.TransitionListener() { @Override public void onTransitionStart(Transition transition) { } @Override public void onTransitionEnd(Transition transition) { animateRevealColor(bgViewGroup, R.color.sample_red); body.setText(R.string.reveal_body3); body.setTextColor(ContextCompat.getColor(RevealActivity.this, R.color.theme_red_background)); btnRed.setLayoutParams(params); } @Override public void onTransitionCancel(Transition transition) { } @Override public void onTransitionPause(Transition transition) { } @Override public void onTransitionResume(Transition transition) { } }); TransitionManager.beginDelayedTransition(bgViewGroup, transition); final RelativeLayout.LayoutParams relativeRarams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); relativeRarams.addRule(RelativeLayout.CENTER_IN_PARENT); btnRed.setLayoutParams(relativeRarams); } private void animateRevealColor(ViewGroup viewRoot, @ColorRes int color) { int cx = (viewRoot.getLeft() + viewRoot.getRight()) / 2; int cy = (viewRoot.getTop() + viewRoot.getBottom()) / 2; animateRevealColorFromCoordinates(viewRoot, color, cx, cy); } private Animator animateRevealColorFromCoordinates(ViewGroup root, @ColorRes int color, int cx, int cy) { int finalRadius = Math.max(root.getWidth(), root.getHeight()); final Animator animator = ViewAnimationUtils.createCircularReveal(root, cx, cy, 0, finalRadius); root.setBackgroundColor(ContextCompat.getColor(this, color)); animator.setDuration(getResources().getInteger(R.integer.anim_duration_long)); animator.setInterpolator(new AccelerateInterpolator()); animator.start(); return animator; }