zoukankan      html  css  js  c++  java
  • 自定义动画的实现-实例

    一:效果

    上面是一个大嘴在吃一个球,下面是三个球分别一大一小的变化

             

    GitHub地址:https://github.com/luofangli/Custom_Animation

    代码:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.example.custom_animation.BigEatSmallCircle
    android:id="@+id/myview"
    android:layout_width="0dp"
    android:layout_height="200dp"
    android:layout_marginStart="10dp"
    android:layout_marginTop="10dp"
    android:layout_marginEnd="10dp"
    android:background="@color/design_default_color_primary"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.5"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

    <com.example.custom_animation.CircleFollowJump
    android:id="@+id/circleAnima"
    android:layout_width="0dp"
    android:layout_height="200dp"
    android:layout_marginStart="10dp"
    android:layout_marginEnd="10dp"
    android:background="@color/black"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/myview" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    package com.example.custom_animation

    import android.animation.ValueAnimator
    import android.animation.ValueAnimator.INFINITE
    import android.animation.ValueAnimator.ofFloat
    import android.content.Context
    import android.graphics.*
    import android.util.AttributeSet
    import android.util.Log
    import android.view.View
    import androidx.core.graphics.toRectF

    class BigEatSmallCircle:View {
    //小圆的半径
    private var smallArcRadius = 0f
    //大圆的动画因子
    private var sweepAngle = 0f
    private var startAngle = 0f
    //小圆的x,y坐标
    private var smallCircleX = 0f
    private var smallCircleY = 0f
    //小圆x的最大距离
    private var smallCircleBigX = 0f
    //大圆的动画
    private var valueAnimatorBigArc = ValueAnimator()
    //小圆的动画
    private var valueAnimatorSmallCircle = ValueAnimator()
    //画大圆的paint
    private val paintBigCircle: Paint by lazy {
    Paint().apply {
    style = Paint.Style.FILL
    color = Color.RED
    }
    }
    constructor(context: Context):super(context){}
    constructor(context: Context,attributeSet: AttributeSet):super(context,attributeSet){}

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    super.onSizeChanged(w, h, oldw, oldh)
    Log.v("lfl","在OnSizeChanged")
    ArcRect()
    }

    override fun onDraw(canvas: Canvas?) {
    super.onDraw(canvas)
    //画大圆
    canvas?.drawArc(ArcRect(),startAngle,sweepAngle,true,paintBigCircle)
    //画小圆
    canvas?.drawCircle(smallCircleX,smallCircleY,smallArcRadius,paintBigCircle)
    }
    //确定圆弧的矩形区域 并且确定小圆的x,y坐标
    private fun ArcRect():RectF{
    //距离画布左右边缘的距离为
    var xDistance = 0f
    //距离画布上下边缘的距离
    var yDistance = 0f
    //当画布的高度小于宽度时
    if (measuredHeight<measuredWidth){
    smallArcRadius = measuredHeight/6f
    xDistance = (measuredWidth-8.5f*smallArcRadius)/2
    }else{
    smallArcRadius = measuredWidth/8.5f
    yDistance = (measuredHeight-6*smallArcRadius)/2
    }
    //确定小圆的x,y坐标
    smallCircleBigX = xDistance+7.5f*smallArcRadius
    smallCircleY = yDistance+3*smallArcRadius
    //返回大圆的矩形区域
    return RectF(xDistance,yDistance,
    (xDistance+6*smallArcRadius).toFloat(),
    (yDistance+6*smallArcRadius).toFloat())
    }
    //大圆的动画因子的改变
    private fun changBigArcAngle(){
    valueAnimatorBigArc = ValueAnimator.ofFloat(0f,45f).apply {
    duration = 1000L
    repeatCount = INFINITE
    addUpdateListener {
    val value = it.animatedValue as Float
    startAngle = value
    sweepAngle = 360f-value*2
    invalidate()
    }
    }
    //小球移动的动画
    valueAnimatorSmallCircle = ValueAnimator.ofFloat(0f,5.5f*87.5f).apply {
    duration = 1000L
    repeatCount = INFINITE
    addUpdateListener {
    val value = it.animatedValue as Float
    smallCircleX = smallCircleBigX - value
    invalidate()
    }
    }
    }
    //启动动画
    fun startAnima(){
    changBigArcAngle()
    valueAnimatorBigArc.start()
    valueAnimatorSmallCircle.start()
    }
    }

    package com.example.custom_animation

    import android.animation.ValueAnimator
    import android.content.Context
    import android.graphics.Canvas
    import android.graphics.Color
    import android.graphics.Paint
    import android.util.AttributeSet
    import android.util.Log
    import android.view.CollapsibleActionView
    import android.view.ContextMenu
    import android.view.View

    class CircleFollowJump:View {
    //圆的半径
    private var raduis = 0f
    //圆在y轴上的位置
    private var cy = 0f
    //圆的x的位置
    private val cxArray = mutableListOf<Float>()
    //存圆的半径
    private val raduisArray = arrayOf(0f,0f,0f)
    //存入动画
    private val valueAnimatorArray = mutableListOf<ValueAnimator>()
    //准备画笔
    private val paint_circle:Paint by lazy {
    Paint().apply {
    style = Paint.Style.FILL
    color = Color.RED
    }
    }
    constructor(context: Context):super(context){}
    constructor(context: Context,attributeSet: AttributeSet):super(context,attributeSet){}

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    super.onSizeChanged(w, h, oldw, oldh)
    sure_centerAndradius()
    }

    override fun onDraw(canvas: Canvas?) {
    super.onDraw(canvas)
    //画三个圆
    draw3circle(canvas)
    }
    //确定中心点,以及圆的最大半径
    private fun sure_centerAndradius(){
    //临时判断值,
    val temp = measuredHeight/2f
    if (7*temp>measuredWidth){
    //圆的半径大了,
    raduis = measuredWidth/7f
    }else{
    //圆的半径刚刚好
    raduis = temp
    }
    //在x轴上圆离两边的距离
    val xDistance = (measuredWidth-7*raduis)/2
    //在y轴上圆离两边的距离
    val yDistance = (measuredHeight-2*raduis)/2
    //圆中心点y
    cy = yDistance+raduis
    //将半径存入数组中
    //各圆中心点x
    for (i in 0..2){
    raduisArray[i] = raduis
    val cx = (xDistance+raduis+i*2.5*raduis).toFloat()
    cxArray.add(cx)
    }
    }
    //画三个圆
    private fun draw3circle(canvas: Canvas?){
    for (i in 0..2){
    canvas?.drawCircle(cxArray[i],cy,raduisArray[i],paint_circle)
    }
    }
    //动画因子的改变
    private fun changeRadius(){
    Log.v("lfl","在改变因子方法中")
    for (i in 0..2){
    ValueAnimator.ofFloat(1f,0.1f,1f).apply {
    duration = 1000
    repeatCount = ValueAnimator.INFINITE
    startDelay = i*155L
    addUpdateListener {
    val value = it.animatedValue as Float
    //各圆半径为
    raduisArray[i] = raduis*value
    invalidate()
    }
    valueAnimatorArray.add(this)
    }
    }
    }
    //启动动画
    fun startAnima(){
    changeRadius()
    for (i in 0..2){
    valueAnimatorArray[i].start()
    }
    }

    }

    package com.example.custom_animation

    import android.animation.ValueAnimator
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import android.util.Log
    import kotlinx.android.synthetic.main.activity_main.*

    class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    myview.startAnima()
    circleAnima.startAnima()


    }
    }
    
    
    
    
    
    
  • 相关阅读:
    [书目20071127]图书 时间陷阱 目录
    [文摘20071113]十四项心理定律
    Win2003下:JDK1.5 + Eclipse3.2 + Tomcat6.0 + tomcatPluginV32
    [转]初试eclipse mysql
    [转]测试工具
    [转]如何进行软件需求分析
    OA流程设计尝试:Div步骤拖动
    [转]需求分析的20条法则
    Eclipse 3.2 + Tomcat 5.5 + Lomboz 3.2 简单配置
    [转]软件项目管理中的风险管理研究
  • 原文地址:https://www.cnblogs.com/luofangli/p/14774252.html
Copyright © 2011-2022 走看看