I have a button and imageView and I need to execute some code that changes image properties while button is pressed. But I do not know how to realize it. I tried to use onTouchListener by executing code:
while(event?.action != MotionEvent.ACTION_UP)
But it causes the app to hang.
You want to start your task (whatever it is) when you get an
ACTION_DOWNevent (i.e. the user has pressed yourView) and stop it when you get anACTION_UPevent (the user has lifted their finger or whatever) or anACTION_CANCEL(e.g. the user's dragged their finger outside of theView).That'll give you the while the button is held behaviour. But that task needs to run asynchronously - coroutines, a thread, a delayed
Runnableposted to the main looper (you can do this through aViewby calling one of thepostmethods).You can't just spin in a loop, the system can't do anything else (including displaying UI changes and responding to touches) until your code has finished running. And if you're waiting for an
ACTION_UPwhile blocking the thread, you're not going to get one. (A newMotionEventwould come through a later function call anyway.)Here's a simple example using the looper:
Posting a
Runnableto the mainLooperis basically adding a bit of your code to a task queue - so you're not blocking the thread and preventing anything else from happening, you're saying to the system "hey, do this at this time please" and it'll try its best to hit that time. And because theRunnablere-posts itself at the end, you get that looping behaviour while allowing other code to run, because you're not seizing control of execution. You're just deferring a bit of code to run later, then allowing execution to continue.Coroutines are a neater way to do this I think, but I like to use the
Looperas an example because it's been a part of Android since the old times, and it can be a simple way to get this kind of behaviour when you have main-thread work that needs a delay or to run for a significant amount of time