I'm trying to animate an ImageView with a list of pictures, iterating through them quickly, so that it creates the impression of an animation. Sadly it does give the alert: Skipped 391 frames! The application may be doing too much work on its main thread.
This is my Main-Activity which implements the Animator-interface.
override fun onCreate(savedInstanceState: Bundle?) {
GlobalScope.launch {
show(Action.Idle)
}
}
My Animator show() function (runs the Runnables with android.os.Handler):
fun show(action: Action){
getHandler().removeCallbacksAndMessages(null)
when (action) {
Action.MoveRight -> getHandler().post(getRight())
Action.MoveUp -> getHandler().post(getUp())
Action.MoveDown -> getHandler().post(getDown())
Action.MoveLeft -> getHandler().post(getLeft())
Action.Idle -> getHandler().post(idle())
}
}
My idle function (anim.idle is an array of Ints/Drawables):
fun idle() = object : Runnable{
override fun run() {
val anim = getAnimation()
repeat(anim.idle!!.size){
getActivity().runOnUiThread {
binding.figure.setImageResource(anim.idle[it])
binding.figure.invalidate()
}
Thread.sleep(500)
}
getHandler().postDelayed(this,5000)
}
}
CodePudding user response:
You can use AnimationDrawable
to have the ImageView
show a sequence of pictures, see also the guide to
to create the animation-list
in res/drawable/colored_androids.xml:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
<item android:drawable="@drawable/ic_android_blue_24dp" android:duration="250"/>
<item android:drawable="@drawable/ic_android_mint_24dp" android:duration="250"/>
<item android:drawable="@drawable/ic_android_green_24dp" android:duration="250"/>
<item android:drawable="@drawable/ic_android_mint_24dp" android:duration="250"/>
</animation-list>
My Activity
has a field for the AnimationDrawable
private lateinit var coloredAndroidsAnimation: AnimationDrawable
and in onCreate()
the following lines are required for the setup:
findViewById<ImageView>(R.id.iv_animated).apply {
setBackgroundResource(R.drawable.colored_androids)
coloredAndroidsAnimation = background as AnimationDrawable
setOnClickListener{
coloredAndroidsAnimation.start()
}
}
CodePudding user response:
While I don't think you can change a view that is attached to the UI from a background thread, you can create/edit views on a background thread (I do this lots)
So a possible solution might be to programmatically create a series of ImageViews in the background. It might then be possible to measure them with the same parameters as the UI in the background thread as measurement can be costly (not sure if they would be re-measured when added to the UI)
Then in the UI thread your loop would add
and remove
Views from the parent view.
CodePudding user response:
I finally solved this problem. The Handler and the Callback seemed to cause this issue. I changed it into a while and now everything is working just fine.