这个效果做出来以后,真的美极了!放在你的应用中,无疑增添了光彩!

效果图

  

其实,第一种效果,才是产品的需求要的效果。第三种效果,是不是很熟悉?支付宝的咻一咻!哈哈,无意中,我就写出来了。

实现步骤

1.attrs.xml定义属性

 <declare-styleable name="WaveView">
<!--圆颜色-->
<attr name="wave_color" format="color"/>
<!--中心圆图片半径-->
<attr name="wave_coreImageRadius" format="integer"/>
<!--波浪圆之间间距,值越小越窄-->
<attr name="wave_width" format="integer"/>
</declare-styleable>

2.WaveView的初始化

  /**
* 波浪圆圈颜色
*/
private int mColor = getResources().getColor(R.color.yellow);
/**
* 第一个圆圈的半径(也就是圆形图片的半径)
*/
private int mImageRadius=50;
/**
* 波浪圆之间间距
*/
private int mWidth = 3;
/**
* 最大宽度
*/
private Integer mMaxRadius = 300;
/**
* 是否正在扩散中
*/
private boolean mIsWave = false;
// 透明度集合
private List<Integer> mAlphas = new ArrayList<>();
// 扩散圆半径集合
private List<Integer> mRadius = new ArrayList<>();
private Paint mPaint; public WaveView(Context context) {
this(context, null);
} public WaveView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public WaveView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WaveView, defStyleAttr, 0);
mColor = a.getColor(R.styleable.WaveView_wave_color, mColor);
mWidth = a.getInt(R.styleable.WaveView_wave_width, mWidth);
mImageRadius = a.getInt(R.styleable.WaveView_wave_coreImageRadius, mImageRadius);
a.recycle();
} private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
// mAlphas.add(255);
// mRadius.add(0); }

3.重写onDraw()

    @Override
public void onDraw(Canvas canvas) {
// 绘制扩散圆
mPaint.setColor(mColor);
for (int i = 0; i < mAlphas.size(); i++) {
// 设置透明度
Integer alpha = mAlphas.get(i);
mPaint.setAlpha(alpha);
// 绘制波浪圆
Integer radius = mRadius.get(i);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, mImageRadius+radius, mPaint); if (alpha > 0 && mImageRadius+radius < mMaxRadius) {
alpha = (int) (255.0F * (1.0F - (mImageRadius+radius) * 1.0f / mMaxRadius));
mAlphas.set(i, alpha);
mRadius.set(i, radius + 1);
}else if(alpha < 0 && mImageRadius+radius > mMaxRadius){
// 当最外面那个圆达到了View的宽度时,移除,保证内存的回收
mRadius.remove(i);
mAlphas.remove(i);
} }
// 判断当波浪圆扩散到指定宽度时添加新扩散圆
// if (mRadius.get(mRadius.size() - 1) == mWidth) {
// addWave();
// }
if (mIsWave) {
invalidate();
}
}

思路:一直不停的在根据list中的半径值和alpha值在画对应的圆,list中有多少个圆,就会画出多少个,当alpha的值小于0了,视觉上,人眼看不到了,或者已经到了View的边界,就将他移除。减少内存的占用。

4.提供的一些公共的方法,方便调用

/**
* 开始扩散
*/
public void start() {
mIsWave = true;
invalidate();
} /**
* 停止扩散
*/
public void stop() {
mIsWave = false;
} /**
* 是否扩散中
*/
public boolean isWave() {
return mIsWave;
} /**
* 设置波浪圆颜色
*/
public void setColor(int colorId) {
mColor = colorId;
} /**
* 设置波浪圆之间间距
*/
public void setWidth(int width) {
mWidth = width;
} /**
* 设置中心圆半径
*/
public void setMaxRadius(int maxRadius) {
mMaxRadius = maxRadius;
} public void setImageRadius(int imageRadius) {
mImageRadius = imageRadius;
} public void addWave(){
mAlphas.add(255);
mRadius.add(0);
}

