两种方式实现类似水波扩散效果,先上图为敬

  1. 自定义view实现
  2. 动画实现

自定义view实现

思路分析:通过canvas画圆,每次改变圆半径和透明度,当半径达到一定程度,再次从中心开始绘圆,达到不同层级的效果,通过不断绘制达到view扩散效果

private Paint centerPaint; //中心圆paint
private int radius = 100; //中心圆半径
private Paint spreadPaint; //扩散圆paint
private float centerX;//圆心x
private float centerY;//圆心y
private int distance = 5; //每次圆递增间距
private int maxRadius = 80; //最大圆半径
private int delayMilliseconds = 33;//扩散延迟间隔,越大扩散越慢
private List<Integer> spreadRadius = new ArrayList<>();//扩散圆层级数,元素为扩散的距离
private List<Integer> alphas = new ArrayList<>();//对应每层圆的透明度
复制代码

style文件里自定义属性

<declare-styleable name="SpreadView"><!--中心圆颜色--><attr name="spread_center_color" format="color" /><!--中心圆半径--><attr name="spread_radius" format="integer" /><!--扩散圆颜色--><attr name="spread_spread_color" format="color" /><!--扩散间距--><attr name="spread_distance" format="integer" /><!--扩散最大半径--><attr name="spread_max_radius" format="integer" /><!--扩散延迟间隔--><attr name="spread_delay_milliseconds" format="integer" />
</declare-styleable>复制代码

初始化


public SpreadView(Context context) {this(context, null, 0);
}public SpreadView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);
}public SpreadView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SpreadView, defStyleAttr, 0);radius = a.getInt(R.styleable.SpreadView_spread_radius, radius);maxRadius = a.getInt(R.styleable.SpreadView_spread_max_radius, maxRadius);int centerColor = a.getColor(R.styleable.SpreadView_spread_center_color, ContextCompat.getColor(context, R.color.colorAccent));int spreadColor = a.getColor(R.styleable.SpreadView_spread_spread_color, ContextCompat.getColor(context, R.color.colorAccent));distance = a.getInt(R.styleable.SpreadView_spread_distance, distance);a.recycle();centerPaint = new Paint();centerPaint.setColor(centerColor);centerPaint.setAntiAlias(true);//最开始不透明且扩散距离为0alphas.add(255);spreadRadius.add(0);spreadPaint = new Paint();spreadPaint.setAntiAlias(true);spreadPaint.setAlpha(255);spreadPaint.setColor(spreadColor);
}
复制代码

确定圆心位置

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);//圆心位置centerX = w / 2;centerY = h / 2;
}
复制代码

自定义view的绘制


