主要Android动画制作与简单涉及自定义View(自定义View)

1.View相关的属性设置

1.1 创建View类

直接继承View,多用于作图

继承FrameLayout,多用于xml内部含多个控件的情况

1.1.1 代码创建控件

constructor(context:Context):super(context){}

1.1.2 xml创建文件

constructor(context: Context, attrs: AttributeSet?):super(context,attrs){}

1.1.3 xml里设置了style样式时创建文件

constructor(context: Context, attrs: AttributeSet?, style:Int):super(context, attrs,style){}

1.2 由xml自定义view的特殊操作

init { 
        // 讲layout布局文件和当前这个类相关联
        val layoutInflater = LayoutInflater.from(context)  // 使用布局解析器解析出来
        val lp = FrameLayout.LayoutParams( // 创建一个布局参数
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT)
        addView(binding.root,lp)//将解析出来的View添加到当前的容器里面 显示出来
}

我先获取好了对应的binding, 这里是获取布局解析器,并得到一个布局参数

1.3 设置View的自定义属性

 1.3.1 在value中创建attrs ,resource File,找到对应的自定义View,并规划自定义的属性

注意除了枚举类 enum可以给对应值 ; 其他属性都只给属性名和对应得基本类型

1.2.2 解析自定义属性得方式

 找到context和AttributeSet,先将属性设置器与自定义的attrs传进去,再一个一个属性,通过getString等方法设置 属性对应的值

最后记得recycle

2.绘制动画方法

2.1准备工具

2.1.1 懒加载画笔

2.2 测量此控件尺寸

  固定的套路哦

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        //定义变量保存最终的宽和高
        var mWidth = 0
        var mHeight = 0
        //获取外部设置的模式
        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val widthSize = MeasureSpec.getSize(widthMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)
        val heightSize = MeasureSpec.getSize(heightMeasureSpec)

        when (widthMode){
            MeasureSpec.EXACTLY -> mWidth = widthSize
            MeasureSpec.AT_MOST -> mWidth = textWidth()
        }
        when(heightMode){
            MeasureSpec.EXACTLY -> mHeight = heightSize
            MeasureSpec.AT_MOST ->mHeight = textHeight()
        }
        //告诉外部(父容器) 自己的尺寸
        setMeasuredDimension(mWidth,mHeight)
    }

2.2.1 封装数据换算方法

dp To px 最重要!!!

 fun px2dp(px:Int):Int{
        return (px / context.resources.displayMetrics.density).toInt()
    }

    fun dp2px(dp:Int) = context.resources.displayMetrics.density * dp

    fun sp2px(sp:Float):Float{
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,sp,context.resources.displayMetrics)
    }

2.3 封装各个绘制部分

2.3.1 静态图像

找到几何关系 ,确定绘制基本要素

2.3.2 动态图像

重写onSizeChanged() ,重新计算整个高度与宽度

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        //重新计算音浪的宽度 高度 间距
        if (height != mWaveHeight){
            mWaveHeight = height
        }
        if (width != (mWaveWidth*3+2*mSpace)){
            mSpace = width / 10
            mWaveWidth = (width - 2*mSpace)/3
        }
    }

设置属性动画 ,此处为多个属性一起设置 ,设置的类型 补间动画同样有

 private val mAnimatorSet: AnimatorSet by lazy {
        //保存三个属性动画
        val animators = arrayListOf<Animator>()
        for (i in 0 until 3)
            ValueAnimator.ofFloat(0f,1f).apply {
                duration = mWavePase.toLong()
                repeatCount = ValueAnimator.INFINITE//重复次数:无限
                repeatMode = ValueAnimator.REVERSE//重复模式:到终点即反向
                startDelay = i*mDelay//各波浪间隔

                animators.add(this)
                addUpdateListener {//实时更新 各波浪高度
                    mHeightRateArray[i] = it.animatedValue as Float
                    invalidate()
                }
            }
        AnimatorSet().apply {/**所有属性动画一起开启*/
            playTogether(animators)
        }
    }

属性动画开启,暂停与结束

 fun startAnimation(){
        mAnimatorSet.start()
    }
    fun pauseAnimation(){
        mAnimatorSet.pause()
    }
    fun stopAnimation(){
        mAnimatorSet.cancel()
    }

2.3.3 不要忘记onDraw()方法内绘制图案

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值