android小动画:不断扩散的圆点
效果图
(ps: 其实就两个半径和透明度一起变化的小圆, 本项目中用来指示指尖位置)
实现原理
监听点击的位置,在父布局中动态增加 自定义的动画View
代码实现
(1)activity
点击监听及添加View
// 触屏点击位置 private var pointX: Int = 0 private var pointY: Int = 0 private var circleView: SpreadCircleView?= null // 触摸点击 override fun onTouchEvent(event: MotionEvent?): Boolean { when (event!!.action) { MotionEvent.ACTION_DOWN -> { pointX = event.x.toInt() pointY = event.y.toInt() } MotionEvent.ACTION_MOVE -> { } MotionEvent.ACTION_UP ->{ addPointCircle() } else -> { } } return true }
/** * 添加自动扩散的圆点 View */ fun addPointCircle(){ if(circleView == null){ circleView = SpreadCircleView(this); circleView?.let{ lifecycle.addObserver(it) } } binding.rootLayout.removeView(circleView) circleView?.let{ // 宽度和高度相同 val width = it.maxRadius.toInt() * 2 var lp = FrameLayout.LayoutParams(width, width ) lp.marginStart = pointX - width/2 lp.topMargin = pointY - width/2 binding.rootLayout.addView(it, lp) it.startAnimation() } }
(2)圆点View
实现(属性动画,根据动画进度来确定圆的当前半径,利用LifecycleObserver
绑定周期)
/** * Created by Liming on 2021/9/1 15:36 * 不断扩散的小圆, 用于显示指尖位置 */ class SpreadCircleView : View, LifecycleObserver { private var paint: Paint = Paint() // 圆圈最大半径 val maxRadius = 25.toPx() // 圆圈中心点 var centerX:Int = 0 var centerY:Int = 0 private var animator : ObjectAnimator? = null // 是否已开始绘制第二个圆 var hasDrawCicle2 = false // 动画进度 private var progress = 0f set(value){ field = value // 刷新界面 invalidate() } constructor(context: Context?) : super(context) constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) init{ paint.style = Paint.Style.FILL paint.color = ContextCompat.getColor(context, R.color.rect_orange) // #ffa200 paint.strokeWidth = 3.toPx() paint.isAntiAlias = true // 防锯齿 } override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) //圆心位置 centerX = w / 2; centerY = h / 2; } override fun draw(canvas: Canvas?) { super.draw(canvas) // 第一个圆 drawCircle(canvas, progress) // 第二个圆 if(hasDrawCicle2 || progress > 0.5f ){ // 第一个圆的进度第一次达到 0.5 时,开始绘制第二个圆, hasDrawCicle2 = true var progress2 = progress + 0.5f if(progress2 > 1){ progress2 = progress2 - 1 } drawCircle(canvas, progress2) } } /** * 根据进度绘制 半径和透明度变化的圆 */ fun drawCircle(canvas: Canvas?, animProgress: Float){ // 透明度 0 - 255 var alpha = 255 * (1 - animProgress) paint.alpha = alpha.toInt() var radius = maxRadius * animProgress // 绘制圆 canvas?.drawCircle(centerX.toFloat(), centerY.toFloat(), radius, paint ) } private fun getAnimator(): ObjectAnimator?{ if(animator == null){ animator = ObjectAnimator.ofFloat(this, "progress", 0f, 0.99f) animator?.duration = 1500 animator?.repeatCount = -1 //-1代表无限循环 animator?.interpolator = LinearInterpolator() } return animator } fun startAnimation() { // 开始动画 getAnimator()?.start() hasDrawCicle2 = false } @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun resume() { // 开始动画 animator?.start() } @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) fun pause() { animator?.pause() } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun destory() { // 清除动画,避免内存泄漏, animator?.cancel() clearAnimation() } }
补充一个用到的扩展函数
fun Int.toPx(): Float{ val resources = Resources.getSystem() return TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), resources.displayMetrics ) }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
赞 (0)