Android自定义View实现水波纹效果
程序员文章站
2023-11-12 12:24:28
介绍:水波纹散开效果的控件在 app 里面还是比较常见的,例如 网易云音乐歌曲识别,附近搜索场景。
看下实现的效果:
实现思路: 先将最大圆半径与最小圆半径间距分成...
介绍:水波纹散开效果的控件在 app 里面还是比较常见的,例如 网易云音乐歌曲识别,附近搜索场景。
看下实现的效果:
实现思路: 先将最大圆半径与最小圆半径间距分成几等份,从内到外,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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
Android自定义View简易折线图控件(二)
-
Android自定义ScrollView实现放大回弹效果实例代码
-
Android自定义View圆形进度条控件(三)
-
Android自定义View仿IOS圆盘时间选择器
-
Android自定义View 使用PathMeasure简单模仿系统ProgressBar(四)
-
Android 仿摩拜单车共享单车进度条实现StepView效果
-
Android自定义view实现太极效果实例代码
-
Android 使用ViewPager实现轮播图效果
-
Android中TabLayout+ViewPager实现tab和页面联动效果
-
Android中实现记事本动态添加行效果