5.Activity中的调用和xml布局

WaveActivity.java

    private ImageView head;
private WaveView wave;
private ScaleAnimation scaleAnimation;
private MediaPlayer mPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wave);
scaleAnimation = new ScaleAnimation(1.2f, 1f, 1.2f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setDuration(500);
scaleAnimation.setFillAfter(true);
wave = (WaveView) findViewById(R.id.wave);
head = (ImageView) findViewById(R.id.head);
mPlayer = MediaPlayer.create(this, R.raw.water_wave);
head.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
wave.addWave();
head.startAnimation(scaleAnimation);
if(mPlayer.isPlaying()){
mPlayer.stop();
try {
mPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
mPlayer.start();
}
});
wave.start();
} @Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
wave.setImageRadius(head.getWidth()/2);
}

activity_wave.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
>
<com.dx.demi.view.WaveView
android:id="@+id/wave"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:wave_color="@color/yellow"
app:wave_coreImageRadius="30"
app:wave_width="40"/> <ImageView
android:id="@+id/head"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/user"
android:layout_centerInParent="true"/>
</RelativeLayout>

6.需要注意的细节

/**
* 获取View的宽高在构造方法中拿不到的,getWidth(),getHeight()都会为零
* @param hasWindowFocus
*/
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
mMaxRadius = getWidth() > getHeight() ? getHeight() / 2 : getWidth() / 2;
invalidate();
} /**
* 防止window是去焦点时,也就是应用在后台时,停止View的绘制
*/
@Override
public void invalidate() {
if (hasWindowFocus()) {
super.invalidate();
}
}

三种效果的切换

1.我目前贴的代码实现的是效果3(咻一咻):点击图片,图片会放大,同时会播放背景音乐(网上随便找了个还听得过去的),并增加一个新的波浪圆。

2.效果1:打开View的界面,每个一段固定的距离,就会产生一个新的波浪圆。波浪圆是空心的。这个只要设置画笔的风格为STROKE,并设置StrokeWidth。Activity中注释掉动画,注释掉点击事件,注释掉音乐播放。但是要记得一开始就得添加新圆,不然啥都没有。毕竟不像效果3那样,点击图片才有。

 mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
mAlphas.add(255);
mRadius.add(0);

3.效果2:打开View的界面,每个一段固定的距离,就会产生一个新的波浪圆。波浪圆是实心的。Activity中注释掉动画,注释掉点击事件,注释掉音乐播放。设置画笔的风格为FILL就OK了,默认风格就是FILL。

总结:

在完成这个自定义View的时候,花了很长时间。我也不是一开始就是这样的一个思路。没有想到过用集合来存放半径,没有第一时间想到getWidth()的值在构造方法中会获取不到.所以还是得多想,多尝试。我们才会进步,提高!在自定义View时,一定要明白一个真理:”onDraw()方法重新调用时,会抹去上一次绘制过的图像“。有些地方,我写的可能不是很好,还需要优化。欢迎点评!

源代码链接

https://github.com/Demidong/ClockView

