首页 > 解决方案 > Kotlin - 多个动画同时和/或相互重复

问题描述

我正在尝试在 Android Studio 中创建一个游戏应用程序。概念是:有圆圈掉下来,您需要单击/按下它们以使它们消失,然后才能触摸屏幕底部的一条线。为此,我创建了一个带有圆圈作为图像的 ImageView。我让它出现在顶部,它以缓慢的速度向下移动。当我按下它时,它会消失。问题是,第二个圆圈出现在第一个圆圈之后,这很好,但是向下动画没有开始,而且 OnClickListener 也不起作用。

下面是创建圆的代码:

/*Creation of ball via imageView.
ImageView is created on the current Activity Layout with the circle as image.
ImageView is 200x200 and appears in the middle of the screen (horizontal) on top.
*/
private fun drawBall(){
    val imageView = ImageView(this)
    imageView.setImageDrawable(getDrawable(R.drawable.ball_1))
    imageView.layoutParams = LinearLayout.LayoutParams(200, 200)
    imageView.x = (width/2.5).toFloat()
    layout.addView(imageView)
    moveBall(imageView)
}

这是动画开始的代码和圆圈消失的 OnClickListener:

//Animation of ball falling down.
private fun moveBall(imageView: ImageView){
    val valueAnimator = ValueAnimator.ofFloat(0f, height*0.68.toFloat() )
    valueAnimator.addUpdateListener {
        val value = it.animatedValue as Float
        imageView.translationY = value
    }

    valueAnimator.interpolator = LinearInterpolator()
    valueAnimator.duration = 2500
    valueAnimator.start()

    //Shooting the ball and incrementing score
    imageView.setOnClickListener(){
        imageView.visibility = View.INVISIBLE
        var currentScore = textView_score.text.toString().toInt()
        currentScore++
        textView_score.text = currentScore.toString()
    }
}

在这里,您可以找到我试图创建要倒下的圆的多个实例的代码:

//Multiple instances of the falling ball animation.
private fun startBalls(){
    val runnable = Runnable { drawBall() }
    runnable.run(){
        drawBall()
    }

    val exec = ScheduledThreadPoolExecutor(1)
    val period : Long = 1000
    exec.scheduleAtFixedRate(runnable,0, period, TimeUnit.MILLISECONDS)
    val delay : Long = 1000
    exec.scheduleWithFixedDelay(runnable, 0, delay, TimeUnit.MILLISECONDS)
}

我认为我的主要问题是我试图创建圆圈的多个实例。先感谢您。

标签: androidmultithreadingandroid-studioanimationkotlin

解决方案


Logging frommoveBall()显示RunnableScheduledThreadPoolExecutor. 更具体地说,下一行 after valueAnimator.start()根本不执行(第一次“触摸” UI 元素会导致非 UI 线程中的异常”),因此OnClickListener除了第一个ImageView.

由于与 a重用相同的实例似乎也是一个问题,因此您可以使用自定义类并让它 在 UI 线程上调用:RunnableScheduledThreadPoolExecutorRunnabledrawBall()

class MyRunnable(val functionToInvoke: () -> Unit): Runnable {
    override fun run() {
        Handler(Looper.getMainLooper()).post(Runnable {
            //this will run on the UI thread
            functionToInvoke.invoke()
      })
    }
}

用途startBalls()

val exec = ScheduledThreadPoolExecutor(1)
val period : Long = 1000
exec.scheduleAtFixedRate(MyRunnable({drawBall()}),0, period, TimeUnit.MILLISECONDS)
val delay : Long = 1000
exec.scheduleWithFixedDelay(MyRunnable({drawBall()}), 0, delay, TimeUnit.MILLISECONDS)

推荐阅读