帶呼吸效果的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]

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章