自定义View之圆形水波扩散动效的更多相关文章

  1. 自定义View之一圆形图片

    自定义View的方法 对现有控件进行扩展 通过组合来实现新的控件 重写View来实现全新的控件 本篇文章主要讲对现有控件的扩展 1.圆形图片控件 自定义View,对ImageView的扩展 重写onD ...

  2. 自定义View,圆形头像

    1. 效果图 2. xml中 <com.etoury.etoury.ui.view.CircleImg android:id="@+id/user_info_head_img" ...

  3. android自定义View绘制圆形头像与椭圆头像

    要实现这两种效果,需要自定义View,并且有两种实现方式.   第一种: public class BitmapShaders extends View {     private  BitmapSh ...

  4. Android绘图机制(一)——自定义View的基础属性和方法

    Android绘图机制(一)--自定义View的基础属性和方法 自定义View看起来,确实看起来高深莫测,很多Android开发都不是特别在行这一块,这里面的逻辑以及一些绘画都是有一点难的,说一下我目 ...

  5. 通过圆形载入View了解自定义View

    这是自定义View的第一篇文章,通过制作简单的自定义View来了解自定义View的流程. 自定义View是Android学习和开发中必不可少的一部分.通过自定义View我们可以制作丰富绚丽的控件,自定 ...

  6. Android 自定义 View 圆形进度条总结

    Android 自定义圆形进度条总结 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 微信公众号:牙锅子 源码:CircleProgress 文中如有纰漏,欢迎大家留言指出. 最近 ...

  7. Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)

      Android 高手进阶(21)  版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明地址:http://blog.csdn.net/xiaanming/article/detail ...

  8. Android 自定义View修炼-Android实现圆形、圆角和椭圆自定义图片View(使用BitmapShader图形渲染方法)

    一.概述 Android实现圆角矩形,圆形或者椭圆等图形,一般主要是个自定义View加上使用Xfermode实现的.实现圆角图片的方法其实不少,常见的就是利用Xfermode,Shader.本文直接继 ...

  9. Android 自定义view --圆形百分比(进度条)

    转载请注明出处:http://blog.csdn.net/wingichoy/article/details/50334595 注:本文由于是在学习过程中写的,存在大量问题(overdraw onDr ...

随机推荐

  1. WIN10系统如何取消右下角的通知菜单,通知图标

    鼠标左键单击通知按钮,然后点击所有设置   在通知和操作页面,取消勾选所有的通知   建议选择在任务栏显示哪些图标,然后勾选显示所有图标  

  2. 微信小程序 - 下拉菜单组件

    使用: 1.导入组件 2.使用组件 3.数据传入 4. 获取数据(通过同步缓存,获取“choose”)- 发送到后端 点击下载:小程序-下拉组件.

  3. nginx获得response自定义的header

    Response header send by upstream is $upstream_http_x_uuid http://wiki.nginx.org/HttpUpstreamModule#. ...

  4. 用 bottle.py 写了个简单的升级包上传

    可以当作一个 demo 来玩吧,在这里分享一下.里面涉及的内容包含了文件上传,cookie 设置和读取,重定向(redirect). from bottle import run, post, get ...

  5. bat 十进制转16进制

    @echo offset code=0123456789ABCDEF:enterset /p num=输入你要转换的十进制数字:echo %num%|findstr "[^0-9]" ...

  6. 【DB2】设置表不记录日志,但是回滚导致表不可用报错:DB2 SQL Error: SQLCODE=-1477, SQLSTATE=55019, SQLERRMC=LEN.TMP;5;3, DRIVER=3.57.82

    今天在生产发现个问题,很多表报错:SQLCODE=-1477 后来线下模拟出这种场景 出现这个问题,此时对表做reorg.runstats都是无效的. 那么怎么来解决这个问题呢? 只能重建表解决问题

  7. urllib2特点--urllib2.Request对象,定制请求头部信息

    # -*- coding: cp936 -*- #python 27 #xiaodeng #urllib2特点--urllib2.Request对象,定制请求 import urllib2 def r ...

  8. 转 ImageMagick及PHP的imagick扩展的安装及配置

    imagick是一个PHP的扩展,用ImageMagick提供的API来进行图片的创建与修改,不过这些操作已经包装到扩展imagick中去了,最终调用的是ImageMagick提供的API Image ...

  9. 主成分分析PCA

    PCA(Principal Component Analysis)不仅仅是对高维数据进行降维,更重要的是经过降维去除了噪声,发现了数据中的模式. PCA把原先的n个特征用数目更少的m个特征取代,新特征 ...

  10. mac下phpstrom安装主题和主题推荐

    phpstorm主题 在mac下finder下command+shift+G键到~/Library/Preferences/PhpStorm2016.2/colors,我的路径可能和你的不同,但是大同 ...