欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 5.0 实现水波扩散效果

程序员文章站 2022-06-23 14:54:08
本文实例为大家分享了android 5.0 实现水波扩散效果的具体代码,供大家参考,具体内容如下 该效果是通过自定义界面来实现的 1、首先自定义属性,attrs.xml...

本文实例为大家分享了android 5.0 实现水波扩散效果的具体代码,供大家参考,具体内容如下

该效果是通过自定义界面来实现的

1、首先自定义属性,attrs.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
 
  <declare-styleable name="rippleview">
    <attr name="ripplecolor" format="color" />
    <attr name="ripplealpha" format="float" />
    <attr name="maskalpha" format="float" />
    <attr name="rippletime" format="integer" />
  </declare-styleable>
 
</resources>

其中属性ripplecolor为水波动画的颜色,ripplealpha为其透明度,rippletime为动画持续时间,maskalpha为触摸遮掩层的透明度。

2、自定义rippleview类继承relativelayout布局,也可以由需求所定继承于其它类,实现水波扩散效果主要的有两点:水波扩散的绘制和动画

1)水波的绘制其实就是绘制一个圆形

canvas.drawcircle(mdownx, mdowny, mradius, mripplepaint);

2)动画效果就是该圆形的绘制从小到大的过程,而该圆形到最大时的半径长度就是当前所在布局的对角线长度:

@override
protected void onsizechanged(int w, int h, int oldw, int oldh) {
 super.onsizechanged(w, h, oldw, oldh);
 // 获取最大半径
 mmaxradius = (float) math.sqrt(w * w + h * h);
}

动画效果用属性动画objectanimator来实现(objectanimator是android3.0后出现的)如下

mrippleanim = objectanimator.offloat(this, "radius", 0, mmaxradius);
mrippleanim.setinterpolator(new acceleratedecelerateinterpolator());
mrippleanim.setduration(mrippletime);

其中的radius为自定义的属性,在动画执行时会回调对应的方法,只需要在该方法中更新圆形的半径就行了

public void setradius(final float radius) {
 mradius = radius;
 invalidate();
}

rippleview完整代码如下:

public class rippleview extends relativelayout {
 
 private int mripplecolor;// 水波颜色
 
 private float mmaskalpha;// 遮掩透明度
 private float mripplealpha;// 水波透明度
 
 private int mrippletime;// 水波动画时间
 private objectanimator mrippleanim;// 显示水波动画
 
 private float mradius;// 当前的半径
 private float mmaxradius;// 水波最大半径
 
 private float mdownx; // 记录手指按下的位置
 private float mdowny;
 private boolean mismask;
 private boolean misanimating;// 是否正在播放动画
 
 private rectf mrect;
 private path mpath;
 private paint mmaskpaint;
 private paint mripplepaint;
 
 public rippleview(context context) {
 this(context, null);
 }
 
 public rippleview(context context, attributeset attrs) {
 this(context, attrs, 0);
 }
 
 public rippleview(context context, attributeset attrs, int defstyle) {
 super(context, attrs, defstyle);
 init();
 // 获取自定义属性
 typedarray ta = context.obtainstyledattributes(attrs,
  r.styleable.rippleview);
 mripplecolor = ta.getcolor(r.styleable.rippleview_ripplecolor,
  mripplecolor);
 mmaskalpha = ta.getfloat(r.styleable.rippleview_maskalpha, mmaskalpha);
 mripplealpha = ta.getfloat(r.styleable.rippleview_ripplealpha,
  mripplealpha);
 mrippletime = ta.getint(r.styleable.rippleview_rippletime, mrippletime);
 ta.recycle();
 initlast();
 }
 
 // 初始化方法
 private void init() {
 mripplecolor = color.black;
 mmaskalpha = 0.4f;
 mripplealpha = 0.8f;
 mrippletime = 800;
 
 mpath = new path();
 mmaskpaint = new paint(paint.anti_alias_flag);
 mripplepaint = new paint(paint.anti_alias_flag);
 }
 
 // 初始化
 private void initlast() {
 mmaskpaint.setcolor(mripplecolor);
 mripplepaint.setcolor(mripplecolor);
 mmaskpaint.setalpha((int) (mmaskalpha * 255));
 mripplepaint.setalpha((int) (mripplealpha * 255));
 }
 
 // 初始化动画
 private void initanim() {
 mrippleanim = objectanimator.offloat(this, "radius", 0, mmaxradius);
 mrippleanim.setinterpolator(new acceleratedecelerateinterpolator());
 mrippleanim.setduration(mrippletime);
 mrippleanim.addlistener(new animator.animatorlistener() {
  @override
  public void onanimationstart(animator animator) {
  misanimating = true;
  }
 
  @override
  public void onanimationend(animator animator) {
  setradius(0);
  mismask = false;
  misanimating = false;
  }
 
  @override
  public void onanimationcancel(animator animator) {
 
  }
 
  @override
  public void onanimationrepeat(animator animator) {
 
  }
 });
 }
 
 @override
 protected void onsizechanged(int w, int h, int oldw, int oldh) {
 super.onsizechanged(w, h, oldw, oldh);
 // 获取最大半径
 mmaxradius = (float) math.sqrt(w * w + h * h);
 // 获取该类布局范围
 mrect = new rectf(0f, 0f, getmeasuredwidth() * 1.0f,
  getmeasuredheight() * 1.0f);
 // 初始化动画
 initanim();
 }
 
 @override
 public boolean ontouchevent(motionevent event) {
 // 按下事件
 if (event.getaction() == motionevent.action_down) {
  mismask = true;
  invalidate();
 } else if (event.getaction() == motionevent.action_move) {
  invalidate();
 }
 // 抬起事件
 else if (event.getaction() == motionevent.action_up) {
  mdownx = event.getx();
  mdowny = event.gety();
  if (misanimating) {
  mrippleanim.cancel();
  }
  boolean isinview = mrect.contains(mdownx, mdowny);
  if (isinview) {
  mrippleanim.start();
  } else {
  mismask = false;
  invalidate();
  }
 
 }
 
 return true;
 }
 
 @override
 protected void ondraw(canvas canvas) {
 super.ondraw(canvas);
 // 绘制遮掩
 if (mismask) {
  canvas.save(canvas.clip_save_flag);
  mpath.reset();
  mpath.addrect(mrect, path.direction.cw);
  canvas.clippath(mpath);
  canvas.drawrect(mrect, mmaskpaint);
  canvas.restore();
 
 }
 
 // 绘制水波
 canvas.save(canvas.clip_save_flag);
 mpath.reset();
 mpath.addcircle(mdownx, mdowny, mradius, path.direction.cw);
 canvas.clippath(mpath);
 canvas.drawcircle(mdownx, mdowny, mradius, mripplepaint);
 canvas.restore();
 
 }
 
 // 属性动画回调的方法
 public void setradius(final float radius) {
 mradius = radius;
 invalidate();
 }
}

界面布局代码

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  xmlns:ripple="http://schemas.android.com/apk/res/com.example.rippleview"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#000000" >
 
  <com.example.rippleview.rippleview
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:layout_centerinparent="true"
    android:background="#ffffff"
    android:clickable="true"
    ripple:ripplecolor="#ababab" >
 
    <textview
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerinparent="true"
      android:text="click me"
      android:textsize="18sp" />
  </com.example.rippleview.rippleview>
 
</relativelayout>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。