开发中的东西太多,怕自己忘记了,简单记录一下。

声明:此控件借鉴了大佬的想法,在此感谢大佬提供的支持,我只是把大佬的想法拿出来而已。

ok,废话到此结束,看效果:

分析一下,我们可以看到,图中有两个圆:stop状态下,黄色的默认图,start状态下,水波纹效果的黑色的圆,默认状态下下的圆没什么好说的,直接通过

canvas.drawCircle

绘制一个圆就好,关键是,点击start之后,黑色的圆的水波纹怎么搞。我们可以观察这个水波纹,他是由好多个透明度同的圆来组成的,我们就可以在绘制这个黑色的圆的时候,通过设定他的半径和透明度的方式来实现这样一个效果。

下面还是上代码吧,再下去,我自己都晕了

public class WaterRippleView extends android.support.v7.widget.AppCompatTextView {
/**
* 波纹生成时的半径
*/
private float mWaveRadiusMin;
/**
* 波纹消失前的半径
*/
private float mWaveRadiusMax;
/**
* 每条波纹持续时间
*/
private long mWaveDuration;
private Paint mPaint;
/**
* 中间圆圈的画笔
*/
private Paint mCenterCirclePaint;
/**
* 画笔是否为stroke模式(即线条)
*/
private boolean stroke = false;
/**
* 波纹颜色
*/
private int mWaveColor;
/**
* 波纹停止的颜色
*/
private int mWaveStopColor;
/**
* 波纹动画效果
*/
private Interpolator mInterpolator = new DecelerateInterpolator();
private boolean mIsRunning;
private int mStopCircleColor;
private int mCenterCircleRadius;
/**
* 动画集合
*/
private ArrayList<ValueAnimator> mAnimators; public WaterRippleView(Context context) {
this(context, null);
} public WaterRippleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public WaterRippleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//执行初始化
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.WaterRippleView, 0, defStyleAttr);
mWaveColor = typedArray.getColor(R.styleable.WaterRippleView_color, Color.BLUE);
mStopCircleColor = getResources().getColor(R.color.income_top);//设置停止状态下的颜色--默认值
mWaveStopColor = typedArray.getColor(R.styleable.WaterRippleView_stopColor, Color.BLUE);//设置停止状态下的额颜色--xml
mWaveDuration = typedArray.getInteger(R.styleable.WaterRippleView_duration, 3000);
stroke = typedArray.getBoolean(R.styleable.WaterRippleView_stroke, false);//是否开启水波纹效果
typedArray.recycle();//释放掉TypedArray
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//设置抗锯齿
mPaint.setDither(true); mPaint.setStrokeWidth(3);//设置线的粗细
mAnimators = new ArrayList<>();
mCenterCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCenterCirclePaint.setStyle(Paint.Style.FILL);
mCenterCirclePaint.setColor(mStopCircleColor);
if (stroke) {
mPaint.setStyle(Paint.Style.STROKE);
} else {
mPaint.setStyle(Paint.Style.FILL);
}
} private ValueAnimator createAnimator() {
ValueAnimator animator = new ValueAnimator();
animator.setFloatValues(mWaveRadiusMin, mWaveRadiusMax);
L.d("mWaveRadiusMin", mWaveRadiusMin + "");
L.d("mWaveRadiusMax", mWaveRadiusMax + "");
animator.setDuration(mWaveDuration);
animator.setRepeatCount(-1);
animator.setInterpolator(mInterpolator);
return animator;
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int size = MeasureSpec.getSize(widthMeasureSpec);
mCenterCircleRadius = (int) (size / 2 * 0.8);
mWaveRadiusMin = mCenterCircleRadius;
mWaveRadiusMax = size / 2;
} @Override
protected void onDraw(Canvas canvas) {
int cX = getMeasuredWidth() / 2;
int cY = getMeasuredHeight() / 2;
if (mIsRunning) {
if (mAnimators.size() > 0) {
for (ValueAnimator mAnimator : mAnimators) {
if (mAnimator != null) {
float animatorValue = (float) mAnimator.getAnimatedValue();
L.d("animatorValue", "" + animatorValue);
//设置透明度
int alpha = getAlpha(animatorValue);
mPaint.setAlpha(alpha);
//画水波纹
canvas.drawCircle(cX, cY, animatorValue, mPaint);
}
}
}
}
canvas.drawCircle(cX, cY, mCenterCircleRadius, mCenterCirclePaint);
postInvalidate();
super.onDraw(canvas);
} private void createAnimators() {
for (int i = 0; i < 3; i++) {
mAnimators.add(createAnimator());
}
} //开启动画
public void start() {
if (mIsRunning) {
return;
}
mIsRunning = true;
mPaint.setColor(mWaveColor);
mCenterCirclePaint.setColor(mWaveColor);
if (mAnimators.size() == 0) {
createAnimators();
}
final int size = mAnimators.size();
for (int i = 0; i < size; i++) {
final int index = i;
postDelayed(new Runnable() {
@Override
public void run() {
if (mIsRunning && index < size) {
mAnimators.get(index).start();
}
}
}, (long) (mWaveDuration * index * 1f / size));
}
postInvalidate();
} //是否开启水波纹
public boolean isStart() {
for (ValueAnimator mAnimator : mAnimators) {
if (mAnimator == null && !mAnimator.isRunning()) {
return false;
}
}
return true;
} //关闭动画
public void stop() {
mIsRunning = false;
mPaint.setColor(mStopCircleColor);
mCenterCirclePaint.setColor(mStopCircleColor);
for (ValueAnimator mAnimator : mAnimators) {
if (mAnimator != null) {
mAnimator.cancel(); }
}
mAnimators.clear();
} //设置水波纹颜色
public void setColor(int color) {
mWaveColor = color;
postInvalidate();
} //设计水波纹持续时间
public void setDuration(long duration) {
mWaveDuration = duration;
postInvalidate();
} //是否画笔stroke
public void setStroke(boolean stroke) {
this.stroke = stroke;
postInvalidate();
} public boolean isStroke() {
return stroke;
} //获取水波纹透明度
private int getAlpha(float mRadius) {
int alpha = 1;
if (mWaveRadiusMax > 0) {
alpha = (int) ((1 - (mRadius - mWaveRadiusMin) / (mWaveRadiusMax - mWaveRadiusMin)) * 127);
}
return alpha;
} }

  XML中引用:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"> <Button