@Override
protected void onDraw(Canvas canvas) {super.onDraw(canvas);for (int i = 0; i < spreadRadius.size(); i++) {int alpha = alphas.get(i);spreadPaint.setAlpha(alpha);int width = spreadRadius.get(i);//绘制扩散的圆canvas.drawCircle(centerX, centerY, radius + width, spreadPaint);//每次扩散圆半径递增,圆透明度递减if (alpha > 0 && width < 300) {alpha = alpha - distance > 0 ? alpha - distance : 1;alphas.set(i, alpha);spreadRadius.set(i, width + distance);}}//当最外层扩散圆半径达到最大半径时添加新扩散圆if (spreadRadius.get(spreadRadius.size() - 1) > maxRadius) {spreadRadius.add(0);alphas.add(255);}//超过8个扩散圆,删除最先绘制的圆,即最外层的圆if (spreadRadius.size() >= 8) {alphas.remove(0);spreadRadius.remove(0);}//中间的圆canvas.drawCircle(centerX, centerY, radius, centerPaint);//TODO 可以在中间圆绘制文字或者图片//延迟更新,达到扩散视觉差效果postInvalidateDelayed(delayMilliseconds);
}复制代码

xml样式

<com.airsaid.diffuseview.widget.SpreadViewandroid:id="@+id/spreadView"android:layout_width="match_parent"android:layout_height="wrap_content"app:spread_center_color="@color/colorAccent"app:spread_delay_milliseconds="35"app:spread_distance="5"app:spread_max_radius="90"app:spread_radius="100"app:spread_spread_color="@color/colorAccent" />
复制代码

效果图

中心圆处可以自定义写文字,画图片等等...

动画实现

思路分析:通过动画实现,imageView不停做动画缩放+渐变
最中心的imageView保持不变
中间一层imageView从原始放大到1.4倍,同时从不透明变为半透明
最外层的imageView从1.4倍放大到1.8倍,同时从半透明变为全透明
利用shape画一个圆,作为动画基础视图

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"><corners android:radius="65dp"/><solid android:color="@color/colorAccent"/>
</shape>
复制代码

布局视图

<FrameLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><!--中心imageView--><ImageViewandroid:id="@+id/iv_wave"android:layout_width="130dp"android:layout_height="130dp"android:layout_gravity="center"android:background="@drawable/shape_circle" /><!--中间的imageView--><ImageViewandroid:id="@+id/iv_wave_1"android:layout_width="130dp"android:layout_height="130dp"android:layout_gravity="center"android:background="@drawable/shape_circle" /><!--最外层imageView--><ImageViewandroid:id="@+id/iv_wave_2"android:layout_width="130dp"android:layout_height="130dp"android:layout_gravity="center"android:background="@drawable/shape_circle" />
</FrameLayout>
复制代码

中间imageView的动画

private void setAnim1() {AnimationSet as = new AnimationSet(true);//缩放动画,以中心从原始放大到1.4倍ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.4f, 1.0f, 1.4f,ScaleAnimation.RELATIVE_TO_SELF, 0.5f,ScaleAnimation.RELATIVE_TO_SELF, 0.5f);//渐变动画AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.5f);scaleAnimation.setDuration(800);scaleAnimation.setRepeatCount(Animation.INFINITE);alphaAnimation.setRepeatCount(Animation.INFINITE);as.setDuration(800);as.addAnimation(scaleAnimation);as.addAnimation(alphaAnimation);iv1.startAnimation(as);
}
复制代码

最外层imageView的动画

private void setAnim2() {AnimationSet as = new AnimationSet(true);//缩放动画,以中心从1.4倍放大到1.8倍ScaleAnimation scaleAnimation = new ScaleAnimation(1.4f, 1.8f, 1.4f, 1.8f,ScaleAnimation.RELATIVE_TO_SELF, 0.5f,ScaleAnimation.RELATIVE_TO_SELF, 0.5f);//渐变动画AlphaAnimation alphaAnimation = new AlphaAnimation(0.5f, 0.1f);scaleAnimation.setDuration(800);scaleAnimation.setRepeatCount(Animation.INFINITE);alphaAnimation.setRepeatCount(Animation.INFINITE);as.setDuration(800);as.addAnimation(scaleAnimation);as.addAnimation(alphaAnimation);iv2.startAnimation(as);
}
复制代码

效果图

相比较而言,自定义view的效果更好点,动画实现起来更方便点。

两种方式实现的扩散效果介绍完毕,具体项目里还是要按需变动的。

同时欢迎关注微信公众号

Android 两种方式实现类似水波扩散效果相关推荐

  1. Android 两种方式优雅实现按钮防重复点击,防抖功能

    1. Kotlin 扩展函数实现防抖(Kotlin) 1.1创建ViewExtension.kt文件: fun <T : View> T.withTrigger(delay: Long = ...

  2. android不调用系统发送短信,android之两种方式调用短信发送接口

    释放双眼,带上耳机,听听看~! 相信很多程序员在开发程序的时候都会遇到短信调用端口的情况,今天是技术狗小编为大家带来的关于android之两种方式调用短信发送接口,希望对你学习这方面知识有帮助! an ...

  3. android asynctask源码分析,Android通过Handler与AsyncTask两种方式动态更新ListView(附源码)...

    本文实例讲述了Android通过Handler与AsyncTask两种方式动态更新ListView的方法.分享给大家供大家参考,具体如下: 有时候我们需要修改已经生成的列表,添加或者修改数据,noti ...

  4. com.android.sadk卸载不掉,Android的Service的两种方式以及使用

    Service根据使用方式有两种:startService.bindService. 区别: ①启动方式:前者startService.后者bindService: ②和Activity联系:前者Ac ...

  5. 【Android 逆向】Android 进程代码注入原理 ( 注入本质 | 静态注入和动态注入 | 静态注入两种方式 | 修改动态库重打包 | 修改 /data/app/xx/libs 动态库 )

    文章目录 一.注入本质 二.静态注入和动态注入 三.静态注入两种方式 ( 修改动态库重打包 | 修改 /data/app/packageName/libs/ 下的动态库 ) 一.注入本质 进程注入本质 ...

  6. Android中实现SQLite数据库CRUD操作的两种方式

    Android中实现SQLite数据库CRUD操作的两种方式 SQLite是一款轻量级的关系型数据库,具有运行速度.占用资源少的特点.通常只需要几百KB的内存就够了,因此特别适合在移动设备上使用.SQ ...

  7. 创建安卓模拟器的两种方式及常用Android命令介绍

    创建安卓模拟器有以下两种方式: 1>通过图形界面创建,在Eclipse中单击Windows->Android Virtual Device Manager启动图形界面窗口 2>如果用 ...

  8. android动态居中布局,Android动态添加布局的两种方式

    释放双眼,带上耳机,听听看~! 前言 大多数时候我们布局都是用xml来布局的,但有些时候也是会用到动态布局的,尤其是在一些大项目中,动态布局更是体现的淋漓尽致. 所以今天我们就来学习一些动态加添布局的 ...

  9. linux耳机插拔检测,Android应用开发之耳机插拔处理两种方式

    本文将带你了解Android应用开发[RK3288][Android6.0] 耳机插拔处理两种方式,希望本文对大家学Android有所帮助. [RK3288][Android6.0]   耳机插拔处理 ...

  10. android注册广播两种方式,Android 注册广播的两种方式对比

    Android 注册广播的两种方式对比 1.常驻型广播 常驻型广播,当你的应用程序关闭了,如果有广播信息来,你写的广播接收器同样的能接受到, 他的注册方式就是在你的应用程序中的AndroidManif ...

最新文章

  1. 更大的工字型电感作为150kHz导航信号接收天线
  2. 【PC工具】录屏软件,必须好用无广告!
  3. Head First JSP---随笔九(Web应用安全)
  4. 简单却实用的的例子:Jquery获取 radio 选中后的文字
  5. 表单隐藏域与display:none
  6. String、int、Integer互转的常用方法
  7. 解析xml文件的几种技术
  8. java和php区别吗_请说说Java和PHP的区别
  9. 爬虫选用PPTP协议代理ip的必要性
  10. J2EE框架(四)核心设计模式
  11. 在CTeX上编码论文《杂谈勾股定理》及论文式样
  12. C#实例.net_经典例子400个
  13. ajax json destoon,destoon数据如何生成json
  14. 【工作规划】未来自我学习计划及发展注意事项
  15. Python爬虫之string、strings、stripped_strings、get_text和text用法区别
  16. ADI Blackfin DSP处理器-BF533的开发详解61:DSP控制ADXL345三轴加速度传感器-LCD(含源码)
  17. 什么是智能巡检?有何作用与意义
  18. 产品设计的五个要素层面
  19. 从苹果IOS14的App Library分类看用户行为与使用需求
  20. VS中重复定义的解决方法

热门文章

  1. 多小区下小区上行速率的计算(5)
  2. 返回信息是html的性能测试,Web前端性能测试小点
  3. flutter 点击旋转动画_flutter RotationTransition实现旋转动画
  4. 【机器学习系列】变分推断第三讲:基于随机梯度上升法SGD的变分推断解法
  5. 动态树算法概述及习题
  6. 刷题记录 CF每日一题打卡 2020.6月7-6月13
  7. 数据算法_数据结构和常用算法
  8. Docker新手入门基础知识与实战教程
  9. ASP.NET Core中使用Csp标头对抗Xss攻击
  10. django使用ajax传输数据