I am trying to perform sort of a stop light function on a button press but instead there are two of every color. The desired functionality would be red, red, yellow, yellow, green, and green. I have tried to set a delay in between each color but it doesn't happen sequentially it just adds up the delays and they all show up at once.
Here is the snippet of the activity that I have tried to do this:
Button previewButton = (Button) findViewById(R.id.preview_visual_button);
final Button redButton1 = (Button) findViewById(R.id.red_button_1);
final Button redButton2 = (Button) findViewById(R.id.red_button_2);
final Button yellowButton1 = (Button) findViewById(R.id.yellow_button_1);
final Button yellowButton2 = (Button) findViewById(R.id.yellow_button_2);
final Button greenButton1 = (Button) findViewById(R.id.green_button_1);
final Button greenButton2 = (Button) findViewById(R.id.green_button_2);
redButton1.setVisibility(View.GONE);
redButton2.setVisibility(View.GONE);
yellowButton1.setVisibility(View.GONE);
yellowButton2.setVisibility(View.GONE);
greenButton1.setVisibility(View.GONE);
greenButton2.setVisibility(View.GONE);
if(previewButton != null) {
previewButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int time = 100;
delay(time);
}
});
}
}
public void delay(final int c){
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(c);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Button redButton1 = (Button) findViewById(R.id.red_button_1);
Button redButton2 = (Button) findViewById(R.id.red_button_2);
Button yellowButton1 = (Button) findViewById(R.id.yellow_button_1);
Button yellowButton2 = (Button) findViewById(R.id.yellow_button_2);
Button greenButton1 = (Button) findViewById(R.id.green_button_1);
Button greenButton2 = (Button) findViewById(R.id.green_button_2);
redButton1.setVisibility(View.VISIBLE);
redButton2.setVisibility(View.VISIBLE);
yellowButton1.setVisibility(View.VISIBLE);
yellowButton2.setVisibility(View.VISIBLE);
greenButton1.setVisibility(View.VISIBLE);
greenButton2.setVisibility(View.VISIBLE);
}
}, c);
}
EDIT:
previewButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int time = 1000;
redButton1.setVisibility(View.VISIBLE);
delay(time);
redButton2.setVisibility(View.VISIBLE);
delay(time);
yellowButton1.setVisibility(View.VISIBLE);
delay(time);
yellowButton2.setVisibility(View.VISIBLE);
delay(time);
greenButton1.setVisibility(View.VISIBLE);
delay(time);
greenButton2.setVisibility(View.VISIBLE);
}
});
}
public void delay(final int time) {
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
Because that's basically what the postDelayed method does. It runs the code in the runnable after the specified time. So it delays for 100ms then runs just turns all the buttons on at once. Also I'm not sure what you are trying to do by calling Thread.sleep() on your UI thread. I would suggest writing a new method that just runs a Thread.sleep() inside a separate thread and call it between each pair of button toggle commands. Kind of like this
public void pause(int time) {
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
Then basically call this in between each pair of button toggle statements. This should do the trick.
Update UI with Thread sleep
This will help answer the question if anyone visits in the future.
Related
Goal:
When you start the android app, the button should not be displayed after 5 seconds.
Problem:
The code doesn't work and what part am I missing?
Info:
*Im new in android
*The code is inspired from this page Android - Hide button during an onClick action
Thank you!
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button button2 = (Button) findViewById(R.id.btn_test);
button2.setVisibility(GONE);
new Thread(new Runnable() {
#Override
public void run() {
try
{
//dummy delay for 5 second
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
runOnUiThread(new Runnable() { //resetting the visibility of the button
#Override
public void run() {
//manipulating UI components from outside of the UI Thread require a call to runOnUiThread
button2.setVisibility(VISIBLE);
}
});
}
}).start();
}
}
This can be achieved in a simpler way. If your needed sequence is:
Start the app -> Display a button -> Wait 5 seconds -> Hide the button
final Button button2 = (Button) findViewById(R.id.btn_test);
button2.postDelayed(new Runnable() {
#Override
public void run() {
if (!isDestroyed() && !isFinishing()) {
button2.setVisibility(View.GONE);
}
}
},5000);
Otherwise, if you should display the button after 5 seconds after app launch, then just set button's visibility to GONE in your layout and change button2.setVisibility(View.GONE) to button2.setVisibility(View.VISIBLE) inside post delayed action
You need to set a listener to start your command, onCreate is the creation.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Button button2 = (Button) findViewById(R.id.btn_test);
button2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
button2.setVisibility(GONE);
new Thread(new Runnable() {
#Override
public void run() {
try
{
//dummy delay for 5 second
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
runOnUiThread(new Runnable() { //resetting the visibility of the button
#Override
public void run() {
//manipulating UI components from outside of the UI Thread require a call to runOnUiThread
button2.setVisibility(VISIBLE);
}
});
}
}).start();
}
this code will hide the button AFTER onClick, start the thread, and after 5 seconds it will appear again.
My goal is when the user tap start button, letters "o" "n" "o" "m" and so forth will appear at the center of the screen. "o" will appear first then after a few seconds will be replaced by "n" then "o" and so forth.
note: for brevity, i just make the guessword = onomatopoeia, first. In reality, guessword will changes every time i tap the start bottom.
this is the code:
private String guessword = "onomatopoeia";
private TextView showchar;
private int n = guessword.length();
private char letArray[]= guessword.toCharArray();;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play);
addStartListener();
}
public void addStartListener(){
Button start = (Button) findViewById(R.id.start);
showchar = (TextView) findViewById (R.id.charView);
start.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Thread thread = new Thread()
{
#Override
public void run() {
try {
for(int i = 0 ; i < n ; i++) {
sleep(1000);
showchar.setText(letArray[i]);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
}
});
}
thanks for the help
I decided to implement runonuithread but still it crashes:
this is the updated version:
private String guessword = "onomatopoeia";
private TextView showchar;
private int n = guessword.length();
private char letArray[]= guessword.toCharArray();
private Handler handler;
private int i = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_play);
handler = new Handler();
showchar = (TextView) findViewById (R.id.charView);
}
public void startGame(View view){
new Thread() {
public void run() {
while(i++ < n) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
showchar.setText(letArray[i]);
}
});
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
use this code for setting the text in your textview
runOnUiThread(new Runnable() {
#Override
public void run() {
showchar.setText(letArray[i]);
}
});
You are updating ui from a thread which is not possible.
showchar.setText(letArray[i]);
UI must be updated ui thread.
All you are doing is repeatedly setting value to TextView you can use Handler with a delay for this purpose.
You could use runOnUiThread also but i don't see the need for a thread for what you are doing.
Use a Handler. You can find an example #
Android Thread for a timer
in my new Android app I need to push a button to make visibile a progress bar but I need to make it invisible after 3 seconds.
I found this on the web but It does not work:
public void search(View view) throws InterruptedException {
ProgressBar progressbarSearch = (ProgressBar) findViewById(R.id.progressBar);
Button searchbutton = (Button) findViewById(R.id.button);
progressbarSearch.setVisibility(1);
searchbutton.setText("Searching devices...");
Handler myHandler = new Handler();
//this waits 3 seconds, then will call the run() method below.
myHandler.postDelayed(stopSearching, 3000);
}
private Runnable stopSearching = new Runnable()
{
#Override
public void run()
{
ProgressBar progressbarSearch = (ProgressBar) findViewById(R.id.progressBar);
progressbarSearch.setVisibility(0);
}
};
Where is the error? The progress bar starts after the button is pressed but it does not become invisible after 3 seconds.
progressbarSearch.setVisibility( View.INVISBLE );
You should use a constant here, it's really error prone and not maintainable to use a value. (Proof by example :))
Button searchbutton = (Button) findViewById(R.id.button);
searchbutton.setText("Searching devices...");
searchbutton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
ProgressBar progressbarSearch = (ProgressBar) findViewById(R.id.progressBar1);
progressbarSearch.setVisibility(View.VISIBLE);
try {
search(v);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
public void search(View view) throws InterruptedException {
Handler myHandler = new Handler();
// this waits 3 seconds, then will call the run() method below.
myHandler.postDelayed(stopSearching, 3000);
}
private Runnable stopSearching = new Runnable() {
#Override
public void run() {
ProgressBar progressbarSearch = (ProgressBar) findViewById(R.id.progressBar1);
progressbarSearch.setVisibility(View.INVISIBLE);
}
};
change your code like this
i doing simple stop watch with [start/pause] and [reset] button. problem occur when i pressed start button after pause. the run method is not calling. please help me.
my code is
public class StopWatch3 extends Activity implements Runnable{
// text view influenced by the Thread
private TextView threadModifiedText;
int time=0;
Button b1,b2,b3;
boolean shouldRun = false;
/** Called when the activity is first created. */
Thread currentThread = new Thread(this);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stopwatch);
b1=(Button)findViewById(R.id.button1);
b2=(Button)findViewById(R.id.button2);
b3=(Button)findViewById(R.id.button3);
threadModifiedText = (TextView) findViewById(R.id.textView1);
Log.e("before",""+currentThread.getState());
b1.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
Log.e("stopw",(String) b1.getText());
if(b1.getText().toString().equals("start")){
if(currentThread.getState()==Thread.State.NEW){
currentThread.start();
Log.e("after",""+currentThread.getState());
shouldRun = true;
b1.setText("pause");
}
else{
shouldRun = true;
b1.setText("pause");
}
}
else if(b1.getText().toString().equals("pause")){
shouldRun = false;
b1.setText("start");
}
}
});
b2.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
time=0;
}
});
}
#Override
public void run(){
try {
while(shouldRun){
Thread.sleep(1000);
threadHandler.sendEmptyMessage(0);
}
} catch (InterruptedException e) {
}
}
private Handler threadHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
time++;
threadModifiedText.setText(""+time);
}
};
}
You cannot start thread after it finishes it's job, and his state is no longer NEW anyway, you'll have to create a new thread in this case.
When you press "start" the second time, you reach this part:
else{
shouldRun = true;
b1.setText("pause");
}
And nothing in this code will make the thread run again of course...
I think your thread just runs to an end when you set shouldRun to false.
Enclose your while loop into another while loop that is true as long as your program runs.
i have an ImageView in which the picture switches every 5s, i am trying to add a pause and
resume button that can stop and restart the action. i am using a Handler, Runnable, and
postDelay() for image switch, and i put the code on onResume. i am thinking about using
wait and notify for the pause and resume, but that would mean creating an extra thread. so
far for the thread, i have this:
class RecipeDisplayThread extends Thread
{
boolean pleaseWait = false;
// This method is called when the thread runs
public void run() {
while (true) {
// Do work
// Check if should wait
synchronized (this) {
while (pleaseWait) {
try {
wait();
} catch (Exception e) {
}
}
}
// Do work
}
}
}
and in the main activity's onCreate():
Button pauseButton = (Button) findViewById(R.id.pause);
pauseButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
while (true) {
synchronized (thread)
{
thread.pleaseWait = true;
}
}
}
});
Button resumeButton = (Button) findViewById(R.id.resume);
resumeButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
while (true) {
// Resume the thread
synchronized (thread)
{
thread.pleaseWait = false;
thread.notify();
}
}
}
});
the pause button seems to work, but then after that i can't press any other button, such as
the resume button.
thanks.
i am using a Handler, Runnable, and
postDelay() for image switch
Why? Why not use postDelayed() and get rid of the Thread and Handler?
void doTheImageUpdate() {
if (areWeStillRunning) {
myImageView.setImageResource(R.drawable.whatever);
myImageView.postDelayed(updater, 5000);
}
}
Runnable updater=new Runnable() {
public void run() {
doTheImageUpdate();
}
};
When you want to start updating, set areWeStillRunning to true and call doTheImageUpdate(). When you want to stop updating, set areWeStillRunning to false. You'll need to work out the edge case of where the user presses pause and resume within 5 seconds, to prevent doubling things up, but I leave that as an exercise for the reader.
If you really want to use a background thread, you will want to learn more about how to use background threads. For example, while(true) {} without any form of exit will never work. There are some good books on the subject, such as this one.
sorry to answer my own question, but the comment section is too small.
i did this (per CommonsWare):
private Runnable mWaitRunnable = new Runnable() {
public void run()
{
doTheImageUpdate();
}
};
private void doTheImageUpdate()
{
try
{
if(bStillRunning)
{
sText = "Step one: unpack egg";
iDrawable = R.drawable.monster2;
t.setText(sText);
mImage = BitmapFactory.decodeResource(getResources(), iDrawable);
imageView.setImageBitmap(mImage);
tts1 = new TTS(getApplicationContext(), ttsInitListener, true);
mHandler.postDelayed(mWaitRunnable, 5000);
}
}
catch (Exception e)
{
Log.e("mWaitRunnable.run()", e.getMessage());
}
}
Button pauseButton = (Button) findViewById(R.id.pause);
pauseButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
bStillRunning = false;
}
});
Button resumeButton = (Button) findViewById(R.id.resume);
resumeButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
bStillRunning = true;
}
});
again pause works but resume doesn't. and i have already simplified my problem by making the text, the image, and delay time the same for all the steps. i was hoping to make these variable, in additional to the number of steps.