事件流处理方式介绍和所包含的类型
635
2022-09-26
探索安卓中有意义的动画!(安卓中的动画有哪几类它们的特点和区别是什么)
动画!
笔者非常喜欢动画效果,因为它不仅提高用户参与度,还能迅速夺人眼球。想想那些以动画设计著称的应用,它们使用起来是多么可心、流畅、自然。
Falcon Pro:即使细微的动画效果也可以对用户体验产生巨大影响。
现在,与那些你很喜欢但没有动画的应用做一番比较。
Medium: 尽管笔者很喜爱 medium APP,但它的确缺少恰当的动画。
小动作也能造就大不同
我们可以从多个方面利用动画,从而:* 通过导航上下文传输用户;* 强化元素的层级结构;* 展示屏幕显示的组件变化。
本文旨在说明,在应用中实现有意义的动画十分简单可行——那么,即刻开始吧。
触觉反馈
在用户触摸屏幕时提供反馈,有助于视觉交流,形成互动。这些动画不应分散用户的注意力,但又使他们享受其中,获得清晰的视感,从而鼓励进一步操作。
安卓框架为此类反馈提供了波纹效果,通过设定视图背景,即可使用:
?android:attr/selectableItemBackground-在视图范围内展示波纹效果;
波纹在接触点开始,之后填充整个视图背景。
?android:attr/selectableItemBackgroundBorderless –将波纹效果延伸至视图之外。
圆形波纹效果在接触点开始,并沿半径延伸至视图之外。
View Property Animator
此处将绘制下文提到的所有动画属性。
注意: 如果已在视图中设置了侦听器,并打算在相同视图下,实现其他动画且不使用回调函数,则需要将侦听器设为 null。
用程序实现时,简单又整洁:
mButton.animate() .alpha(1f) .scaleX(1f) .scaleY(1f) .translationZ(10f) .setInterpolator(new FastOutSlowInInterpolator()) .setStartDelay(200) .setListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }) .start();
制作 FAB 的 alpha 动画值
FAB 的(X 和 Y 轴)坐标动画
FAB 的 Z 坐标动画
Object Animator
使用自定义属性给视图做缩放动画,并改变其前景色,可以达成下图的效果:
view – 应用动画的视图;property – 设定动画的属性;start color – 动画视图的初始颜色;target color – 动画视图的目标颜色。
private void animateForegroundColor(@ColorInt final int targetColor) { ObjectAnimator animator = ObjectAnimator.ofInt(YOUR_VIEW, FOREGROUND_COLOR, Color.TRANSPARENT, targetColor); animator.setEvaluator(new ArgbEvaluator()); animator.setStartDelay(DELAY_COLOR_CHANGE); animator.start();}
接下来,使用相似的方法做视图缩放的动画,主要区别在于:
private void resizeView() { final float widthHeightRatio = (float) getHeight() / (float) getWidth(); resizeViewProperty(View.SCALE_X, .5f, 200); resizeViewProperty(View.SCALE_Y, .5f / widthHeightRatio, 250); } private void resizeViewProperty(Property
Interpolators
该视图以线型动作开始和结束动画。
该视图开始动作很快,逐渐降速直至结束。
该视图以线型动作开始,逐渐降速直至结束。
该视图在动画开始时加速,并在接近结束时逐渐减速。
Circular Reveal
如上图所示,在视图的动画效果显示之前,使用 ViewPropertyAnimator 隐藏浮动操作图标。只需定义如下属性就可以配置 circular reveal:
int centerX = (startView.getLeft() + startView.getRight()) / 2; int centerY = (startView.getTop() + startView.getBottom()) / 2; float finalRadius = (float) Math.hypot((double) centerX, (double) centerY); Animator mCircularReveal = ViewAnimationUtils.createCircularReveal( targetView, centerX, centerY, 0, finalRadius);
窗口转换
enter –决定活动视图如何进入场景;exit -决定活动视图如何退出场景;reenter –决定活动视图退出后如何再度进入;shared elements –决定活动间如何共享视图转换。
自 API 21起,还有如下几种新的转换方式:
爆炸
Explode 转换允许视图从屏幕各个方位退出,会使压缩视图产生爆炸效果。
在网格布局中爆炸效果尤其好。
这种效果易于实现——首先,需要在 res/transition 目录中创建如下转换:
具体做法如下:
接下来,需要将此设置为活动的转换。既可以将其添加到活动主题:
也可以编程的方式解决:
Transition explode = TransitionInflater.from(this).inflateTransition(R.transition.explode);getWindow().setEnterTransition(explode);
滑动
滑动切换可以使活动从屏幕右侧或底部滑入/出。可能你以前有过类似的效果,但是这个新切换更加灵活。
滑动切换使我们依次滑动子视图
这种转换在切换活动时尤为常见,笔者对向右侧滑的流畅感觉情有独钟,当然这也很容易创建:
渐变
渐变切换使活动转换出现淡入或淡出的效果。
在视图中使用渐变动画操作简单,且效果宜人。
创建此切换的操作比之前的切换更加简单:
优化转换
实验的同时,笔者发现了一些可以改善上述转换效果的方法。
启用/禁用转换重叠——上一转换过程结束,新的页面动画才会开始,这样就会形成时延。在不同的案例中,若启用如下属性,转换过程都会更加流畅自然:
排除特定视图转换—有时我们并不想让活动中的所有视图参与动画,而且大多数情况下,工具栏和状态栏是造成转换故障主因。所幸,可以排除特定的视图,使之无法转换:
工具栏和操作栏——当使用操作栏的活动向使用工具栏的活动转换时(反之亦然),转换过程总是磕磕绊绊。为此,应当确保转换中的两个活动都使用相同的组件。
转换持续时间——既不能让用户等太久,也不能让动画转换过快。这取决于转换持续时间,最好通过试验敲定恰当的时间。笔者发现,多数情况下200-500微秒最为合适。
共享元素转换
这里,第一个页面中的视图缩小并平移至第二个页面的标题图片位置。
在布局中,必须使用 transitionName 属性将所有共享视图联系起来——这表明了视图间的转换关系。下图展示了之前动画中的共享视图:
这些都是共享视图,意味着它们会在每次页面转换过程中形成动画。
屏幕 1)
屏幕2)
Pair participants = new Pair<>(mSquareView, ViewCompat.getTransitionName(mSquareView));ActivityOptionsCompat transitionActivityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation( SharedTransitionsActivity.this, participants);ActivityCompat.startActivity(SharedTransitionsActivity.this, intent, transitionActivityOptions.toBundle());
转换的同时滑动这些视图,有助于完成转换。
以上就是两个视图间的转换,那么在第二个页面中从底部滑入的视图怎么办呢?
(它们就是左边的那些视图)
其实这个实现过程也很简单,如下:
Slide slide = new Slide(Gravity.BOTTOM);slide.addTarget(R.id.view_separator);slide.addTarget(R.id.text_detail);slide.addTarget(R.id.text_close);getWindow().setEnterTransition(slide);
如你所见,创建一个新的Slide 转换:将目标视图添加到转换中,并将滑动动作设为入场动画。
自定义转换
我们也可以使用之前介绍过的 API 动画创建自己的自定义转换。例如,将共享元素转换衍伸,成为转换视图变体——当我们需要显示对话框(或者类似的弹框视图)时,自定义转换就会非常有用。具体如下所示:
该动画可以在组件状态间引导用户的注意力。
先来简单了解一下上图发生了什么:
动态矢量图片 ##
在图片上做几种不同的动画并不容易。
那么如何完成呢,请看下图:
该图由几个不同文件组成,首先创建两个独立的矢量文件,每个都包含如下属性:
该矢量由 ic_add.xml 文件(如下所示)生成
该矢量由ic_remove.xml 文件(如下所示)生成
状态转换的动画;图片旋转的动画。
然后创建目标文件中引用的每个文件。
改变图片状态
propertyName –执行动画的属性;valueFrom –矢量路径的初始值;valueTo –矢量路径的目标值;duration –动画持续时间;interpolator –动画插值器;valueType –动画值类型。
形状旋转
可使用相似的方法旋转图像,只是会用到旋转属性和旋转值:
执行相反的动画(从 Remove 到 Add)所需的操作方法相同,只不过将动画值反置。
完成后的动态矢量图,效果很不错吧?
动画卡顿原因
动画卡顿的原因大概有这样三种,这些因素将直接影响动画的性能,导致卡顿。即:
手势滑动速度 帧率 触摸事件响应的速度
结语
虽然只是浅谈,文本旨在围绕创建有意义的动画提供有益的视角,使读者受益。今后,笔者会继续努力,以求进一步改善应用的外观与用户体验。
发表评论
暂时没有评论,来抢沙发吧~