In my testing code app I have a problem with setting if statement with getVisibility in it.
Basicaly, app should reveal (from GONE to VISIBLE) 1 TextView tv1, and then reveal 1 LinearLayout LL1 with 2 Buttons inside it btn1 & btn2. When either is pressed, LL1 should disappear (from VISIBLE back to GONE) and in its place, new tv2 or tv3 should appear (from GONE to VISIBLE) depending on which button is pressed. tv4 should wait until LL1 is GONE, and then appear. A 1s interval is set between appearances.
Everything runs ok, until IF part which doesnt work. I have also tried
if (btn1.isPressed() || btn2.isPressed())
and
if (tv2.getVisibility()==View.VISIBLE || tv3.getVisibility()==View.VISIBLE)
but it didnt work. I guess the problem is the way I acces getVisibility.
I even tryed defining global boolean x=false;, and then in OnClickListener setting x=true; but then if (x) {... returns false!?
HOW TO MAKE IF STATEMENT WORK!?
Everything (tv1..tv4, btn1, btn2, LL1) in layout file is predefined and inittialy set to GONE.
This is my activity>
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_layout);
Thread mainThread = new Thread(
new Runnable() {
#Override
public void run() {
startApp();
}
}
);
mainThread.start();
}
public void startApp() {
Button btn1 = (Button) findViewById(R.id.btn1);
Button btn2 = (Button) findViewById(R.id.btn2);
TextView tv1 = (TextView) findViewById(R.id.line1);
TextView tv2 = (TextView) findViewById(R.id.line2);
TextView tv3 = (TextView) findViewById(R.id.line3);
TextView tv4 = (TextView) findViewById(R.id.line4);
LinearLayout LL1 = (LinearLayout) findViewById(R.id.LL1);
show_line(tv1, 1000);
btnLL(LL1, btn1, btn2, tv2, tv3);
//THIS IS THE PROBLEM IT ALWAYS RETURNS TRUE
if (LL1.getVisibility()==View.GONE) show_line(tv4, 1000);
}
public void show_line (final TextView tv, int duration) {
try {
Thread.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
tv.getHandler().post(new Runnable() {
public void run() {
tv.setVisibility(View.VISIBLE);
}
});
/*tv.setVisibility(View.VISIBLE); CANT USE THIS BECAUSE IM NOT IN UI THREAD*/
}
public void btnLL (final LinearLayout LL, Button btnLeft, Button btnRight, final TextView tvLeft, final TextView tvRight) {
//LL.setVisibility(View.VISIBLE); AGAIN NOT IN UI THREAD
LL.getHandler().post(new Runnable() {
public void run() {
LL.setVisibility(View.VISIBLE);
}
});
btnLeft.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LL.getHandler().post(new Runnable() {
public void run() {
LL.setVisibility(View.GONE);
}
});
tvLeft.getHandler().post(new Runnable() {
public void run() {
tvLeft.setVisibility(View.VISIBLE);
}
});
}
});
btnRight.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LL.getHandler().post(new Runnable() {
public void run() {
LL.setVisibility(View.GONE);
}
});
tvRight.getHandler().post(new Runnable() {
public void run() {
tvRight.setVisibility(View.VISIBLE);
}
});
}
});
}
//THIS IS THE PROBLEM IT ALWAYS RETURNS TRUE
if (LL1.getVisibility()==View.GONE) show_line(tv4, 1000);
most likely because it has not been rendered yet, thus not visible yet.
You will need to place that check in something like this:
LL1.getHandler().post(new Runnable() {
public void run() {
if (LL1.getVisibility()==View.GONE) show_line(tv4, 1000);
}
});
Which will wait for LL1 to be rendered/visible, before checking for getVisibility().
note: like GVillani82 said, you are unnecessarily using threads and posts. You don't really need Thread mainThread = new Thread() (and along with those view.getHandler().post()), only some view.post().
OK, just as I wrote a comment with my "primitive" solution, I realized the problem, tested it and confirmed :) Why that IF didn't work...
execution steps:
1) show_line() gets from GONE to VISIBLE
2) btnLL() gets from GONE to VISIBLE and sets up 2 buttons with their onClick()
3) this is the important part
this is where the user should interact with app and make a choice so onClick could execute and then 4) IF statement should execute.
What actually happened is that IF statement executed before user interaction so, the LL1 was still VISIBLE, therefore if (LL1.getVisible()==View.GONE) returned false, and by the time user presses the button and LL1 switches to GONE, IF is already executed and doesn't check any more.
Related
I have a countdown timer starting at 60000 milliseconds and want to change the text color from Color.BLUE to Color.RED once the time is at and below 10000 milliseconds. I've tried the following without any success; attempted to setTextColor of TextSwitcher and add IF statement that would change color based on int value timerState.. I can't figure out how to make it work besides possibly stopping the timer and creating another one once the millisecondsUntilFinished hits 10000 which actually lead to my second issue where:
I click on an imageButton that initiates a dialog fragment (PauseFragment) and calling cancel() on my CountDownTimer via timerCDT.cancel(). I ran into some nullpointer issues hence the if statements checking for null in my code, but now once the PauseFragment dismisses my new timer starts back at 60000 rather than where it last left off. I was hoping that long timerState = 60000 would get updated to whatever millisUntilFinished is everytime onTick() was called but I'm not sure where I went wrong!
Therefore, can someone please assist me with changing TextSwitcher text color dynamically and assist in figuring out why my CountDownTimer isn't starting at the expected value. Any assistance is greatly appreciated.
THANKS in advance!
public class GameActivity extends FragmentActivity implements PauseFragment.FragmentCommunicator,{
public static long timerState = 60000;
public static boolean isTimerOn = false;
private String modeChoice = ModesActivity.mode;
private TextSwitcher timerTextSwitcher;
CountDownTimer timerCDT;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...more code
timerTextSwitcher = (TextSwitcher) findViewById(R.id.timerTextSwitcher);
timerTextSwitcher.setFactory(new ViewSwitcher.ViewFactory() {
public View makeView() {
// Create a new TextView and set properties
TextView textView = new TextView(getApplicationContext());
textView.setLayoutParams(new TextSwitcher.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
textView.setTextSize(20);
textView.setTextColor(Color.BLUE);
if (timerState < 10001) {
textView.setTextColor(Color.RED);
}
return textView;
}
});
// Declare the animations and initialize them
Animation in = AnimationUtils.loadAnimation(this, android.R.anim.slide_in_left);
Animation out = AnimationUtils.loadAnimation(this, android.R.anim.slide_out_right);
// set the animation type to textSwitcher
timerTextSwitcher.setInAnimation(in);
timerTextSwitcher.setInAnimation(out);
}
timerCDT = new CountDownTimer(timerState, 1000) {
public void onTick(long millisUntilFinished) {
isTimerOn = true;
timerTextSwitcher.setText(String.valueOf(millisUntilFinished / 1000));
timerState = millisUntilFinished;
}
//TODO: assign highscores for players to beat
public void onFinish() {
timerTextSwitcher.post(new Runnable() {
#Override
public void run() {
createToast("GAME OVER!");
}
});
isTimerOn = false;
DialogFragment endDialog = new EndGameFragment();
endDialog.show(getSupportFragmentManager(), "EndGameDialogFragment");
}
};
timerCDT.start();
#Override
public void onPause() {
super.onPause();
Bundle args = new Bundle();
args.putInt(ARG_SCORE, scoreINT);
args.putLong(ARG_TIMER, timerState);
args.putString(GameActivity.ARG_MODE, modeChoice);
if (timerCDT != null) {
timerCDT.cancel();
}
else{
createToastExtended("onPause() - timerCDT is null; attempt to cancel");
}
}
//.!.other fun code here.!.
#Override
protected void onStop() {
super.onStop();
if (timerCDT != null) {
timerCDT.cancel();
}
else{
createToastExtended("onStop() - timerCDT is null; attempt to cancel");
}
}
//Player Response information
#Override
public void pauseFragmentResponse() {
if (timerCDT != null) {
timerCDT.start();
}
else{
createToastExtended("pauseFragmenResponse() - timerCDT is null; attempt to start");
}
}
public void pauseStartFrag(View view) {
DialogFragment dialog = new PauseFragment();
if (timerCDT != null) {
timerCDT.cancel();
}
else{
createToastExtended("pauseStartFrag() - timerCDT is null;attempt to cancel");
}
dialog.show(getSupportFragmentManager(), "PauseDialogFragment");
}
// Code for PauseFragment
//TODO: remove unuses imports on all files within project;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
public class PauseFragment extends DialogFragment {
public static boolean isPaused = false;
public FragmentCommunicator fComm;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
fComm = (FragmentCommunicator) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement FragmentCommunicator");
}
}
#Override
public void onDetach() {
super.onDetach();
fComm = null;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
isPaused = true;
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(inflater.inflate(R.layout.fragment_pause, null))
.setMessage(R.string.dialog_pause)
.setPositiveButton(R.string.action_main_menu, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent i4 = new Intent(getActivity(), StartActivity.class);
startActivity(i4);
}
})
.setNeutralButton(R.string.action_restart, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent i4 = new Intent(getActivity(), ModesActivity.class);
startActivity(i4); }
})
.setNegativeButton(R.string.action_resume, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
fComm.pauseFragmentResponse();
dismiss();
}
});
// Create the AlertDialog object and return it
return builder.create();
}
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
isPaused = false;
}
public interface FragmentCommunicator {
public void pauseFragmentResponse();
}
}
Lastly, Idk if it's of any help but I also tried starting the CountDownTimer timerCDT without the FragmentCommunicator interface but the system couldn't find the timer? If someone could shine light on why this happened I'd appreciate it as well.
Seriously, one last thing, if the timer is for a game and needs to be stopped and updated frequently, is it best to use CountDownTimer, TimerTask, a newThread that implements Runnable or a handler or some sort? I've tried them all but as I add components and features to the app I need more and more flexibility with changing the time and not quite sure if I'm headed down the right path. Hope this post isn't too vague. Please let me know if I need to separate into multiple posts or something...
Thanks as always!
just had a look on the developer website here http://developer.android.com/reference/android/os/CountDownTimer.html and it looks like you should probably be placing that if statement in the onTick method, so for every tick you do the check.
EDIT
ok this works perfectly for me
private TextSwitcher TextSw;
private TextView TextSwTextView;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(com.game.test.R.layout.sample);
TextSw = (TextSwitcher) findViewById(R.id.TextSwitchView);
TextSw.setFactory(new ViewSwitcher.ViewFactory()
{
public View makeView()
{
// Create a new TextView and set properties
TextView textView = new TextView(getApplicationContext());
textView.setLayoutParams(new TextSwitcher.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
textView.setTextSize(20);
textView.setTextColor(Color.BLUE);
return textView;
}
});
mtimer = new CountDownTimer(60000, 1000)
{
public void onTick(long millisUntilFinished)
{
TextSwTextView = (TextView) TextSw.getChildAt(0);
if(millisUntilFinished < 10001)
TextSwTextView.setTextColor(Color.RED);
TextSwTextView.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish()
{
TextSwTextView.setText("done!");
}
}.start();
}
so the above is a simple version of yours, the text that is displaying the timer will change to Red when the timer hit 1000. You should be able to build this into yours.
But the main thing you have to do here is to check how much the timer has left in the in the onTick method and also change the text color in here to - see above
This thread helped me solve my problem more easily:
https://groups.google.com/forum/#!topic/android-developers/jdlUp_RlP2w
Your get a handle on the textviews within the textSwitcher like this:
TextView t1 = (TextView) mSwitcher.getChildAt(0);
TextView t2 = (TextView) mSwitcher.getChildAt(1);
Then you set whatever color you need based on your code logic.
TextView t1, t2;
textSwitcher = (TextSwitcher) findViewById(R.id.textView99);
textSwitcher.setInAnimation(this, R.anim.slide_in_right);
textSwitcher.setOutAnimation(this, R.anim.slide_out_left);
t1 = new TextView(this);
t2 = new TextView(this);
t1.setTextSize(20);
t2.setTextSize(20);
textSwitcher.addView(t1);
textSwitcher.addView(t2);
I create adapter in onPostExecute like this, and i set button's id programmatically.
list.add(new adapters.GunADP("name","name","name",buttonId));
//i set button id 5000
When i try to getId in end of the onPostExecute method, android don't find that id. And i also can't get that id from onCreate because when app starts that buttun does not exist.
And i created hackButton for try to get id from hackButton's onClickListener, id returns successfully because onpostexecute method's finished and now that id exist but i don't want to use this way.
btn_devam = (Button) findViewById(R.id.button_ileri);
btn_devam.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Button x = (Button) findViewById(5000);
x.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(this, "tag "+v.getTag()+"id "+v.getId(), Toast.LENGTH_SHORT).show();
}
});
}
});
So how can i get button's id which i created programmatically after onPostExecute finished?
I want to use this code;
Button x = (Button) findViewById(5000);
I cannot use that in oncreate, and also end of the onpostexecute. So how can i get that specific id after that created.
I think you are missing the reference of the view that contains that Button.
yourView.findViewById("Id to search");
yourview is the reference of parent view of your button i.e V in your function argument.
I've solved!
I've created thread like this in on create
private Thread mMainThread;
mMainThread = new Thread(){
#Override
public void run(){
try{
synchronized (this) {
wait(2000);
try{
Button x = (Button) findViewById(5000);
x.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(BiletSecim.this, "tag "+v.getTag()+" id "+v.getId(), Toast.LENGTH_SHORT).show();
}
});
}catch(Exception e){
}
}
}catch (Exception e) {
}
}};
Then at the end of onpostexecute method i start the thread
mMainThread.start();
2000 miliseconds is okay for me.
I have an ImageButton in my application.
<ImageButton
android:id="#+id/imageButton1"
android:layout_width="80dp"
android:layout_height="80dp"
android:clickable="true"
android:src="#drawable/button" />
I bind it to an onClickListener:
View.OnClickListener imgButtonHandler = new View.OnClickListener() {
public void onClick(View v) {
// Here I update the image source to a different image.
}
};
Now what happens is: when I click the imagebutton, the imagebutton changes to a
different image. But I want it to change back automatically after 0.5 sec (during the
same time the user should not be able to click anything). How do I
implement that? I tried to sleep in the onClick function in the listener, but it's
not working...
New edit:
The proposed answer will solve my problem if I only have one imagebutton. I tried it out
and both work like charm!
Actually it is not working as expected. During that 500ms, the user still could click!
It is not solving the problem...
Posting a delayed runnable might do the job.
public void onClick(View v) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// change the background of the image button
(ImageButton)v.setBackgroundResource(R.drawable.someimage);
}
}, 500);
}
EDIT:
In fact, I've ran the following code on an actual device with two ImageButton and it works fine.
BTW, if you want the buttons to be un-clickable during the 500ms, just set it as imgBtn1.setClickable(false); and set it back to be clickable in the runnable as imgBtn1.setClickable(true);
public class TestFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.test_layout, container, false);
final ImageButton imgBtn1 = (ImageButton) view.findViewById(R.id.test_img_btn1);
final ImageButton imgBtn2 = (ImageButton) view.findViewById(R.id.test_img_btn2);
imgBtn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
imgBtn1.setBackgroundResource(R.drawable.device_type_apple);
imgBtn1.setClickable(false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// change the background of the image button
imgBtn1.setBackgroundResource(R.drawable.device_type_windows);
imgBtn1.setClickable(true);
}
}, 500);
}
});
imgBtn2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
imgBtn2.setBackgroundResource(R.drawable.device_type_apple);
imgBtn2.setClickable(false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// change the background of the image button
imgBtn2.setBackgroundResource(R.drawable.device_type_android);
imgBtn2.setClickable(true);
}
}, 500);
}
});
return view;
}
}
You can use handle with runnable to auto update image
Handler mHandler = new Handler();
Runnable mUpdateTimer = new Runnable() {
#Override
public void run() {
// code update image here
// auto update after 0.5s
mHandler.postDelayed(mUpdateTimer, 500);
}
};
And when image button clicked:
View.OnClickListener imgButtonHandler = new View.OnClickListener() {
public void onClick(View v) {
mHandler.postDelayed(mUpdateTimer, 500);
}
};
Handler.postDelayed
this method is not good way ,see http://developer.android.com/reference/android/os/Handler.html#postDelayed(java.lang.Runnable,long)
it say
Returns true if the Runnable was successfully placed in to the message queue. Returns false on failure, usually because the looper processing the message queue is exiting. Note that a result of true does not mean the Runnable will be processed -- if the looper is quit before the delivery time of the message occurs then the message will be dropped.
so this methed may never invoke,it may be make you image button status never come back ,so you must be care the return value or use other widget ViewFliper,it can set animation when image switch and you can set delpoy .
In my application i'm changing image of button for 1sec.how to compare image of button.i tried a lot.please help me.when i chang image 1st tyme after 1sec its not changing agian.its remain the same.below is the code-
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
if(time==-1){
onStop();
}
else
runOnUiThread(new Runnable() {
public void run() {
Random rand=new Random();
System.out.println("timer...."+time);
time=time-1;
int num = rand.nextInt(buttonIds.length);
int buttonId = buttonIds[num];
Button bb=(Button) findViewById(buttonId);
if((bb.getBackground()).equals(button.getBackground()))
{
bb.setBackgroundResource(R.drawable.happy);
wrong++;
System.out.println("llllllllllll"+wrong);
}
else
{
bb.setBackgroundResource(R.drawable.whoa);
count++;
System.out.println("mmmmmm"+count);
}
}
});
}
},0, 1000);
}
Edit
you are getting the button freshly like this
Button bb=(Button) findViewById(buttonId);
so it will always remains whoa....because the condition is always false.....
I would suggest you to set Content Description while setting the background resource and then compare the content Description....You can't compare by bb.getBackground()).equals(button.getBackground())
do something like this
but1=(Button) findViewById(R.id.b1);
but1.setBackgroundResource(R.drawable.happy);
but1.setContentDescription("happy");
and
if(bb.getContentDescription().equals(button.getContentDescription())
this is my first Question, i hope i do it right.
I need to change the color of some buttons in a specific interval.
I decided to do it with the Colorfilter, because the setBackground method makes the Button look ugly.
The Problem is the following:
If i set the ColorFilter within a Runnable, it is not working.
But:
Setting the ColorFilter in the onCreate or click method is working.
And:
Setting the BackgroundColor with setBackgroundColor within the Runnable is working.
I forgot to mention, that it is all working fine if i run it on an emulator with android 4.1 but not with 2.3.3.
Any ideas? Here is the code
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
int counter = 0;
Button b = null;
final Handler handler = new Handler();
final Runnable doit = new Runnable() {
public void run() {
if ( counter % 2 == 0) {
b = (Button) findViewById(R.id.button1);
b.setBackgroundColor(0xffff0000); // working
//b.getBackground().setColorFilter(0xFFD2691E, PorterDuff.Mode.MULTIPLY); // doesnt work
}
else {
//b.getBackground().clearColorFilter();
b.setBackgroundColor(0xff00ff00);
}
counter++;
}
};
public void click(View view) {
// configure timer 1
Timer timer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
handler.post(doit);
}
};
timer.schedule(task, 1111, 1111);
}
}
I had the same problem with imageviews.
I found a solution, you have to call the invalidate()-methode:
ImageView img =(ImageView) findViewById(R.id.myimageview);
img.getDrawable().clearColorFilter();
img.invalidate();