Android(安卓)实现水波纹动效
16lz
2021-12-04
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 //波动属性设置
更多相关文章
- (4.2.15)【android开源工具】Android画柱状图
- android 设置各种颜色 android:background="@color/white"
- Android(安卓)设置圆角背景
- android 朗读tts_如何设置Android以大声朗读您的文本
- EditText焦点问题
- Android(安卓)APK权限大全
- Android(安卓)统计图表引擎 AChartEngine(三) - 示例源码折线图
- Android控件属性集锦
- 安卓开发问题记录