Android: Updating UI with a Button? - java

So I have some simple code but it seems to not be working.. any suggestions?
I just want an image to show after a button is pressed then become invisible after 2 seconds.
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
firstImage.setVisibility(ImageView.VISIBLE);
// delay of some sort
firstImage.setVisibility(ImageView.INVISIBLE);
}
}
The image never shows, it always stays invisible, should I be implementing this in another way? I've tried handlers.. but it didn't work, unless I did it wrong.

Never make your UI thread sleep!
Do this:
final Handler handler = new Handler();
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
firstImage.setVisibility(ImageView.VISIBLE);
handler.postDelayed(new Runnable(){
public void run(){
firstImage.setVisibility(ImageView.INVISIBLE);
}
}, DELAY);
}
}
Where you would set DELAY as 2000 (ms).

Well, you will need to add a delay between the two lines. Use a thread or a timer to do this.
Start a thread on click of a button. In the run method, change the ImageView's visibility to VISIBLE, then put the thread to sleep for n secs, and then change then make it invisible.
To call the imageView's setvisibility method, you will need a hanlder here.
Handler handler = new Handler();
handler.post(new Runnable() {
public void run() {
image.setVisibiliy(VISIBLE);
Thread.sleep(200);
image.setVisibility(INVISIBLE);
}
});

I know this question has already been answered, but I thought I would add an answer for people who like me, stumbled across this looking for a similar result where the delay was caused by a process rather than a "sleep"
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
firstImage.setVisibility(ImageView.VISIBLE);
// Run the operation on a new thread
new Thread(new Runnable(){
public void run(){
myMethod();
returnVisibility();
}
}).start();
}
}
private void myMethod() {
// Perform the operation you wish to do before restoring visibility
}
private void returnVisibility() {
// Restore visibility to the object being run on the main UI thread.
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
firstImage.setVisibility(ImageView.INVISIBLE);
}
});
}

Related

How to simulate a delay?

I want my Android app to do an auto demo, so after user clicks on a "Auto Demo" button, it will switch to a view and delay a second and click on a button on that view, then 2 seconds later click on another button on that screen .. so on, my java code looks like this :
private class AutoDemoListener implements View.OnClickListener
{
public void onClick(View v)
{
Is_AutoDemo_B=true;
Out("AutoDemoListener");
switchView(demoView, registrationView);
startRegistration();
Thread t = new Thread(new Runnable()
{
#Override
public void run()
{
runOnUiThread(new Runnable()
{
#Override
public void run()
{
try
{
registrationView.symbolButton[2][8].performClick();
Thread.sleep(1000);
registrationView.symbolButton[4][13].performClick();
Thread.sleep(2000);
registrationView.symbolButton[0][1].performClick();
Thread.sleep(1000);
registrationView.symbolButton[6][18].performClick();
}
catch (InterruptedException e) { e.printStackTrace(); }
}
});
}
});
t.start();
Is_AutoDemo_B=false;
}
}
But what it does now is : wait 4 seconds and simulate all 4 clicks at once, so there is no delay between each click, what's the right way to do it ?
You have to perform the delay in the background and post the results back to the UI each time.
You can do this using a Handler. The UI thread already comes with a prepared Looper that will allow you to easily use the Handler (other threads do not and require more setup).
The nesting of runnables would look nasty, so here it is with just adding increasing delays:
private class AutoDemoListener implements View.OnClickListener
{
public void onClick(View v)
{
Is_AutoDemo_B=true;
Out("AutoDemoListener");
switchView(demoView, registrationView);
startRegistration();
final Handler handler = new Handler();
registrationView.symbolButton[2][8].performClick();
handler.postDelayed(new Runnable() {
public void run() {
registrationView.symbolButton[4][13].performClick();
}
}, 1000);
handler.postDelayed(new Runnable() {
public void run() {
registrationView.symbolButton[0][1].performClick();
}
}, 3000);
handler.postDelayed(new Runnable() {
public void run() {
registrationView.symbolButton[6][18].performClick();
}
}, 5000);
handler.postDelayed(new Runnable() {
public void run() {
Is_AutoDemo_B=false;
}
}, 5100);
}
}
In Kotlin this could be much cleaner using a coroutine:
val autoDemoListener = View.OnClickListener {
Is_AutoDemo_B = true
Out("AutoDemoListener")
switchView(demoView, registrationView)
startRegistration()
CoroutineScope(Job() + Dispatchers.Main).launch {
registrationView.symbolButton[2][8].performClick()
delay(1000)
registrationView.symbolButton[4][13].performClick()
delay(2000)
registrationView.symbolButton[0][1].performClick()
delay(1000)
registrationView.symbolButton[6][18].performClick()
Is_AutoDemo_B=false
}
}
TimeUnit.SECONDS.sleep(1); see How do I make a delay in Java? is also in Android https://developer.android.com/reference/java/util/concurrent/TimeUnit
Maybe spawn new threads, sleep in these child threads and block the main threads until the child thread returns. #Tenfour04's answer is a similar concept to spawning threads i think ...

