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

Android自定义View实现水波纹效果

程序员文章站 2023-11-12 12:24:28
介绍:水波纹散开效果的控件在 app 里面还是比较常见的,例如 网易云音乐歌曲识别,附近搜索场景。 看下实现的效果: 实现思路: 先将最大圆半径与最小圆半径间距分成...

介绍:水波纹散开效果的控件在 app 里面还是比较常见的,例如 网易云音乐歌曲识别,附近搜索场景。

看下实现的效果:

Android自定义View实现水波纹效果

实现思路: 先将最大圆半径与最小圆半径间距分成几等份,从内到外,paint 透明度依次递减,绘制出同心圆,然后不断的改变这些同心圆的半径大小,延迟一定时间重绘,便达到了想外散开的动画效果了。

public class waveview extends view {

 private static final string tag = "waveview";

 private int wavecolor;

 private int wavecount;

 private bitmap wavecentericon;

 private paint paint;

 private int mwidth;

 private int mheight;

 private int centerx;

 private int centery;

 private float radius; // 最外圆半径,即最大半径

 private float innerradius; // 最内圆的半径,即最小半径

 private int centericonwidth;

 private int centericonheight;

 private float[] wavedegreearr;

 private boolean isrunning = true;

 public waveview(context context) {
  this(context, null);
 }

 public waveview(context context, attributeset attrs) {
  super(context, attrs);
  readattrs(context, attrs);
  init();
 }

 private void init() {
  paint = new paint(paint.anti_alias_flag);
  paint.setcolor(wavecolor);
  paint.setstyle(paint.style.fill);
  wavedegreearr = new float[wavecount];

  // 设置中间 drawable 点击事件


 }

 private void readattrs(context context, attributeset attrs) {
  typedarray typedarray = context.obtainstyledattributes(attrs, r.styleable.waveview);
  try {
   wavecolor = typedarray.getcolor(r.styleable.waveview_wavecolor, 0xffff0000);
   wavecount = typedarray.getint(r.styleable.waveview_wavecount, 4);
   drawable centerdrawable = typedarray.getdrawable(r.styleable.waveview_wavecentericon);
   wavecentericon = ((bitmapdrawable) centerdrawable).getbitmap();
  } catch (exception e) {

  } finally {
   typedarray.recycle();
  }
 }

 @override
 protected void onsizechanged(int w, int h, int oldw, int oldh) {
  super.onsizechanged(w, h, oldw, oldh);
  mwidth = w;
  mheight = h;
  centerx = mwidth / 2;
  centery = mheight / 2;
  radius = math.min(mwidth, mheight) / 2f;
  centericonwidth = wavecentericon.getwidth();
  centericonheight = wavecentericon.getheight();
  innerradius = math.max(centericonwidth, centericonheight) * 1.2f;

  for (int i = 0; i < wavecount; i++) {
   wavedegreearr[i] = innerradius + (radius - innerradius) / wavecount * i;
  }

 }

 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
  int widthmode = measurespec.getmode(widthmeasurespec);
  int heightmode = measurespec.getmode(heightmeasurespec);
  if (widthmode == measurespec.unspecified || widthmode == measurespec.at_most) {
   widthmeasurespec = measurespec.makemeasurespec(dp2px(120), measurespec.exactly);
  }
  if (heightmode == measurespec.unspecified || heightmode == measurespec.at_most) {
   heightmeasurespec = measurespec.makemeasurespec(dp2px(120), measurespec.exactly);
  }
  super.onmeasure(widthmeasurespec, heightmeasurespec);
 }


 @override
 protected void ondraw(canvas canvas) {
  drawwave(canvas);
  drawcentercircle(canvas);
  drawcentericon(canvas);

 }

 private void drawcentercircle(canvas canvas) {
  canvas.drawcircle(centerx, centery, innerradius, paint);
 }

 private void drawwave(canvas canvas) {
  for (int i = 0; i < wavecount; i++) {
   paint.setalpha((int) (255 - 255 * wavedegreearr[i] / radius));
   canvas.drawcircle(centerx, centery, wavedegreearr[i], paint);
  }
  for (int i = 0; i < wavedegreearr.length; i++) {
   if ((wavedegreearr[i] += 4) > radius) {
    wavedegreearr[i] = innerradius;
   }
  }
  if (isrunning) {
   postinvalidatedelayed(50);
  }
 }

 private void drawcentericon(canvas canvas) {
  paint.setalpha(255);
  int left = centerx - centericonwidth / 2;
  int top = centery - centericonheight / 2;
  canvas.drawbitmap(wavecentericon, left, top, paint);
 }

 @override
 public boolean ontouchevent(motionevent event) {
  switch (event.getaction()) {
   case motionevent.action_up:
    // 处理事件逻辑
    handleevent(event);
    return true;
  }
  return true;
 }

 private void handleevent(motionevent event) {
  float touchx = event.getx();
  float touchy = event.gety();
  log.i(tag, "handleevent: " + "(" + touchx + "," + touchy + ")");
  float distancex = math.abs(touchx - centerx);
  float distancey = math.abs(touchy - centery);
  // 计算触摸点距离中心点的距离
  float distance = (float) math.sqrt(distancex * distancex + distancey * distancey);
  // 当点击的点距离中心点距离小于最内圆半径时,认为是点击有效,否则无效
  if (distance < innerradius) {
   if (listener != null) {
    listener.oncenterwaveclick();
   }
  }
 }

 oncenterwaveclicklistener listener;

 public interface oncenterwaveclicklistener {
  void oncenterwaveclick();
 }

 public void setoncenterwaveclicklistener(oncenterwaveclicklistener listener) {
  this.listener = listener;
 }

 public void toggle() {
  isrunning = !isrunning;
  invalidate();
 }

 public boolean iswaverunning() {
  return isrunning;
 }


 private int dp2px(int dpvalue) {
  return (int) typedvalue.applydimension(typedvalue.complex_unit_dip, dpvalue, getresources().getdisplaymetrics());
 }

}

github地址:https://github.com/xing16/waveview

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