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.
Related
I have implemented one counter and onFinish() of first counter,I started second counter but the first counter not able to finish.Text "Bye Guyz" remain for some time so how to finish the text.
Please help me.
Thanks in advance.!!!
Code :-
counter= new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
if (count == 0) {
tv.setText("First counter");
tv2.setVisibility(View.VISIBLE);
tv2.setText("Hello Guyz");
}
}
public void onFinish() {
if(!flag) {
tv2.setText("Bye Guyz");
count = 0;
try {
counter.cancel();
}catch (Exception e){}
}
else if(flag) {
counter1 = new CountDownTimer(9000, 1000) {
public void onTick(long millisUntilFinished) {
flag = false;
tv.setText("Second counter");
tv2.setVisibility(View.VISIBLE);
tv2.setText("Hello Girls");
count = 0;
}
public void onFinish() {
tv2.setVisibility(View.VISIBLE);
tv2.setText("Bye Girls");
count = 0;
}
}.start();
Did you "debug" the code to be sure the code is arriving to counter1 = new CountDownTimer(9000, 1000)?
Are you sure when the first counter arrives to onFinish() the flag variable is true?
Why do you call counter.cancel() in onFinish() when obviously the counter is already over?
public void onFinish() {
if(!flag) {
tv2.setText("Bye Guyz");
count = 0;
try {
counter.cancel();
}catch (Exception e){}
}
If you say your tv2 displays "Bye Guyz" it means that your flag is set to false, so the "else if" part is not being executed. onFinish() is only executed once, so you need to make sure the flag is set for true to start the second counter.
Also you shouldn't cancel your counter in onFinish() because it's already finished.
Here is my alternative is as follows
Create the custom Counterextending Thread
class Counter extends Thread {
private long timeOne, timeTwo;
private OnCounterFinishedListener mCounterFinishedListener;
private Thread t;
Activity activity = null;
Counter(Context context){
t = new Thread(this);
activity = (Activity)context;
}
#Override
public void run() {
try {
sleep(timeOne);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
mCounterFinishedListener.firstCounterFinished();
}
});
sleep(timeTwo);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
mCounterFinishedListener.secondCounterFinished();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
void setTimes(long timeOne, long timeTwo){
this.timeOne = timeOne;
this.timeTwo = timeTwo;
}
public void start(OnCounterFinishedListener listener){
mCounterFinishedListener = listener;
t.start();
}
interface OnCounterFinishedListener{
void firstCounterFinished();
void secondCounterFinished();
}
}
Then inside your main thread you can start this counter as
final Counter counter = new Counter(this);
counter.setTimes(5000, 5000);
counter.start(new Counter.OnCounterFinishedListener() {
#Override
public void firstCounterFinished() {
// Update your first TextView
}
#Override
public void secondCounterFinished() {
// Update your second TextView
}
});
I have been spending couple hours to try to update the textview inside the dialog, but failed.
When the option is clicked, there are new dialog is shown, and inside the dialog, there are textviews and button, when I click the button, the textview will be update.
Here is the code related to the button onClick listener:
start.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
for (int i = 0; i < 50 ; i ++){
final String currentNum = String.valueOf(i + 1);
Thread t = new Thread() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(currentNum); //it is fine
currentNum.setText(currentNum); //it is the problem, the setText only work when the for loop is finished.
}
});
}
};
t.start();
}
}
});
Please let me know if you need more information. Thanks a lot in advance!
//it is a optionmenu
case R.id.action_refresh:
final TextView currentNum;
final ImageButton start;
String currentNum = Integer.toString(songList.size());
final Dialog lyricsAnalysis = new Dialog(this,R.style.cust_dialog);
lyricsAnalysis.requestWindowFeature(Window.FEATURE_NO_TITLE);
lyricsAnalysis.setContentView(R.layout.analysis);
lyricsAnalysis.setCancelable(true); //back button to cancel
lyricsAnalysis.setCanceledOnTouchOutside(true);
start = (ImageButton) lyricsAnalysis.findViewById(R.id.start);
//first value
currentNum.setText(String.valueOf(currentNum));
start.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
for (int i = 0; i < 50 ; i ++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
updateTextView(lyricsAnalysis,i);
}
}
});
lyricsAnalysis.show();
lyricsAnalysis.getWindow().setLayout(600, 1000);
break;
}
return super.onOptionsItemSelected(item); }
public void updateTextView(Dialog dialog, int i) {
final TextView currentNum = (TextView) dialog.findViewById(R.id.currentNum);
currentNum.setText(Stri`enter code here`ng.valueOf(i));
//return;
}
Try this method. This may helps you. It's work for me.(But I am not use this in dialog)
public void updateTextView(String toThis) {
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(toThis);
//return;
}
try like this
int elapsedtime=0;
boolean isTimerRunning=false;
Timer timerr;
inside onCreate
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//declare your textview here;
timerr=new Timer();
startTimer();
}
/*
* timer for displaying message bubble
*/
protected static void startTimer() {
isTimerRunning = true;
elapsedtime = 0;
// recordingseek.setProgress(0);
timerr.scheduleAtFixedRate(new TimerTask() {
public void run() {
// increase every sec
elapsedtime++;
mmHandler.obtainMessage(1).sendToTarget();
System.out.println("recording time" + elapsedtime);
if(elapsedtime==50)
timerr.cancel();
}
}, 1000, 2000);
};
public static Handler mmHandler = new Handler() {
public void handleMessage(Message msg) {
textview.setText(elapsedtime);
}
};
}
};
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 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
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);