美文网首页无名之辈的Android之路
自定义View的使用:数据加载进度动画

自定义View的使用:数据加载进度动画

作者: 搬码人 | 来源:发表于2021-08-24 19:06 被阅读0次

    引入

    在申请网络数据的过程中,需要界面展示正在获取数据的状态。比如在腾讯视频获取数据未完成时,屏幕中央会有三个模型缩放的动画。要实现这样的动画效果,就需要利用自定义View来实现


    绘制草图

    自定义View的创建步骤

    • 1 重写构造方法
     constructor(context: Context):super(context){}
        constructor(context: Context,attrs:AttributeSet?):super(context,attrs){}
        constructor(context: Context,attrs: AttributeSet?,style:Int):super(context,attrs,style){}
    
    • 2 继承onSizeChanged方法对view的元素进行设置
      如:自定义画圆设置半径与圆心
     override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
            super.onSizeChanged(w, h, oldw, oldh)
            //两种情况设置圆的半径
            radius = if ((measuredHeight/2)*7 <= measuredWidth){
                measuredHeight/2f
            }else{
                measuredWidth/7f
    
            }
            cy = measuredHeight/2f
            cx = measuredWidth/2f -2.5f*radius
        }
    
    • 3 继承onDraw方法进行绘制
      画圆的几个重要条件:半径,圆心,画笔Paint()

    两种画多个圆的方式

    -1 普通的画圆方式
    直接多次调用canvas?.drawCircle

            canvas?.drawCircle(cx,cy,radius,mPaint)
            canvas?.drawCircle(cx+2.5f*radius,cy,radius,mPaint)
            canvas?.drawCircle(cx+5f*radius,cy,radius,mPaint)
    

    -2 通过移动画布的方式
    canvas?.save():保存当前的状态
    canvas?.translate:移动画布
    canvas?.restore:画布恢复到初始状态,比如位置返回至初始的位置。

     override fun onDraw(canvas: Canvas?) {
            super.onDraw(canvas)
            canvas?.save()
            //将画布移动到cx cy的位置
            //cx 和 cy表示移动的距离
            canvas?.translate(cx,cy)
            //绘制一个圆
            canvas?.drawCircle(0f,0f,radius,mPaint)
            //移动画布至第二个圆的圆心
            canvas?.translate(2.5f*radius,0f)
            //绘制第二个圆
            canvas?.drawCircle(cx,cy,radius,mPaint)
            
            //绘制第三个圆
            canvas?.translate(2.5f*radius,0f)
            canvas?.drawCircle(0f,0f,radius,mPaint)
            canvas?.restore()
            
        }
    

    自定义进度代码

    创建createAnimator()方法实现缩放动画。
    为使三个圆有一次缩放的效果,使用数组的方式将动画的延迟时间和初始比例都放进数组中,当然动画对象也需要放入数组中,在createAnimator方法中利用for()依次对动画对象mAnimators进行配置。
    ValueAnimator属性动画
    invalidate触发绘制(刷新)

    package com.example.falltype
    
    import android.animation.ValueAnimator
    import android.content.Context
    import android.graphics.Canvas
    import android.graphics.Paint
    import android.util.AttributeSet
    import android.view.View
    
    /**
     *@Description
     *@Author PC
     *@QQ 1578684787
     */
    class PulseLoadingView:View {
        //圆的半径
        private var radius = 0f
        //第一个圆的坐标
        private var cx = 0f
        private var cy = 0f
        //画笔
        private val mPaint = Paint().apply {
            color = context.resources.getColor(R.color.main_purple)
            style = Paint.Style.FILL
        }
        //动画对象
        private  var mAnimators = mutableListOf<ValueAnimator>()
        //保存延时的时间
        private var delays = arrayOf(100L,200L,300L)
        //保存每个圆缩放的比例
        private val scales = arrayOf(0.2f,0.2f,0.2f)
        constructor(context: Context):super(context){}
        constructor(context: Context,attrs:AttributeSet?):super(context,attrs){}
        constructor(context: Context,attrs: AttributeSet?,style:Int):super(context,attrs,style){}
    
        override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
            super.onSizeChanged(w, h, oldw, oldh)
            //两种情况设置圆的半径
            radius = if ((measuredHeight/2)*7 <= measuredWidth){
                measuredHeight/2f
            }else{
                measuredWidth/7f
    
            }
            cy = measuredHeight/2f
            cx = measuredWidth/2f -2.5f*radius
        }
    
        override fun onDraw(canvas: Canvas?) {
            super.onDraw(canvas)
            for (i in 0..2){
                canvas?.save()
                canvas?.translate(cx+i*2.5f*radius,cy)
                canvas?.scale(scales[i],scales[i])
                canvas?.drawCircle(0f,0f,radius,mPaint)
                canvas?.restore()
            }
    
    //一般的画圆方式
    //        canvas?.drawCircle(cx,cy,radius,mPaint)
    //        canvas?.drawCircle(cx+2.5f*radius,cy,radius,mPaint)
    //        canvas?.drawCircle(cx+5f*radius,cy,radius,mPaint)
    
        }
        private fun createAnimator(){
            for (i in 0..2) {
                ValueAnimator.ofFloat(0.2f, 1f).apply {
                    duration = 600
                    startDelay = delays[i] // 设置每个圆对应的延迟时间
                    repeatCount = ValueAnimator.INFINITE
                    addUpdateListener {
                        scales[i] = it.animatedValue as Float
                        invalidate()
                    }
                    mAnimators.add(this)
                }
            }
        }
        private fun start(){
            for (item in mAnimators){
                item.start()
            }
        }
        private fun stop(){
            for (item in mAnimators){
                item.end()
            }
        }
       //启动动画
        fun show(){
            createAnimator()
           start()
        }
    
        //隐藏动画
        fun hide(){
            stop()
        }
    
    }
    

    在MainActivity设置按钮点击事件,欣赏进度动画的效果

    package com.example.falltype
    
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import com.example.falltype.databinding.ActivityMainBinding
    
    class MainActivity : AppCompatActivity() {
        lateinit var mbinding:ActivityMainBinding
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            mbinding = ActivityMainBinding.inflate(layoutInflater)
            setContentView(mbinding.root)
    
            mbinding.mStart.setOnClickListener {
                mbinding.loadingView.show()
            }
            mbinding.stop.setOnClickListener {
                mbinding.loadingView.hide()
            }
        }
    }
    

    运行效果
    点击start


    数据加载动画效果

    相关文章

      网友评论

        本文标题:自定义View的使用:数据加载进度动画

        本文链接:https://www.haomeiwen.com/subject/jzldiltx.html