欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

android小动画:不断扩散的圆点

程序员文章站 2022-03-25 09:37:56
效果图(ps: 其实就两个半径和透明度一起变化的小圆, 本项目中用来指示指尖位置)实现原理监听点击的位置,在父布局中动态增加 自定义的动画view代码实现(1)activity点击监听及添加view...

 效果图

(ps: 其实就两个半径和透明度一起变化的小圆, 本项目中用来指示指尖位置)

android小动画:不断扩散的圆点

实现原理

监听点击的位置,在父布局中动态增加 自定义的动画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
        )
    }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。