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

效果图

  

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

实现步骤

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. Android实战技巧:如何在ScrollView中嵌套ListView

    前几天因为项目的需要,要在一个ListView中放入另一个ListView,也即在一个ListView的每个ListItem中放入另外一个ListView.但刚开始的时候,会发现放入的小ListVie ...

  2. C#.NET常见问题(FAQ)-如何把文本复制粘贴到文本框的光标位置

    前面已经通过Clipborad.SetText之后,这里就要先把目标文本框的文本改成插入之后的值,然后修改光标所在位置  

  3. C#.NET常见问题(FAQ)-override覆盖和virtual虚类如何理解

    父类使用virtual关键字,可以让子类的实例完全代替基类的类成员.(前面父类virtual后面子类override),比如下面我定义一个Employee的员工的基类,给这个基类定义了Start_Wo ...

  4. android中去掉ListView控件中的分割线

    通过设置android:divider="@null" ,可以去掉ListView控件中的分割线 也可以自定义分割线的颜色,比如: <ListView android:id= ...

  5. 【高德地图Android SDK】视频教学

    前两天参加了高德在北航举办的公开课,感觉非常不错.完成老师布置的作业之后,还顺利地拿到了高德开发者认证证书!! 现在来跟大家分享一下,如何快速学习[高德地图Android SDK]的开发.一天包会!连 ...

  6. Word2007视频教程

    超级好教程 http://v.youku.com/v_show/id_XMTAwOTgwNTIw.html 视频: oeasy教你玩转office系列之Word视频教程01 http://v.youk ...

  7. MapReduce实现大矩阵乘法

    来自:http://blog.csdn.net/xyilu/article/details/9066973 引言 何 为大矩阵?Excel.SPSS,甚至SAS处理不了或者处理起来非常困难,需要设计巧 ...

  8. Win10下安装Ubuntu16.04虚拟机并搭建TensorFlow1.3环境

    本文具体参考资料链接 1.VMware下载安装 百度输入VMware搜索,出现如下界面,点击下载: 此处安装步骤可以网上搜索,也可不用搜索,直接按照按照提示一步一步确认即可完成. 2.Ubuntu16 ...

  9. PPT里面的背景音乐找不到?

      ppt,找不到播放器,却有音乐播放!如何实现? 原来是在幻灯片切换处的音效添加的音乐~   文章来源:刘俊涛的博客 欢迎关注,有问题一起学习欢迎留言.评论

  10. Java之创建对象>3.Enforce the singleton property with a private constructor or an enum type

     1. 通过一个公开的字段来获取单例 // Singleton with public final field public class Elvis { public static final Elv ...