1. 程式人生 > >週末閒著無聊分享一個自己寫的帶呼吸效果的android水波紋自定義view

週末閒著無聊分享一個自己寫的帶呼吸效果的android水波紋自定義view

無圖無真相,廢話不多說先來看看最終效果:


用法:

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]