iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >android小动画:不断扩散的圆点
  • 683
分享到

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

2024-04-02 19:04:59 683人浏览 独家记忆
摘要

 效果图 (ps: 其实就两个半径和透明度一起变化的小圆, 本项目中用来指示指尖位置) 实现原理 监听点击的位置,在父布局中动态增加 自定义的动画View 代码实现 (1)acti

 效果图

(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
    }

   
    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绑定周期)



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
        )
    }

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

--结束END--

本文标题: android小动画:不断扩散的圆点

本文链接: https://www.lsjlt.com/news/158554.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • android小动画:不断扩散的圆点
     效果图 (ps: 其实就两个半径和透明度一起变化的小圆, 本项目中用来指示指尖位置) 实现原理 监听点击的位置,在父布局中动态增加 自定义的动画View 代码实现 (1)acti...
    99+
    2022-11-12
  • 如何利用CSS3动画实现圆圈由小变大向外扩散的效果
    这篇文章将为大家详细讲解有关如何利用CSS3动画实现圆圈由小变大向外扩散的效果,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。css3中新增了一个animation的属性,该属性类似于创建一个animati...
    99+
    2023-06-08
  • Android如何将Glide动态加载不同大小的图片切圆角与圆形
    这篇文章主要介绍了Android如何将Glide动态加载不同大小的图片切圆角与圆形,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Glide加载动态图片首先我们先要去依赖一个g...
    99+
    2023-05-30
    android glide
  • Android 滑动小圆点ViewPager的两种设置方法详解流程
    第一种方法: 一、测试如下,直接设置小圆点不是图标 二、准备工作 1.在drawable创建dot.xml,设置小圆点,比较方便 <?xml version=...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作