Android自定义水波纹动画Layout实例代码

Android自定义水波纹动画Layout实例代码,第1张

概述话不多说,我们先来看看效果:Hi前辈搜索预览这一张是《Hi前辈》的搜索预览图,你可以在这里下载这个APP查看更多效果:

话不多说,我们先来看看效果:

Hi前辈搜索预览

这一张是《Hi前辈》的搜索预览图,你可以在这里下载这个APP查看更多效果:

http://www.wandoujia.com/apps/com.superlity.hiqianbei

LSearchVIEw

这是一个MD风格的搜索框,集成了ripple动画以及search时的loading,使用很简单,如果你也需要这样的搜索控件不妨来试试:https://github.com/onlynight/LSearchView

RippleEverywhere

女友的照片:

女友的照片:

这是一个水波纹动画支持库,由于使用暂时只支持AndroID4.0以上版本。https://github.com/onlynight/RippleEverywhere

实现原理

使用属性动画完成该动画的实现,由于androID2.3以下已经不是主流机型,故只兼容4.0以上系统。

关于属性动画,如果还有童鞋不了解可以去看看hongyang大神的这篇文章:

http://www.jb51.net/article/82668.htm

在我看来属性动画实际上就类似于定时器,所谓定时器就是独立在主线程之外的另外一个用于计时的线程,每当到达你设定时间的时候这个线程就会通知你;属性动画也不光是另外一个线程,他能够 *** 作主线程UI元素属性就说明了它内部已经做了线程同步。

基本原理

我们先来看下关键代码

@OverrIDeprotected voID onDraw(Canvas canvas) {if (running) {// get canvas current statefinal int state = canvas.save();// add circle to path to crate ripple animation// attention: you must reset the path first,// otherwise the animation will run wrong way.ripplePath.reset();ripplePath.addCircle(centerX,centerY,radius,Path.Direction.CW);canvas.clipPath(ripplePath);// the {@link VIEw#onDraw} method must be called before// {@link Canvas#restoretoCount},or the change will not appear.super.onDraw(canvas);canvas.restoretoCount(state);return;}// in a normal condition,you should call the// super.onDraw the draw the normal situation.super.onDraw(canvas);}Canvas#save()和Canvas#restoretoCount()

这个两个方法用于绘制状态的保存与恢复。绘制之前先保存上一次的状态;绘制完成后恢复前一次的状态;以此类推直到running成为false,中间的这个过程就是动画的过程。

Path#addCircle()和Canvas#clipPath()

addCircle用于在path上绘制一个圈;clipPath绘制剪切后的path(只绘制path内的区域,其他区域不绘制)。

radiusAnimator = ObjectAnimator.offloat(this,"animValue",1);/*** This method will be called by {@link this#radiusAnimator}* reflection calls.** @param value animation current value*/public voID setAnimValue(float value) {this.radius = value * maxRadius;System.out.println("radius = " + this.radius);invalIDate();}

这一段是动画的动效关键,首先要有一个随着时间推移而变化的值,当每次这个值变化的时候我们需要跟新界面让vIEw重新绘制调用onDraw方法,我们不能手动调用onDraw方法,系统给我们提供的invalIDate会强制vIEw重绘进而调用onDraw方法。

以上就是这个动画的全部关键原理了,下面我们来一份完整的源码:

import androID.animation.Animator;import androID.animation.ObjectAnimator;import androID.annotation.TargetAPI;import androID.content.Context;import androID.graphics.Canvas;import androID.graphics.Path;import androID.util.AttributeSet;import androID.vIEw.VIEw;import androID.vIEw.animation.AccelerateDecelerateInterpolator;import androID.Widget.ImageVIEw;/*** Created by lion on 2016/11/11.* <p>* RippleImageVIEw use the {@link Path#addCircle} function* to draw the vIEw when {@link RippleImageVIEw#onDraw} called.* <p>* When you call {@link VIEw#invalIDate()} function,then the* {@link VIEw#onDraw(Canvas)} will be called. In that way you* can use {@link Path#addCircle} to draw every frame,you will* see the ripple animation.*/public class RippleImageVIEw extends ImageVIEw {// vIEw center xprivate int centerX = 0;// vIEw center yprivate int centerY = 0;// ripple animation current radiusprivate float radius = 0;// the max radius that ripple animation needprivate float maxRadius = 0;// record the ripple animation is runningprivate boolean running = false;private ObjectAnimator radiusAnimator;private Path ripplePath;public RippleImageVIEw(Context context) {super(context);init();}public RippleImageVIEw(Context context,AttributeSet attrs) {super(context,attrs);init();}public RippleImageVIEw(Context context,AttributeSet attrs,int defStyleAttr) {super(context,attrs,defStyleAttr);init();}@TargetAPI(21)public RippleImageVIEw(Context context,int defStyleAttr,int defStyleRes) {super(context,defStyleAttr,defStyleRes);init();}private voID init() {ripplePath = new Path();// initial the animator,when animValue change,// radiusAnimator will call {@link this#setAnimValue} method.radiusAnimator = ObjectAnimator.offloat(this,1);radiusAnimator.setDuration(1000);radiusAnimator.setInterpolator(new AccelerateDecelerateInterpolator());radiusAnimator.addListener(new Animator.AnimatorListener() {@OverrIDepublic voID onAnimationStart(Animator animator) {running = true;}@OverrIDepublic voID onAnimationEnd(Animator animator) {running = false;}@OverrIDepublic voID onAnimationCancel(Animator animator) {}@OverrIDepublic voID onAnimationRepeat(Animator animator) {}});}@OverrIDeprotected voID onLayout(boolean changed,int @R_301_6823@,int top,int right,int bottom) {super.onLayout(changed,@R_301_6823@,top,right,bottom);centerX = (right - @R_301_6823@) / 2;centerY = (bottom - top) / 2;maxRadius = maxRadius(@R_301_6823@,bottom);}/*** Calculate the max ripple animation radius.** @param @R_301_6823@ vIEw @R_301_6823@* @param top vIEw top* @param right vIEw right* @param bottom vIEw bottom* @return*/private float maxRadius(int @R_301_6823@,int bottom) {return (float) Math.sqrt(Math.pow(right - @R_301_6823@,2) + Math.pow(bottom - top,2) / 2);}/*** This method will be called by {@link this#radiusAnimator}* reflection calls.** @param value animation current value*/public voID setAnimValue(float value) {this.radius = value * maxRadius;System.out.println("radius = " + this.radius);invalIDate();}@OverrIDeprotected voID onDraw(Canvas canvas) {if (running) {// get canvas current statefinal int state = canvas.save();// add circle to path to crate ripple animation// attention: you must reset the path first,you should call the// super.onDraw the draw the normal situation.super.onDraw(canvas);}/*** call the {@link Animator#start()} function to start the animation.*/public voID startAnimation() {if (radiusAnimator.isRunning()) {radiusAnimator.cancel();}radiusAnimator.start();}}

以上所述是小编给大家介绍的AndroID自定义水波纹动画Layout实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!

总结

以上是内存溢出为你收集整理的Android自定义水波纹动画Layout实例代码全部内容,希望文章能够帮你解决Android自定义水波纹动画Layout实例代码所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/web/1147653.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存