How to start a thread if a button is idle?

I need a thread to start after 3 seconds of a button being idle, is there a simple way of doing it?
I'm building a counter app, the button triggers two counters, the total counter and the "tapping counter", the tapping counter helps keep track of the actual change of values, showing how many taps the user did, I need it to vanish after some seconds so the user can tap again.
for stuffs like that I usually use a Handler with a Runnable in order to do stuff after X milliseconds the user isn't doing a specific action.
First, create a runnable and a handler
final android.os.Handler handler = new android.os.Handler();
private Runnable runnable;
private final long DELAY = 3000; // how many milliseconds you want to wait
Then add the onClickListener:
myButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
Then, inside onClick event, remove callbacks and istantiate the handler again as follows:
if(runnable != null) {
// in this case the user already clicked once at least
handler.removeCallbacks(runnable);
}
runnable = new Runnable() {
#Override
public void run() {
//this code will run when user isn't clicking for the time you set before.
}
};
handler.postDelayed(runnable, DELAY);
Final result:
final android.os.Handler handler = new android.os.Handler();
private Runnable runnable;
private final long DELAY = 3000; // how many milliseconds you want to wait
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// all your previous stuffs
myButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(runnable != null) {
// in this case the user already clicked once at least
handler.removeCallbacks(runnable);
}
runnable = new Runnable() {
#Override
public void run() {
//this code will run when user isn't clicking for the time you set before.
}
};
handler.postDelayed(runnable, DELAY);
}
});
}
I hope this helps, for any question feel free to ask
Handler may work in this scenario, with a 3000 milisecond delay.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// do action
}
}, 3000);
At first, you create a Timer with a TimerTask(with your Thread) and schedule it to run after 3 seconds.
Every time the button is pressed, you reset the timer.
public class MyClass{
private Timer timer=new Timer()
private TimerTask task=new TimerTask(){
public void run(){
//your action
}
};
public void init(){
timer.schedule(task,3000);
}
public void onButtonClick(){
task.cancel();
timer.schedule(task,3000);
}
}

How to detect taps on a button whilst a delay caused by postDelayed Handler

I want to solve a problem that I have been trying to do so the last couple of days but I dont have that much experience and I couldnt find the solution enywhere else.
Anyway,
In my app I have a button in wich I have implemented the onClickClistener in order to respond to touch and inside that I have added a Handler which adds a delay and after that some code is being executed. My problem is that i want to detect any tap of the button whilst the delay is happening and the postDelyed function doesn't allow me to do so. How can I actually do that?
I've posted my code that is related on that.
Thanks in advance!
P.S(I dont mind not using this postDelayed thing.)
Button button = findViewById(R.id.myButtonId);
button.setOnClickListener(new View.OnClickListener){
#Override
public void onClick(View v) {
.......
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do some thing after the delay
}
}, randomDelay);
//Do other things
}
});
boolean previousTapDetected;
...
button.setOnClickListener(new View.OnClickListener){
#Override
public void onClick(View v) {
.......
if(previousTapDetected) {
//We got a tap during the delay
}
Handler handler = new Handler();
previousTapDetected = true;
handler.postDelayed(new Runnable() {
#Override
public void run() {
previousTapDetected = false;
//Do some thing after the delay
}
}, randomDelay);
//Do other things
}
});

