I have four ImageViews and I want to be flashing them by switch & turns which I've kept in a list (for example: 1st ImageView become visible, wait some time, become invisible, wait some time, 3rd ImageView become invisible, wait some time, become visible etc.). I tried some variants but ImageViews always flashing at the same time and sometimes main thread goes to sleep mode instead of the thread I want to. How to implement it correctly?
One of my attempts:
...
//choose ImageView to flash
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 0: flashing(CircleR); break;
case 1: flashing(CircleY); break;
case 2: flashing(CircleG); break;
case 3: flashing(CircleB); break;
default:
CircleR.setVisibility(View.VISIBLE);
CircleY.setVisibility(View.VISIBLE);
CircleG.setVisibility(View.VISIBLE);
CircleB.setVisibility(View.VISIBLE);
}
};
};
...
Thread showList = new Thread (new Runnable() {
#Override
public void run() {
for(int x: list){
h.sendEmptyMessage(x);
try {
showList.sleep(2*PAUSE_DURATION);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
h.sendEmptyMessage(4);
}
});
...
//Here I start my thread
protected void SPStartTurn(){
CircleR.setVisibility(View.INVISIBLE);
CircleY.setVisibility(View.INVISIBLE);
CircleG.setVisibility(View.INVISIBLE);
CircleB.setVisibility(View.INVISIBLE);
showList.run();
}
...
public void flashing(final View view) {
view.setVisibility(View.VISIBLE);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
view.setVisibility(View.INVISIBLE);
//next = true;
}
}, PAUSE_DURATION);
}
using timer:
static void ddd(Context context){
CountDownTimer time = new CountDownTimer(60000, 1000) {//Now time is 1 minute
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
///////set the visibility
}
}.start ();
}
}
I think it will help
Related
I have a code that plays 5 sounds with 1 second delay between the sounds and I want this part of code to be executed every 5 seconds (so it will run in a row so far as a boolean variable is true, and when it becomes false the tread run stopped - I have a button to both start and stop this executions). Everything works perfectly, but the issue is that I can't get rid of the 5 seconds delay in the first time I click the button, so when I first click, the sounds beggins only after 5 seconds. How can I make it start right away and only after the first time start taking the delays?
Here is the button onClick code:
public void clickHandlerStartTempo(final View view) {
if (!tempoOn) {
Toast toast = Toast.makeText(getApplicationContext(), "Start Tempo!", Toast
.LENGTH_SHORT);
toast.show();
tempoOn = true;
final Handler handler = new Handler();
final int delay = 5000; //milliseconds
handler.postDelayed(new Runnable() {
public void run() {
if (tempoOn) {
runCode(view);
handler.postDelayed(this, delay);
}
}
}, delay);
} else {
Toast toast = Toast.makeText(getApplicationContext(), "Stop Tempo!", Toast
.LENGTH_SHORT);
toast.show();
tempoOn = false;
}
}
And here is the runCode method:
public void runCode(View view) {
Runnable runnable = new Runnable() {
#Override
public void run() {
playSound(0);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 4; i++) {
if (tempoOn) {
playSound(1);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
return;
}
}
}
};
Thread thread = new Thread(runnable);
Log.i(TAG, "runCode: Thread id = " + thread.getId());
thread.start();
}
I'm new to android development and any help would be very much appreciated.
Thanks.
First you need to playsound without thread after that you will execute your reaming 5 second logic stop thread after 4 count.
public void onStartPress(){
playSound();
someMethod();
}
public void someMethod(){
Handler uiHandler = new Handler(Looper.getMainLooper());
uiHandler.postDelayed(new Runnable() {
#Override
public void run() {
playSound();
someMethod();
}
},1000);
}
Don't use actual Threads unless you really want to do something off the Ui thread. Most of the time you do want to keep things on the Ui thread.
For simple repeating tasks, you can easily repurpose the CountDownTimer class. Often with an (almost) infinite run time or Long.MAX_VALUE (292 million years). The fist onTick happens immediately after starting.
private CountDownTimer mTimer;
private void start() {
if (mTimer == null) {
mTimer = new CountDownTimer(Long.MAX_VALUE, 5000) {
#Override
public void onTick(long millisUntilFinished) {
// start a beeping countdown
new CountDownTimer(5000, 1000) {
private int state = 1;
#Override
public void onTick(long millisUntilFinished) {
playSound(state);
state = state + 1 % 2;
}
#Override
public void onFinish() {
playSound(0);
}
}.start();
}
#Override
public void onFinish() { /* ignore, never happens */ }
};
mTimer.start();
}
}
private void stop() {
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
}
I am writing an app, where one of my views need to blink by the use of a timer constantly, but I have trouble with making it blink.
Here's my handler code
#SuppressWarnings("All")
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
try {
circle.setVisibility(View.VISIBLE);
Thread.sleep(100);
circle.setVisibility(View.INVISIBLE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
So i am sending an empty message to the handler with some INTERVAL constantly, and I want the image to get visible for 100 milliseconds and then hide again. But the problem is, until the method is finished, my UI elements won't get refreshed. How I do this?
Thanks in advance.
Thread t = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
if(circle.isVisible()){circle.setVisibility(View.VISIBLE);}
else{
circle.setVisibility(View.INVISIBLE);
}
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
if(msg.what == 1) circle.setVisibility(View.VISIBLE);
if(msg.what == 2) circle.setVisibility(View.INVISIBLE);
}
};
then send message 1 & 2 somewhere.
Here's an example of runnable that toggles visibility and infinitely reposts itself, delayed every 100 miliseconds. The problem that you are having is you are stopping the main UI thread, so nothing else is going to happen and your program is probably freezing right? Anyways, this is one style of solution. Another might be to do the posting in another thread.
final Handler mHandler = new Handler();
final View circle = ....;
Runnable blink = new Runnable() {
#Override
public void run() {
int vis = circle.getVisibility();
if(vis == View.VISIBLE){
circle.setVisibility(View.INVISIBLE);
}else{
circle.setVisibility(View.VISIBLE);
}
mHandler.postDelayed(this, 100);
}
};
mHandler.post(blink);
An alternative to the above solutions (Handler, Thread ...) is to create an Animator and rely on Androids flexible animation capabilities.
In this code-snippet you animate directly on the visibility-property of your View, whereas you need to define a custom TimeInterpolator (which only return two distinct values 0.0 and 1.0) as shown:
final ObjectAnimator anim = ObjectAnimator.ofInt(circle, "visibility",
View.VISIBLE, View.INVISIBLE);
anim.setRepeatMode(Animation.REVERSE);
anim.setRepeatCount(Animation.INFINITE);
anim.setDuration(1000);
anim.setInterpolator(new TimeInterpolator() {
#Override
public float getInterpolation(float input) {
return Math.round(input);
}
});
anim.start();
I'm trying to show some imageviews after the user has clicked on a button then wait for some time for the user to see which was the correct button to click then hide it again. Something like this:
User clicks on button giving his answer
-> Score is updated and correct answer is shown to user by setting the visibility of the imageview to visible
-> wait a moment for the user to be able to see which was the correct answer
-> hide the imageview again and load a new question.
So far I have this:
private void gameLoop(){
new Thread(new Runnable() {
#Override
public void run() {
while (isRunning) {
if (time > 0) {
sleepmillis(1000);
time--;
runOnUiThread(new Runnable() {
#Override
public void run() {
textViewTime.setText(time + " sec.");
}
});
} else
finishGame();
}
}
}).start();
}
private void sleepmillis(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void onClick(View view) {
int givenAnswer = -1;
switch (view.getId()) {
case R.id.buttonFirst:
case R.id.imageViewFirst:
givenAnswer = 0;
break;
case R.id.buttonSecond:
case R.id.imageViewSecond:
givenAnswer = 1;
break;
case R.id.buttonThird:
case R.id.imageViewThird:
givenAnswer = 2;
break;
case R.id.buttonFourth:
case R.id.imageViewFourth:
givenAnswer = 3;
break;
}
processAnswer(givenAnswer);
}
private void processAnswer(int givenAnswer){
if (givenAnswer == answers[4]){
score += 5000;
correctAnswersInARow++;
if (correctAnswersInARow == 3)
score += 15000;
if (correctAnswersInARow == 6){
score += 30000;
correctAnswersInARow = 0;
}
}
runOnUiThread(new Runnable() {
#Override
public void run() {
textViewScore.setText("Score: " + score);
}
});
showCorrectAnswer();
answers = gameData.getAnswers();
updateAnswers();
}
private void showCorrectAnswer(){
runOnUiThread(new Runnable() {
#Override
public void run() {
switch (answers[4]){
case 0:
ivCorrectFirst.setVisibility(View.VISIBLE);
break;
case 1:
ivCorrectSecond.setVisibility(View.VISIBLE);
break;
case 2:
ivCorrectThird.setVisibility(View.VISIBLE);
break;
case 3:
ivCorrectFourth.setVisibility(View.VISIBLE);
}
}
});
sleepmillis(400);
hideCorrectAnswers();
}
private void hideCorrectAnswers(){
runOnUiThread(new Runnable() {
#Override
public void run() {
ivCorrectFirst.setVisibility(View.INVISIBLE);
ivCorrectSecond.setVisibility(View.INVISIBLE);
ivCorrectThird.setVisibility(View.INVISIBLE);
ivCorrectFourth.setVisibility(View.INVISIBLE);
}
});
}
So the important part is in the showCorrectAnswer method, where I try to do what I explained here. Although the app waits 400 ms before loading a new question it doesn't show the correct answer.
imageView.setVisibility(View.VISIBLE);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
imageView.setVisibility(View.INVISIBLE);
}
}, ms);
ms is time duration in milliseconds.
What I want: The user keeps the button clicked for 1900ms. If he picks his finger before 1900ms the phone stops vibrating. While if he keeps his finger on the button for more than 1900 sec, calculate() method runs.
I am using: postDelayed as I read it does not interfere with ui thread.
I was trying to check if 1900 sec has passed user has not picked his finger, even than calculate method runs.
Error Happening: If the user picks his finger before 1900 seconds or just he touches and immediately picks, the phone keeps vibrating. Although it should not happen as I am checking it with MotionEvent.ACTION_UP. Please help !!
int flag = 0;
int aborted_flag = 0;
#Override
public boolean onTouch(View v, MotionEvent event) {
Handler mHandler = new Handler();
if(event.getAction()==MotionEvent.ACTION_DOWN){
scanning();
t1 = System.currentTimeMillis();
vibrator.vibrate(1900);
mHandler.postDelayed(new Runnable() {
public void run() {
check();
}
}, 1901);
}
if(event.getAction()==MotionEvent.ACTION_UP){
if(flag == 0){
t2 = System.currentTimeMillis();
vibrator.cancel();
calculate();
aborted_flag = 1;
}
}
return true;
}
private void check() {
t2 = System.currentTimeMillis();
Log.e("Hello","Inside Check");
Log.e("Hello",""+aborted_flag);
vibrator.cancel();
if(aborted_flag==0){
calculate();
flag = 1;
}
}
private void scanning() {
textView.setText("Scanning");
}
private void calculate() {
Log.e("t2-t1 ", t2-t1+"");
if(t2-t1>=1900){
Random r = new Random();
int k = r.nextInt((5 - 0) + 1) + 0;
textView.setText(str[k]);
////////////animation library code/////////////
YoYo.with(Techniques.StandUp)
.duration(700)
.playOn(findViewById(R.id.text_view));
////////////////////////////////////////
changeBackgroundColor(k);
//textView.setTextColor(Color.parseColor("#00ff00"));
flag = 0;
}
else{
textView.setText("Aborted\n Try Again");
relativeLayout.setBackgroundResource(R.color.red);
}
}
public void changeBackgroundColor(final int k) {
runOnUiThread(new Runnable(){
public void run() {
switch(k){
case 0: relativeLayout.setBackgroundResource(R.color.blue);
break;
case 1: relativeLayout.setBackgroundResource(R.color.pink);
break;
case 2:;
case 3: relativeLayout.setBackgroundResource(R.color.green);
break;
default:relativeLayout.setBackgroundResource(R.color.yellow);
}
}
});
}
If you call postDelayed from the UI thread then your code will be executed on the UI thread.
To use a different thread create one:
Thread t = new Thread(new Runnable(){});
t.start();
You can create a HandlerThread and use it's looper to create a handler and then post stuff to it either post or postdelayed
public class myActivity extends Activity
{
private HandlerThread loaderThread;
private Handler loader;
#override
public void onResume()
{
super.onResume();
if (loaderThread == null)
{
loaderThread = new HandlerThread("MyActivitySeparateThread");
loaderThread.start();
loader = new Handler(loaderThread.getLooper());
}
}
#override
public void onDestroy()
{
//Stop and release handler
try {
loader.removeCallbacksAndMessages(null);
loader.dispose();
} finally {
loader = null;
}
//Stop and release Thread
try {
loaderThread.quit();
loaderThread.dispose();
} finally {
loaderThread = null;
}
super.onDestroy();
}
#Override
public boolean onTouch(View v, MotionEvent event)
{
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
scanning();
t1 = System.currentTimeMillis();
vibrator.vibrate(1900);
loader.postDelayed(new Runnable()
{
public void run()
{
check();
}
}, 1901);
break;
}
case MotionEvent.ACTION_UP:
{
if (flag == 0)
{
t2 = System.currentTimeMillis();
vibrator.cancel();
calculate();
aborted_flag = 1;
}
break;
}
}
return true;
}
}
Because in mHandler.postDelayed you call check() which calls calculate() which calls relativeLayout.setBackgroundResource(). UI can be changed only from UIThread.
Make function:
public void changeBackgroundColor(final int color) {
runOnUiThread(new Runnable(){
public void run() {
relativeLayout.setBackgroundResource(color);
}
});
}
And call it from your calculate() function.
I want to put change the image (source) of the imageview in android UI..
could not do it using the code
my code is as follows :
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.view);
iv=(ImageView) findViewById(R.id.imageView11);
Timer Tim=new Timer();
Tim.schedule(new TimerTask()
{ #Override
public void run()
{ runthread(); }
},1000,1000);
}
public void runthread () {
int x=0;
if(x==0)
{ iv.setImageResource(R.drawable.lcd); }
if(x==1)
{ iv.setImageResource(R.drawable.lcd1); }
if(x==2)
{ iv.setImageResource(R.drawable.lcd22); }
if(x==3)
{ iv.setImageResource(R.drawable.lcd3); }
if(x==4)
{ iv.setImageResource(R.drawable.lcd4); }
if(x==5)
{ iv.setImageResource(R.drawable.lcd5); }
if(x==6)
{ iv.setImageResource(R.drawable.lcd6); }
if(x==7)
{ iv.setImageResource(R.drawable.lcd7); }
if(x==8)
{ iv.setImageResource(R.drawable.lcd8); }
if(x==9)
{ iv.setImageResource(R.drawable.lcd9); }
x=x+1;
if(x==10){x=1;}
}
i want to keep counting from 0 to 10 in my UI but this code is not working properly can anyone tel me the problem so that i can modify it so that i can proceed.
thanks in advance
your are missing thing in your code and that is following
myImgView.setImageDrawable(getResources().getDrawable(R.drawable.Image));
so
public void runthread () {
int x=0;
if(x==0)
{ iv.setImageDrawable(getResources().getDrawable(R.drawable.Image)); }
if(x==1)
{ iv.setImageDrawable(getResources().getDrawable(R.drawable.Image)); }
if(x==2)
{ iv.setImageDrawable(getResources().getDrawable(R.drawable.Image)); }
if(x==3)
{ iv.setImageDrawable(getResources().getDrawable(R.drawable.Image)); }
if(x==4)
{ iv.setImageDrawable(getResources().getDrawable(R.drawable.Image)); }
if(x==5)
{ iv.setImageDrawable(getResources().getDrawable(R.drawable.Image)); }
if(x==6)
{ iv.setImageDrawable(getResources().getDrawable(R.drawable.Image)); }
if(x==7)
{ iv.setImageDrawable(getResources().getDrawable(R.drawable.Image)); }
if(x==8)
{ iv.setImageDrawable(getResources().getDrawable(R.drawable.Image)); }
if(x==9)
{ iv.setImageDrawable(getResources().getDrawable(R.drawable.Image)); }
x=x+1;
if(x==10){x=1;}
change image name and run the code it will work fine
initialize your x variable to global meaning initialize it outside your method
,don't keep on initializing it inside your runthread() method , you will always get x=0 for that.
and in your last condition,change it to this
if(x==10){x=0;}
and also
place your timer in onWindowsFocusChanged() override that method
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Timer Tim=new Timer();
Tim.schedule(new TimerTask()
{ #Override
public void run()
{ runthread(); }
},1000,1000);
}
because onWindowsFocusChanged() signifies that your layout has been loaded properly, that's the time you can manipulate your Imageview.
Based on code provided by Corbella this is for people that dislikes convenience methods as runOnUiThread (Runnable action). Details at bottom.
public class MainActivity extends Activity {
private int mX;
private Handler mHandler;
private ImageView mImageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler();
mImageView = (ImageView) findViewById(R.id.image_view);
updateImageContinuouslyWithTimer();
}
private void updateImageContinuouslyWithTimer() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
mHandler.post(new Runnable() {
#Override
public void run() {
runthread();
}
});
}
}, 1000, 1000);
}
public void runthread() {
switch (mX) {
case 0:
mImageView.setImageResource(R.drawable.lcd);
break;
case 1:
mImageView.setImageResource(R.drawable.lcd1);
break;
case 2:
mImageView.setImageResource(R.drawable.lcd2);
break;
case 3:
mImageView.setImageResource(R.drawable.lcd3);
break;
case 4:
mImageView.setImageResource(R.drawable.lcd4);
break;
case 5:
mImageView.setImageResource(R.drawable.lcd5);
break;
case 6:
mImageView.setImageResource(R.drawable.lcd6);
break;
case 7:
mImageView.setImageResource(R.drawable.lcd7);
break;
case 8:
mImageView.setImageResource(R.drawable.lcd8);
break;
case 9:
mImageView.setImageResource(R.drawable.lcd9);
break;
}
mX = (mX + 1) % 10;
}
}
It is proper named with lower case and underscores for the XML names and full length names for code. When you code you should aim for readability because not following convention will not only confuse you in the future but also other developers. Also prefix your member variables with m. This is how I suggest you do in the future.
1) Don't use so many "if statment", its dirty code
2) your x variable must be global
3) Use this
private int mX=0;
public void runthread () {
switch(mX){
case 0: iv.setImageResource(R.drawable.lcd); break;
case 1: iv.setImageResource(R.drawable.lcd1); break;
case 2: iv.setImageResource(R.drawable.lcd2); break;
case 3: iv.setImageResource(R.drawable.lcd3); break;
case 4: iv.setImageResource(R.drawable.lcd4); break;
case 5: iv.setImageResource(R.drawable.lcd5); break;
case 6: iv.setImageResource(R.drawable.lcd6); break;
case 7: iv.setImageResource(R.drawable.lcd7); break;
case 8: iv.setImageResource(R.drawable.lcd8); break;
case 9: iv.setImageResource(R.drawable.lcd9); break;
}
mX = (mX+1) %10;
}
UPDATED:
4) Also don't change UI on another thread (as noticed Simon). Can use this:
Tim.schedule(new TimerTask(){
public void run(){
runOnUiThread(new Runnable() { public void run() { runthread(); } });
}
},1000,1000);