写点什么

『Android 技能篇』优雅的转场动画之 Transition,kotlin 安卓开发教程视频

用户头像
Android架构
关注
发布于: 11 小时前

当调用 view.setClipBounds() 时会触发转场效果:


ChangeClipBounds transition = new ChangeClipBounds();


transition.setInterpolator(new BounceInterpolator());


TransitionManager.beginDelayedTransition(mRoot, transition);


int width = view2.getWidth();


int height = view2.getHeight();


int gap = 140;


Rect rect = new Rect(0, gap, width, height - gap);


if (rect.equals(view2.getClipBounds())) {


view2.setClipBounds(null);


} else {


view2.setClipBounds(rect);


}


最终效果:


[](

)ChangeScroll


当调用 view.scrollTo() 会触发转场效果:


ChangeScroll transition = new ChangeScroll();


transition.setInterpolator(new AnticipateOvershootInterpolator());


TransitionManager.beginDelayedTransition(mRoot, transition);


if (view1.getScrollX() == -100 && view1.getScrollY() == -100) {


view1.scrollTo(0, 0);


} else {


view1.scrollTo(-100, -100);


}


最终效果:


[](

)ChangeTransform


这个就厉害了,View 的 translation、scale 和 rotation 发生改变时都会触发:


ChangeTransform transition = new ChangeTransform();


transition.setInterpolator(new OvershootInterpolator());


TransitionManager.beginDelayedTransition(mRoot, transition);


if (view1.getTranslationX() == 100 && view1.getTranslationY() == 100) {


view1.setTranslationX(0);


view1.setTranslationY(0);


} else {


view1.setTranslationX(100);


view1.setTranslationY(100);


}


if (view2.getRotationX() == 30f) {


view2.setRotationX(0);


} else {


v


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


iew2.setRotationX(30);


}


if (view3.getRotationY() == 30f) {


view3.setRotationY(0);


} else {


view3.setRotationY(30);


}


if (view4.getScaleX() == 0.5f && view4.getScaleY() == 0.5f) {


view4.setScaleX(1f);


view4.setScaleY(1f);


} else {


view4.setScaleX(0.5f);


view4.setScaleY(0.5f);


}


最终效果:



[](


)自定义 Transition



[](

)介绍


其实 Transition 的原理很简单,大致的逻辑如下:


1、记录当前状态的属性值,比如位置大小或者自定义属性之类


2、创建执行动画,参数为当前值和目标值,根据对应算法来完成动画效果


3、根据目标状态的属性值和记录的缓存属性值,调用创建好的动画对象执行即可


那落实到代码中,首先先集成 Transition 类,会让你实现三个方法:captureStartValuescaptureEndValuescreateAnimator


  1. 定义你关心的属性值;官方建议属性定义的规则为:·package_name:transition_class:property_name.· 比如


private static String PROPNAME_TEXT_COLOR = "xiaweizi:changeTextColor:color";


我想在文本颜色发生改变时做转场动画,就可以定义上述的属性。


  1. 记录起始状态的属性;


void captureStartValues(TransitionValues transitionValues)


void captureEndValues(TransitionValues transitionValues);


上述方法分别存储起始状态下对应的属性值:


transitionValues.values.put(PROPNAME_TEXT_COLOR, view.getCurrentTextColor());


  1. 创建动画;


Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, final TransitionValues endValues)


参数值的 startValuesendValues分别可以拿到你存储的属性值,之后创建动画并返回即可,后续系统会根据你创建的动画进行转场。


是不是很简单,接下来通过几个案例带大家感受一下:

[](

)ChangeTextTransition


ChangeTextTransition.java 该类中定义了:


private static String PROPNAME_TEXT = "xiaweizi:changeText:text";


private static String PROPNAME_TEXT_COLOR = "xiaweizi:changeTextColor:color";


private static String PROPNAME_TEXT_SIZE = "xiaweizi:changeTextSize:size";


private static String PROPNAME_TEXT_LEVEL = "xiaweizi:changeTextTypeface:level";


分别代表文本内容变化、文本颜色变化、文本大小变化和文本字体变化。我们只挑一个文本颜色来看一下动画是如何实现的:


// 记录下起始状态属性值