android:id="@+id/click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="start" /> <Button
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="stop" /> <com.zhd.admin.androldlrden.view.WaterRippleView
android:id="@+id/wrv_water"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
app:color="@color/dig_wave"
app:duration="1500"
app:stopColor="#00000000"
app:stroke="false"
app:waveCreateSpeed="500" />
</LinearLayout>

  Activity中使用:

public class MainActivity extends AppCompatActivity {

    private WaterRippleView waterRippleView;
private TextView textView; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
waterRippleView = findViewById(R.id.wrv_water);
textView = findViewById(R.id.click);
} public void onClick(View view) {
switch (view.getId()) {
case R.id.click:
waterRippleView.setStroke(true);
waterRippleView.start();
break;
case R.id.stop:
waterRippleView.stop();
break;
}
}
}

  ok,这样就可以了。

  PS:第一次写这种东西,说的不是很清楚,欢迎大家补充,以后会不定期记录自己学到的东西。

-------------------------羞耻的分割线-------------------------------
更新一下项目地址
https://github.com/zhddream/WaterRippleView

  

关于自定义view--实现自定义水波纹效果的更多相关文章

  1. 自定义view实现水波纹效果

    水波纹效果: 1.标准正余弦水波纹: 2.非标准圆形液柱水波纹: 虽说都是水波纹,但两者在实现上差异是比较大的,一个通过正余弦函数模拟水波纹效果,另外一个会运用到图像的混合模式(PorterDuffX ...

  2. Android 自定义view实现水波纹效果

    http://blog.csdn.net/tianjian4592/article/details/44222565 在实际的开发中,很多时候还会遇到相对比较复杂的需求,比如产品妹纸或UI妹纸在哪看了 ...

  3. android自定义控件(4)-自定义水波纹效果

    一.实现单击出现水波纹单圈效果: 照例来说,还是一个自定义控件,观察这个效果,发现应该需要重写onTouchEvent和onDraw方法,通过在onTouchEvent中获取触摸的坐标,然后以这个坐标 ...

  4. css 滚动视差 之 水波纹效果

    核心属性: background-attachment 这个属性就牛逼了, 它可以定义背景图片是相对视口固定, 还是随着视口滚动, 加上这个属性网页瞬间就从屌丝变成 高大上. 我们来看个例子: htm ...

  5. Android自定义控件-Path之贝赛尔曲线和手势轨迹、水波纹效果

    从这篇开始,我将延续androidGraphics系列文章把图片相关的知识给大家讲完,这一篇先稍微进阶一下,给大家把<android Graphics(二):路径及文字>略去的quadTo ...

  6. 聊聊Android5.0中的水波纹效果

    水波纹效果已经不是什么稀罕的东西了,用过5.0新控件的小伙伴都知道这个效果,可是如果使用一个TextView或者Button或者其它普通控件的话,你是否知道如何给它设置水波纹效果呢?OK,我们今天就来 ...

  7. Dialog详解(包括进度条、PopupWindow、自定义view、自定义样式的对话框)

    Dialog详解(包括进度条.PopupWindow.自定义view.自定义样式的对话框)   Android中提供了多种对话框,在实际应用中我们可能会需要修改这些已有的对话框.本实例就是从实际出发, ...

  8. Android 颜色渲染(七) RadialGradient 环形渲染实现水波纹效果

    利用环形渲染我们可以做到什么? 其实很多都是非常常见的,比如上一篇实现的帮帮糖效果, 彩色的热气球,比如这里要讲到的水波纹效果,或者也可以理解为扩散色渲染效果 首先看一下效果图: 轻触屏幕,即可看到对 ...

  9. Android自己定义控件系列五:自己定义绚丽水波纹效果

    尊重原创!转载请注明出处:http://blog.csdn.net/cyp331203/article/details/41114551 今天我们来利用Android自己定义控件实现一个比較有趣的效果 ...

随机推荐

  1. 网络1712--c语言嵌套循环作业总结

    1.助教有话说 首先,每周一篇的博客作业是很有必要的:编程的过程不仅仅是会敲几行代码.能够通过PTA就大吉大利了,你更应该做到的是梳理代码思路,通过与他人代码思路的比对,取其精华,进而不断进阶,才能逐 ...

  2. 对于分支界限法的理解(补出门门票-week13,结对伙伴对我提的问题的答案)

    首先我的结对伙伴给我提出了一个这样的问题: 使用分支界限法求解"背包问题"的步骤. 当时我是这样回答他的: ub=v+(W-w)x(v(i+1)/w(i+1)) 这个问题我在课上也 ...

  3. alpha-咸鱼冲刺day2-紫仪

    总汇链接 一,合照 emmmmm.自然是没有的. 二,项目燃尽图 三,项目进展 今天并没有什么进展,弄了好久好像也只研究出怎么把JS的功能块插入进去.html的信息提交这些还不知道要怎么弄. 四,问题 ...

  4. Beta冲刺计划---Day0

    Beta阶段报告---Day0 1.需要改进完善的功能   我们上一阶段开发由于开发时间匆忙,对于爬虫耗时的优化没有考虑.优化的空间我在Alpha阶段的总结报告里说过,具体看下图.   这张图显示出爱 ...

  5. beat冲刺计划安排

    1. 团队成员 组长:郭晓迪 组员:钟平辉 柳政宇 徐航 曾瑞 2. 主要计划安排如下: 3. 详细日程任务安排

  6. 201621123057 《Java程序设计》第12周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 面向系统综合设计-图书馆管理系统或购物车 使用流与文件改造你的图书馆管理系统或购物车. 2.1 简述如何 ...

  7. 团队作业7——Beta版本冲刺计划及安排

    上一个阶段的总结: 在Alpha阶段,我们小组已近完成了大部分的功能要求,小组的每一个成员都发挥了自己的用处.经过了这么久的磨合,小组的成员之间越来越默契,相信在接下来的合作中,我们的开发速度会越来越 ...

  8. Android实验报告

    实验名称:Android程序设计 实验时间:2017.5.24 实验人员:20162309邢天岳(结对同学20162313苑洪铭) 实验目的:使用android stuidio开发工具进行基本安卓软件 ...

  9. Flask 扩展 Flask-RESTful

    Flask路由可以指定HTTP请求方法,并在请求函数中根据不同的请求方法,执行不同的逻辑.这样实现一个Restful的请求已经相当简单了 Flask还有更简便的方法,就是其Flask-RESTful扩 ...

  10. [Redis源码阅读]redis持久化

    作为web开发的一员,相信大家的面试经历里少不了会遇到这个问题:redis是怎么做持久化的? 不急着给出答案,先停下来思考一下,然后再看看下面的介绍.希望看了这边文章后,你能够回答这个问题. 为什么需 ...