無圖無真相,廢話不多說先來看看最終效果:
用法:
1.導入自定義屬性文件(將這個文件放在 res/values 下)
attrs.xml
<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<resources>
<!--帶旋轉動畫的ImageView-->
<declare-styleable name="waterRipplesView">
<!--波的總個數-->
<attr name="waveCount" format="integer"/>
<!--程序一開始就播放波紋漣漪動畫-->
<attr name="waveOnLoad" format="boolean"/>
<!--波的顏色-->
<attr name="waveColor" format="color"/>
</declare-styleable>
</resources></span>
2.哈哈重點來啦 導入
WaterRipplesView.java
<span style="font-size:18px;">package com.example.waterWave;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
/**
* 水波紋效果
* @author zihao
* Email [email protected]
*
*/
public class WaterRipplesView extends View {
private Paint paint;//用於繪製水波的畫筆
private boolean isStarting = true;
private List<Circle> circles = new ArrayList<Circle>();
private int waveCount = 5;//波紋的總個數
private int color = 0x00ce9b;//波紋的顏色
private float breathDirection = 1;//呼吸方向(+1:變亮,-1:變暗)
private float breathSpeed = 0.02f;//呼吸速度
private boolean isBreathing = false;
public WaterRipplesView(Context context) {
super(context);
init(context,null);
}
public WaterRipplesView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context,attrs);
}
public WaterRipplesView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context,attrs);
}
private void init(Context context, AttributeSet attrs) {
paint = new Paint();
/**
* 獲取xml的配置參數
*/
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.waterRipplesView, 0, 0);
try {
waveCount = a.getInteger(R.styleable.waterRipplesView_waveCount, 3);
isStarting = a.getBoolean(R.styleable.waterRipplesView_waveOnLoad,true);
color = a.getColor(R.styleable.waterRipplesView_waveColor,0x00ce9b);
} finally {
a.recycle();
}
}
private int a = 0;
private float breath = 1f;//控制呼吸
@Override
public void onDraw(Canvas canvas) {
float alphaSpeed;
float radiusSpeed;
float hw = getWidth()/2f;
/**
* 根據view的寬度計算半徑和透明度的變化速度,(爲了盡力保證半徑和透明度同時達到最值:255是透明度的最大值)
*/
if(hw >255f){
radiusSpeed = hw/255f;
alphaSpeed = 1f;
}else {
alphaSpeed = 255f/hw;
radiusSpeed = 1f;
}
/**
* 控制呼吸
*/
if(isBreathing){
breath=breath+breathSpeed*breathDirection;
if(breath>1 ){
breathDirection *= -1;//呼吸反向
if(beforBreathIsAwave){
isBreathing = false;
isStarting = true;
breath = 1;
}
}else if(breath <0.001){
breathDirection *= -1;//呼吸反向
if(!beforBreathIsAwave){
isBreathing = false;
isStarting = false;
breath = 1;
}
}
}
/**
* 當達到設定的波距或第一次運行時 添加一個新波
*/
if (++a>= (hw/waveCount) || circles.size()<1){
a = 0;
Circle c = new Circle();
c.setX(getWidth() / 2).setY(getHeight() / 2).setColor(color).setAlpha(255).setRadius(1);
circles.add(c);
}
for (int i= 0;i< circles.size();i++){
Circle temp = circles.get(i);
if(isStarting){
temp.setAlpha(temp.getAlpha() - alphaSpeed);//改變波的透明度
if(temp.getAlpha() <0){
temp.setAlpha(0);
}
temp.setRadius(temp.getRadius() + radiusSpeed);//增加波的半徑
}
paint.setColor(temp.getColor());
int tempAlpha = (int)(temp.getAlpha()*breath);//乘以breath是爲了通過改變透明度達到呼吸的效果
paint.setAlpha(tempAlpha<0?0:tempAlpha);
canvas.drawCircle(temp.getX(), temp.getY(), temp.getRadius(), paint);//繪製波
/**
* 當波的半徑大於本控件的寬大時刪除這個波
*/
if( temp.getRadius() >getWidth() || temp.getAlpha() <0){
circles.remove(temp);
}
}
invalidate();
}
//波開始/繼續進行
public void start() {
isStarting = true;
invalidate();
}
//波暫停
public void stop() {
isStarting = false;
invalidate();
}
public boolean isStarting() {
return isStarting;
}
private boolean beforBreathIsAwave = true;
/**
* 此方法調用一次波會呼吸一次
*/
public synchronized void breath(){
this.beforBreathIsAwave = isStarting;
if(beforBreathIsAwave){
breath = 1;
breathDirection =-1;
}
else {
breath = 0.01f;
breathDirection = 1;
}
start();
isBreathing = true;
}
/**
* 代表每個波的類
*/
public class Circle{
private float x;
private float y;
private int color;
private float alpha;
private float radius;
public float getRadius() {
return radius;
}
public Circle setRadius(float radius) {
this.radius = radius;
return this;
}
public float getX() {
return x;
}
public Circle setX(float x) {
this.x = x;
return this;
}
public float getY() {
return y;
}
public Circle setY(float y) {
this.y = y;
return this;
}
public int getColor() {
return color;
}
public Circle setColor(int color) {
this.color = color;
return this;
}
public float getAlpha() {
return alpha;
}
public Circle setAlpha(float alpha) {
this.alpha = alpha;
return this;
}
}
}</span>
3.在你的佈局文件中引用
例如:
<span style="font-size:18px;"><?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/com.example.waterWave"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.example.waterWave.WaterRipplesView
android:id="@+id/wave"
android:layout_width="180dp"
android:layout_height="180dp"
app:waveCount="5"
app:waveOnLoad="true"
app:waveColor="#00ce9b"/>
</LinearLayout>
</span>
github demo地址:https://github.com/HelloWorldZH/tools.git 或 https://github.com/HelloWorldZH/tools
好了,就這樣吧 具體解釋代碼中的註釋寫的夠清楚了 歡迎給我指出問題 Email:[email protected]