Android自定义View实现水波纹效果
时间:2022-07-28
本文章向大家介绍Android自定义View实现水波纹效果,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
介绍:水波纹散开效果的控件在 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
以上就是本文的全部内容,希望对大家的学习有所帮助。
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 解决Laravel5.2 Auth认证退出失效的问题
- php输出文字乱码的解决方法
- laravel-admin表单提交隐藏一些数据,回调时获取数据的方法
- laravel 5.3 单用户登录简单实现方法
- Thinkphp5.0 框架的请求方式与响应方式分析
- Yii框架视图、视图布局、视图数据块操作示例
- 用php定义一个数组最简单的方法
- laravel-admin自动生成模块,及相关基础配置方法
- laravel-admin select框默认选中的方法
- Laravel-admin之修改操作日志的方法
- php使用curl伪造浏览器访问操作示例
- 关于laravel后台模板laravel-admin select框的使用详解
- 基于Laravel-admin 后台的自定义页面用法详解
- php解决约瑟夫环算法实例分析
- 浅谈laravel-admin的sortable和orderby使用问题