Google Glass Immersion - OnClick not working inside a separate thread

My problem is pretty simple. I am creating a card based on the result of a HTTP query performed inside a separate thread. The card also has an onclick method and is defined inside a runOnUiThread() located inside the separate thread. However, when the device is tapped, the onclick event isn't fired.
Here is my code:
private void login() {
Runnable r = new Runnable() {
#Override
public void run() {
// irrelevant code
runOnUiThread(new Runnable() {
#Override
public void run() {
setContentView(buildError(code));
}
}
}
Thread t = new Thread(r);
t.start();
}
private View buildError(String code) {
CardBuilder card = new CardBuilder(this, CardBuilder.Layout.ALERT);
card.setIcon(R.drawable.ic_warning_150);
if (code.equals("1"))
card.setText("Incorrect credientals");
else
card.setText("Unexpected error");
card.setFootnote("Tap to try again");
View cView = card.getView();
cView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("Event", "Clicked"); // This is what isn't triggering
}
});
cView.setFocusable(true);
cView.setFocusableInTouchMode(true);
return cView;
}
Even though the snippet of code contains an error (can't be compiled, missing ; at the Runnable statement), you were on the right track.
The View simply needs to request the focus in order to be clickable right away. Otherwise you'll have to move the focus manually.
cView.setFocusable(true);
cView.setFocusableInTouchMode(true);
cView.requestFocus();
Reference

Editing a Button's colour in a nonUI thread (Android)

I've seen some similar questions and got some information but they stop shy of telling me enough to get it working.
What I'm trying to do is make a simple rhythm game where the player taps a button at regular intervals (ie. beats). I wanted to set up a way of signalling when to tap by having the button change colour, and since this would be a repeated task at regular intervals I want to use a timer object with a schedule method.
But when I try calling on this method it tells me that I can't change the UI in a non UI thread. I've tried a few ways to write a method in the main thread that I can call from the timer object but I get the same error every time. I'm assuming that I just have the wrong idea about what counts as being from the UI thread, so I was hoping someone could clear it up.
Here's a snippet of one way I tried it, just to show what my code looks like:
OnClickListener clickButton = new View.OnClickListener() {
public void onClick(View v) {
if (startBeat == 0){
startBeat = System.nanoTime();
timerStart.scheduleAtFixedRate((new TimerTask()
{
public void run()
{
flashButton();
}
}), 0, beatTime);
timerEnd.schedule(new TimerTask()
{
public void run()
{
unflashButton();
}
}, beatTolerance*2, beatTime);
return;
}
};
public void flashButton(){
beatPrompt.setBackgroundColor(getResources().getColor(R.color.primary1transparent_very));
}
public void unflashButton(){
beatPrompt.setBackgroundColor(getResources().getColor(R.color.primary1));
}
To be clear, this is all contained within my MainActivity class along with the OnCreate class.
if you are in an activity all you need to do is use runOnUiThread() and then place the code to change the ui element in there
public void flashButton(){
runOnUiThread(new Runnable() {
#Override
public void run() {
beatPrompt.setBackgroundColor(getResources().getColor(R.color.primary1transparent_very));
}
});
}
You cannot, under any circumstances, touch a UI object from a non UI thread.
You can accomplish your intent using Handler.sendMessageDelayed
UI can only be touched by the main thread. You should post the actions you are performing on the ui thread via handler or via runOnUiThread
Try something similar to this
timerStart.scheduleAtFixedRate((new TimerTask()
{
public void run()
{
//replace MainActivity with your activity
//if inside a fragment use getActivity()
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
flashButton();
}
});
}
}), 0, beatTime);
If you are in an Activity you could surround flashButton() with an runOnUiThread.
...
runOnUiThread(new Runnable(){
public void run(){
flashButton();
}
});
...
use android.os.Handler Class. Change your code as follows:
private Handler handler=new Handler();
public void flashButton(){
handler.post(new Runnable(){
public void run(){
beatPrompt.setBackgroundColor(getResources().getColor(R.color.primary1transparent_very));
}
});
}
public void unflashButton(){
handler.post(new Runnable(){
public void run(){
beatPrompt.setBackgroundColor(getResources().getColor(R.color.primary1));
}
});
}

Categories