private void captureValues(TransitionValues transitionValues) {


if (transitionValues == null || !(transitionValues.view instanceof TextView)) return;


TextView view = (TextView) transitionValues.view;


transitionValues.values.put(PROPNAME_TEXT, view.getText());


transitionValues.values.put(PROPNAME_TEXT_COLOR, view.getCurrentTextColor());


transitionValues.values.put(PROPNAME_TEXT_SIZE, view.getTextSize());


transitionValues.values.put(PROPNAME_TEXT_LEVEL, view.getTag(R.id.type_face_level));


}


@Override


public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, final TransitionValues endValues) {


if (startValues == null || endValues == null) {


return null;


}


if (!(endValues.view instanceof TextView)) {


return super.createAnimator(sceneRoot, startValues, endValues);


}


TextView endView = (TextView) endValues.view;


int startTextColor = (int) startValues.values.get(PROPNAME_TEXT_COLOR);


int endTextColor = (int) endValues.values.get(PROPNAME_TEXT_COLOR);


ObjectAnimator animator = ObjectAnimator.ofArgb(endView, new TextColorProperty(), startTextColor, endTextColor);


animator.setDuration(300);


return animator;


}


看一下这四种属性发生变化时的效果:


[](

)ChangeBackgroundColorTransition


类似于文本颜色,只不过针对的是 view.setBackground(),主要的代码在于创建 Animator:


@Override


public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, final TransitionValues endValues) {


if (startValues == null || endValues == null) {


return null;


}


final View endView = endValues.view;


ColorDrawable startColorDrawable = (ColorDrawable) startValues.values.get(PROPNAME_COLOR);


ColorDrawable endColorDrawable = (ColorDrawable) endValues.values.get(PROPNAME_COLOR);


if (startColorDrawable == null || endColorDrawable == null) return super.createAnimator(sceneRoot, startValues, endValues);


final int startColor = startColorDrawable.getColor();


final int endColor = endColorDrawable.getColor();


ValueAnimator animator = ValueAnimator.ofObject(new ArgbEvaluator(), startColor, endColor);


animator.setDuration(300);


animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {


@Override


public void onAnimationUpdate(ValueAnimator animation) {


int animatedValue = (int) animation.getAnimatedValue();


endView.setBackgroundColor(animatedValue);


}


});


return animator;


}


最终效果:


[](

)ChangeImageResourceTransition


有的时候发现,在切换图片的时候过度会很生硬,那可以通过在对 View 的 alpha 属性从 101 的过程中替换图片,这样显得很平滑。


@Override


public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, final TransitionValues endValues) {


if (startValues == null || endValues == null) {


return null;


}


if (!(endValues.view instanceof ImageView)) {


return super.createAnimator(sceneRoot, startValues, endValues);


}


final ImageView endView = (ImageView) endValues.view;


final Drawable startDrawable = (Drawable) startValues.values.get(PROPNAME_IMAGE_RESOURCE);


final Drawable endDrawable = (Drawable) endValues.values.get(PROPNAME_IMAGE_RESOURCE);


ValueAnimator animator = ValueAnimator.ofFloat(0, 1f);


animator.setDuration(300);


animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {


@Override


public void onAnimationUpdate(ValueAnimator animation) {


float animatedValue = (float) animation.getAnimatedValue();


if (animatedValue <= 0.5f) {


endView.setImageDrawable(startDrawable);


float ratio = (0.5f - animatedValue) / 0.5f;


endView.setAlpha(ratio);


} else {


endView.setImageDrawable(endDrawable);


float ratio = (animatedValue - 0.5f) / 0.5f;


endView.setAlpha(ratio);


}


}


});


return animator;


最终效果:


[](

)ChangeCustomTransition


除了 View 原生的属性,自定义属性同样也可以。创建 Animator 没什么区别:


@Override


public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, final TransitionValues endValues) {


if (startValues == null || endValues == null) {


return null;


}


if (!(endValues.view instanceof TransitionView)) {


return super.createAnimator(sceneRoot, startValues, endValues);


}


final TransitionView endView = (TransitionView) endValues.view;


final float startRatio = (float) startValues.values.get(PROPNAME_CUSTOM_RATIO);


final float endRatio = (float) endValues.values.get(PROPNAME_CUSTOM_RATIO);


ObjectAnimator animator = ObjectAnimator.ofFloat(endView, "ratio", startRatio, endRatio);


animator.setDuration(300);


return animator;


}

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
『Android 技能篇』优雅的转场动画之 Transition,kotlin安卓开发教程视频