Android 实现水波纹动效

WaterRippleView核心文件

package com.manss.myapplication.widget.animationimport android.content.Contextimport android.graphics.Canvasimport android.graphics.Colorimport android.graphics.Paintimport android.util.AttributeSetimport android.view.Viewimport com.manss.myapplication.widget.DisplayUtilimport java.util.*/** * 水波纹动画view */class WaterRippleView : View {    private var mMaxWaveAreaRadius = 0f    private var mWaveIntervalSize = 0f//波距 = 0f    private var mStirStep = 0f // 波移动的步幅 = 0f    private var mWidth = 0    private var mWaveStartWidth = 0f// px = 0f    private var mWaveEndWidth = 0f// px 最大半径,超过波消失 = 0f    private var mWaveColor = 0    private var mViewCenterX = 0f    private var mViewCenterY = 0f    private val rippleColor = Color.BLUE    //波动属性设置    private val mWavePaint = Paint()    //中心点属性设置    private val mWaveCenterShapePaint = Paint()    private var mFillAllView = false    private var mFillWaveSourceShapeRadius = 0f    private val mWaves: MutableList = ArrayList()    constructor(context: Context?, attrs: AttributeSet?) : super(        context,        attrs    ) {        init()    }    constructor(context: Context?) : super(context) {        init()    }    private fun init() {        setWaveInfo(2f, 1f, 2f, 15f, rippleColor)        mWaveIntervalSize = DisplayUtil.dip2px(context, 20f).toFloat()        mWidth = DisplayUtil.dip2px(context, 2f)        //初始化波动最大半径        mWaveEndWidth = DisplayUtil.dip2px(context, 100f).toFloat()    }    override fun onLayout(        changed: Boolean, left: Int, top: Int, right: Int,        bottom: Int    ) {        super.onLayout(changed, left, top, right, bottom)        mViewCenterX = width / 2.toFloat()        mViewCenterY = height / 2.toFloat()        var waveAreaRadius = mMaxWaveAreaRadius        waveAreaRadius = if (mFillAllView) {            Math.sqrt(                (mViewCenterX * mViewCenterX                        + mViewCenterY * mViewCenterY).toDouble()            ).toFloat()        } else {            Math.min(mViewCenterX, mViewCenterY)        }        if (mMaxWaveAreaRadius != waveAreaRadius) {            mMaxWaveAreaRadius = waveAreaRadius            resetWave()        }    }    override fun onDraw(canvas: Canvas) {        super.onDraw(canvas)        stir()        for (w in mWaves) {            mWavePaint.color = w!!.color            mWavePaint.strokeWidth = mWidth.toFloat()            mWavePaint.alpha = w.alpha            canvas.drawCircle(mViewCenterX, mViewCenterY, w.radius, mWavePaint)        }        if (mFillWaveSourceShapeRadius > 0f) {            canvas.drawCircle(                mViewCenterX, mViewCenterY,                mFillWaveSourceShapeRadius, mWaveCenterShapePaint            )        }        postInvalidateDelayed(FPS.toLong())    }    /**     * 波     *     */    internal inner class Wave {        var radius = 0f        var width = 0f        var color = 0        var alpha = 0        fun reset() {            radius = 0f            width = mWaveStartWidth            color = mWaveColor        }        override fun toString(): String {            return ("Wave [radius=" + radius + ", width=" + width + ", color="                    + color + "]")        }        init {            reset()        }    }    private var mLastRmoveWave: Wave? = null    /**     * 触发涌动传播     */    private fun stir() {        val nearestWave = if (mWaves.isEmpty()) null else mWaves[0]        if (nearestWave == null || nearestWave.radius >= mWaveIntervalSize) {            var w: Wave? = null            if (mLastRmoveWave != null) {                w = mLastRmoveWave                mLastRmoveWave = null                w!!.reset()            } else {                w = Wave()            }            mWaves.add(0, w)        }        val waveWidthIncrease = mWaveEndWidth - mWaveStartWidth        val size = mWaves.size        for (i in 0 until size) {            val w = mWaves[i]            var rP = w!!.radius / mMaxWaveAreaRadius            if (rP > 1f) {                rP = 1f            }            w.width = mWaveStartWidth + rP * waveWidthIncrease            w.radius += mStirStep            w.color = rippleColor            w.alpha = 255 / (i + 1)        }        val farthestWave = mWaves[size - 1]        if (farthestWave!!.radius > mWaveEndWidth) {            mWaves.removeAt(size - 1)        }    }    /**     * 如果true会选择view的最大的对角线作为活动半径     *    */    fun setFillAllView(fillAllView: Boolean) {        mFillAllView = fillAllView        resetWave()    }    fun resetWave() {        mWaves.clear()        postInvalidate()    }    /**     * 填充波形起源的中心点     *     * @param radius 半径大小     */    fun setFillWaveSourceShapeRadius(radius: Float) {        mFillWaveSourceShapeRadius = radius    }    /**     * 设置波形属性     *     * @param intervalSize 两个波形之间的间距     * @param stireStep    波形移动速度     * @param startWidth   起始波形宽度     * @param endWidth     终止波形宽度     * @param color        波形颜色     */    fun setWaveInfo(        intervalSize: Float, stireStep: Float,        startWidth: Float, endWidth: Float, color: Int    ) {        mWaveIntervalSize = intervalSize        mStirStep = stireStep        mWaveStartWidth = startWidth        mWaveEndWidth = endWidth        setWaveColor(color)        resetWave()    }    /**     * 设置波形颜色     *     * @param color     */    fun setWaveColor(color: Int) {        mWaveColor = color        mWaveCenterShapePaint.color = mWaveColor    }    companion object {        private const val FPS = 1000 / 40    }    init {        mWavePaint.isAntiAlias = true        mWavePaint.style = Paint.Style.FILL    }    init {        mWaveCenterShapePaint.isAntiAlias = true        mWaveCenterShapePaint.style = Paint.Style.FILL    }}

 

util文件

package com.manss.myapplication.widget;import android.content.Context;public class DisplayUtil {    public static int dip2px(Context context, float dipValue) {        final float scale = context.getResources().getDisplayMetrics().density;        return (int) (dipValue * scale + 0.5f);    }}

activity_water_ripple_view.xml文件

<?xml version="1.0" encoding="utf-8"?>                

方法调用

 

package com.example.myapplicationimport android.os.Bundleimport androidx.appcompat.app.AppCompatActivityimport com.manss.myapplication.Rimport com.manss.myapplication.widget.DisplayUtilimport com.manss.myapplication.widget.animation.WaterRippleView/** * 水波纹动画 */class WaterRippleActivity :AppCompatActivity(){    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_water)        var waterRipple: WaterRippleView = findViewById(R.id.activity_water_ripple_view)        waterRipple.setFillWaveSourceShapeRadius(DisplayUtil.dip2px(this,15f).toFloat())//        waterRipple.setFillAllView(true)//        waterRipple.setWaveColor(android.R.color.holo_blue_bright)    }}

总结,如果波纹是线条效果,修改WaterRippleView文件的

    init {        mWavePaint.isAntiAlias = true        mWavePaint.style = Paint.Style.FILL    }

修改后

    init {        mWavePaint.isAntiAlias = true        mWavePaint.style = Paint.Style.STROKE    }

修改波纹半径

    //初始化波动最大半径        mWaveEndWidth = DisplayUtil.dip2px(context, 100f).toFloat()

修改波纹颜色

  private val rippleColor = Color.BLUE    //波动属性设置

 

更多相关文章

  1. (4.2.15)【android开源工具】Android画柱状图
  2. android 设置各种颜色 android:background="@color/white"
  3. Android(安卓)设置圆角背景
  4. android 朗读tts_如何设置Android以大声朗读您的文本
  5. EditText焦点问题
  6. Android(安卓)APK权限大全
  7. Android(安卓)统计图表引擎 AChartEngine(三) - 示例源码折线图
  8. Android控件属性集锦
  9. 安卓开发问题记录

随机推荐

  1. 让star也具有CheckBox 功能
  2. android程序在Layout中设置控件水平或垂
  3. Android TextView 文字居中
  4. android 布局文件详解
  5. linux ubuntu android SDK安装
  6. Android系统自带样式(@android:style/)
  7. android layout 属性大全
  8. Android修改默认控件焦点不highlight
  9. Android EditText inputType同时设置text
  10. 安装Android Studio——Installing Andro