I did this code and want to make a traffic light on and off several times and then stop and choose one of the two lights at random, but the program does the operation, but does not show the changing lights as the operation does
private ImageView redLight;
private ImageView greenLight;
private Button Button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.traffic_lights);
redLight = (ImageView) findViewById(R.id.red_light);
greenLight = (ImageView) findViewById(R.id.green_light);
Button = (Button) findViewById(R.id.start_button);
// Assign click listeners to buttons
Button.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v == Button) {
int flag = 0;
for (int i = 0; i <= 100; i++) {
if (flag == 0) {
turnOnRedLight();
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
Log.i("Traffic", "Red");
flag = 1;
} else {
turnOnGreenLight();
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
Log.i("Traffic", "Green");
flag = 0;
}
}
}
}
private void turnOnRedLight() {
redLight.setImageResource(R.drawable.red_on);
}
private void turnOnGreenLight() {
greenLight.setImageResource(R.drawable.green_on);
}
}
You are only sleeping for 100ms so you probably aren't seeing the lights change. Change that to something like 1000 or maybe even 500 and you will probably see the change
Thread.sleep(1000);
Also, a couple notes
Although with this code it may not be a problem, sleeping on the UI Thread usually isn't a good idea. Use a Thread and update UI with runOnUiThread(), use AsyncTask, or Handler.
Don't name your Button "Button". Name it something that isn't an Android keyword like button, btn, startButton, startBtn, or something similar.
When distinguishing between which Button was clicked use the Button id instead of the Object. So you would want to change it to
#Override
public void onClick(View v) {
if (v.getId() == (R.id.start_button)) {
you could also use a switch statement here but not important.
Related
Today I'm developing an App which can intercept the launch between activities, My key code is:
ActivityManagerNative.getDefault().setActivityController(new InterceptActivityController(), false);
private class InterceptActivityController extends IWeChatActivityController.Stub {
void InterceptActivityController() {}
#Override
public boolean activityStarting(Intent intent, String pkg) {
showDialog();
return false;
}
}
private void showBottomDialog() {
Log.d(TAG, "showBottomDialog");
Dialog bottomDialog = new Dialog(mContext);
View contentView = LayoutInflater.from(this).inflate(android.R.layout.simple_list_item_2, null);
bottomDialog.setContentView(contentView);
ViewGroup.LayoutParams layoutParams = contentView.getLayoutParams();
layoutParams.width = getResources().getDisplayMetrics().widthPixels;
contentView.setLayoutParams(layoutParams);
bottomDialog.getWindow().setGravity(Gravity.BOTTOM);
bottomDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
bottomDialog.show();
}
I defined a Button and planned to start an Activity after clicking it. But now I intercept this action and just show a dialog in the function of activityStarting and then return false, after dismissing this dialog, I click the button again, but nothing works, dialog doesn't show any more, Who knows the reason ? Maybe I think this is a google source bug, but I'm not sure.
You know the Dialogs need to be Shown in a Timely manner. I mean You need the Dialog to be Shown for How Long? When you Start showing a Dialog and Dismiss it, It's Not Destroyed, It's just Dismissed.
Look at the Code below. I wrote this in my own app, It's Safe. Try it and see if you're satisfied with it:
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bottomDialog.show();
new Thread(new Runnable() {
#Override
public void run() {
try {
for (int i = 0; i <= 1200; i++) {
Thread.sleep(100); //The time it takes to update i
if (i = 1200) {
bottomDialog.dismiss();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
You can use AsyncTask as well. Also, I put the whole thing in a Click Listener just to show how it can be used.
The idea is define a showing Time for the Dialog
Any idea how to illustrate backspace funtion in this code? I try to make some changes but it can't work the backspace function. So, i would like to help me, with the backspace button.
enter code here
public class MainActivity extends AppCompatActivity implements OnClickListener {
private TextView mCalculatorDisplay;
private Boolean userIsInTheMiddleOfTypingANumber = false;
private CalculatorBrain mCalculatorBrain;
private static final String DIGITS = "0123456789.";
DecimalFormat df = new DecimalFormat("############");
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
// hide the window title.
requestWindowFeature(Window.FEATURE_NO_TITLE);
// hide the status bar and other OS-level chrome
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCalculatorBrain = new CalculatorBrain();
mCalculatorDisplay = (TextView) findViewById(R.id.textView1);
df.setMinimumFractionDigits(0);
df.setMinimumIntegerDigits(1);
df.setMaximumIntegerDigits(8);
findViewById(R.id.button0).setOnClickListener(this);
findViewById(R.id.button1).setOnClickListener(this);
findViewById(R.id.button2).setOnClickListener(this);
findViewById(R.id.button3).setOnClickListener(this);
findViewById(R.id.button4).setOnClickListener(this);
findViewById(R.id.button5).setOnClickListener(this);
findViewById(R.id.button6).setOnClickListener(this);
findViewById(R.id.button7).setOnClickListener(this);
findViewById(R.id.button8).setOnClickListener(this);
findViewById(R.id.button9).setOnClickListener(this);
findViewById(R.id.buttonBackspace).setOnClickListener(this);
findViewById(R.id.buttonAdd).setOnClickListener(this);
findViewById(R.id.buttonSubtract).setOnClickListener(this);
findViewById(R.id.buttonMultiply).setOnClickListener(this);
findViewById(R.id.buttonDivide).setOnClickListener(this);
findViewById(R.id.buttonToggleSign).setOnClickListener(this);
findViewById(R.id.buttonDecimalPoint).setOnClickListener(this);
findViewById(R.id.buttonEquals).setOnClickListener(this);
findViewById(R.id.buttonClear).setOnClickListener(this);
// The following buttons only exist in layout-land (Landscape mode) and require extra attention.
// The messier option is to place the buttons in the regular layout too and set android:visibility="invisible".
if (findViewById(R.id.buttonSquareRoot) != null) {
findViewById(R.id.buttonSquareRoot).setOnClickListener(this);
}
if (findViewById(R.id.buttonSquared) != null) {
findViewById(R.id.buttonSquared).setOnClickListener(this);
}
if (findViewById(R.id.buttonInvert) != null) {
findViewById(R.id.buttonInvert).setOnClickListener(this);
}
if (findViewById(R.id.buttonSine) != null) {
findViewById(R.id.buttonSine).setOnClickListener(this);
}
if (findViewById(R.id.buttonCosine) != null) {
findViewById(R.id.buttonCosine).setOnClickListener(this);
}
if (findViewById(R.id.buttonTangent) != null) {
findViewById(R.id.buttonTangent).setOnClickListener(this);
}
}
#Override
public void onClick (View v) {
String buttonPressed = ((Button) v).getText().toString();
if (DIGITS.contains(buttonPressed)) {
// digit was pressed
if (userIsInTheMiddleOfTypingANumber) {
if (buttonPressed.equals(".") && mCalculatorDisplay.getText().toString().contains(".")) {
// ERROR PREVENTION
// Eliminate entering multiple decimals
} else {
mCalculatorDisplay.append(buttonPressed);
}
} else {
if (buttonPressed.equals(".")) {
// ERROR PREVENTION
// This will avoid error if only the decimal is hit before an operator, by placing a leading zero
// before the decimal
mCalculatorDisplay.setText(0 + buttonPressed);
} else {
mCalculatorDisplay.setText(buttonPressed);
}
}
userIsInTheMiddleOfTypingANumber = true;
}else{
// operation was pressed
if (userIsInTheMiddleOfTypingANumber) {
mCalculatorBrain.setOperand(Double.parseDouble(mCalculatorDisplay.getText().toString()));
userIsInTheMiddleOfTypingANumber = false;
}
mCalculatorBrain.performOperation(buttonPressed);
if (new Double(mCalculatorBrain.getResult()).equals(0.0)) {
mCalculatorDisplay.setText("" + 0);
} else {
mCalculatorDisplay.setText(df.format(mCalculatorBrain.getResult()));
}
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Save variables on screen orientation change
outState.putDouble("OPERAND", mCalculatorBrain.getResult());
outState.putDouble("MEMORY", mCalculatorBrain.getMemory());
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
// Restore variables on screen orientation change
mCalculatorBrain.setOperand(savedInstanceState.getDouble("OPERAND"));
mCalculatorBrain.setMemory(savedInstanceState.getDouble("MEMORY"));
if (new Double(mCalculatorBrain.getResult()).equals(0.0)){
mCalculatorDisplay.setText("" + 0);
} else {
mCalculatorDisplay.setText(df.format(mCalculatorBrain.getResult()));
}
}
}
In your layout you can add a onClick attribute to each button, say onClick="function", and in your activity you just need to implement a method like this:
public void function(View v) {
switch(v.getId()) {
case R.id.buttonBackspace:
// handle the backspace button
break;
case R.id.xxx:
// handle the button
break;
...
}
}
And for digits, I suggest assign a tag to each digit button in the layout, and do your logic in java based on the tag, instead of the text on the button. Because the text is just a UI, it might change in the future due to other possible requirements.
I'm making a game in Android that has 1 ImageView and 4 images and buttons. I set up the ImageView so that a random image is placed in it and a new random image is displayed after so much time has passed. I need to find a way to put a delay between the changing of the images that doesn't lock the UI. Here is the code that is relevant.
public class MainGameActivity extends Activity {
int points = 0, score = 0, timer = 1000;
ImageView imgView = (ImageView)findViewById(R.id.image);
Random randy = new Random();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_game_activity);
while(points >= 0) {
changeImage();
//Timer goes here
}
}
private void changeImage() {
int randyInt = randy.nextInt(4);
if (randyInt == 0){
imgView.setImageDrawable(getResources().getDrawable(R.drawable.cheese));
} else if (randyInt == 1) {
imgView.setImageDrawable(getResources().getDrawable(R.drawable.worm1));
} else if (randyInt == 2) {
imgView.setImageDrawable(getResources().getDrawable(R.drawable.worm2));
} else if (randyInt == 3) {
imgView.setImageDrawable(getResources().getDrawable(R.drawable.minnow));
}
}
}
The 4 buttons use the same drawables as the ImageView. When the button is pressed the drawable in the ImageView and the drawable in the Image Button are checked for equivalence, so the UI still has to work while the while loop containing the pause in changing the ImageView drawable is still running. Thanks for any assistance you can give.
Sounds like you need a timer.
That has been asked and answered. Please have a look at this stackoverflow answer Android timer? How-to?
also you may try a Switch case instead of all those ifs
Switch(randyInt){
case 1:imgView.setImageDrawable(getResources().getDrawable(R.drawable.cheese));
break;
case 2:imgView.setImageDrawable(getResources().getDrawable(R.drawable.worm1));
break;
case 3:imgView.setImageDrawable(getResources().getDrawable(R.drawable.worm2));
break;
case 4:imgView.setImageDrawable(getResources().getDrawable(R.drawable.minnow));
break;
default:imgView.setImageDrawable(getResources().getDrawable(R.drawable.cheese));
break;
}
You can use the Timer like Lasse pointed in his answer. First of all you need to declare it:
private CountDownTimer timer;
Then in your onCreate you can call the timer (In this example, I'm changing the image every 5 seconds (5000ms), but you can change it if you want):
timer = new CountDownTimer(5000, 20) {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
try{
callImage();
}catch(Exception e){
}
}
};
Then in your callImage method, you set the image on the imageView and start the timer again:
private void callImage(){
int randyInt = randy.nextInt(4);
if (randyInt == 0){
imgView.setImageDrawable(getResources().getDrawable(R.drawable.cheese));
} else if (randyInt == 1) {
imgView.setImageDrawable(getResources().getDrawable(R.drawable.worm1));
} else if (randyInt == 2) {
imgView.setImageDrawable(getResources().getDrawable(R.drawable.worm2));
} else if (randyInt == 3) {
imgView.setImageDrawable(getResources().getDrawable(R.drawable.minnow));
}
try{
imgView.post(new Runnable() {
#Override
public void run() {
timer.start();
}
});
}catch(Exception e){
Log.e("Error", "Error: " + e.toString());
}
}
So, every 5 seconds (or the time that you need) it will change the image, and will not block the UI.
Hope it helps!
The purpose of my app is: User enters a number and clicks a button. The button uses the input to calculate the Fibonacci sequence with a timer - with each number in the sequence displaying each second to a textView. But when I try to run the timer I get the CalledFromWrongThreadException. I've posted my code below. As you can tell by my log statements I believe I know which line is causing the problem. I think it's because I'm calling a method which is outside my onclicklistener but when I move that other method around I just cause more problems.
I've read a couple other posts and I'm not really sure what the proper way is to print to a text area using my method. Does anyone know how I can make this work?
public class MainActivity extends Activity {
// primary widgets
private EditText editText;
private TextView textView;
private Button button1;
static int seconds = 0;
static Timer timer;
static ArrayList<Integer> fibList = new ArrayList<Integer>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.editText1);
textView = (TextView) findViewById(R.id.textView2);
button1 = (Button) findViewById(R.id.button1);
final int delay = 1000;
final int period = 1000;
timer = new Timer();
//Attempt to clear TextView
textView.setText("");
button1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//Clear Textview
String array = " ";
fibList.clear();
textView.setText(array);
//Log.i("ARRAY", "ATTEMPT to CLEAR"+fibList);
String input = editText.getText().toString();
int number = Integer.parseInt(input);
int tmp = 0;
// confirm input
if (number < 20) {
Toast.makeText(getApplicationContext(),
"You entered: " + number, Toast.LENGTH_LONG).show();
for (int i = 0; i <= number; i++) {
fibList.add(fib(i));
// sum even numbers
if (fib(i) % 2 == 0) {
tmp += fib(i);
}
}
} else {
Toast.makeText(getApplicationContext(),
"Number is too Large: " + number, Toast.LENGTH_LONG)
.show();
}
//I believe error occurs in this method
Log.i("TEST", "START TIMER");
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
Log.i("TEST", "RUN TIMER");
int nextIndex = setInterval();
Log.i("TEST", "SET INTERVAL");
if (nextIndex < fibList.size()) {
Log.i("TEST", "TRY TO PRINT");
//It looks like error occurs here when I try to print to textView
textView.setText(fibList.get(nextIndex)+ " ");
Log.i("TEST", "NEXT INDEX"+fibList.get(nextIndex));
Log.i("TEST", "DID PRINT");
}
}
}, delay, period);
Log.i("TEST", "END TIMER");
}
});
}
// run fibonacci sequence
public static int fib(int n) {
if (n < 2) {
return n;
} else {
return fib(n - 1) + fib(n - 2);
}
}
//counts up for every element through the array
public static final int setInterval() {
if (seconds >= fibList.size())
timer.cancel();
return seconds++;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
You can use
runOnUiThread(new Runnable(){
public void run(){
textView.setText("aaa");
}
});
Have your timer post a message to a Handler. The handler will, by default, run on the main thread. IT can then change the UI as needed, so just put the body of your timer into that handler.
I just had this problem and came on to StackOverflow to check out a solution. Didn't find anything proper but a little more experimenting with lot many Logs and debugging got me my solution.
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText("Your String");
}
});
In my code, the problem was due to me accessing Two TextViews in seperate threads one after another using TextView.post(new Runnable...). I guess this was due to it not being able to access UI Thread (as it was busy with previous thread changes). Setting both TextViews together in UI Thread solved the problem. So posting here for anyone else who might be perplexed by similar problem. Hope it helps.
I have the following code in my activity:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!isPreviouslyLoggedIn()) {
setContentView(R.layout.splash);
final TextView revolution=(TextView) findViewById(R.id.textView1);
final Button login=(Button) findViewById(R.id.loginButton);
final Button signUp=(Button) findViewById(R.id.signUpButton);
login.setOnClickListener(loginListener);
signUp.setOnClickListener(signUpListener);
}
else {
setContentView(R.layout.home);
Intent intent = new Intent(getApplicationContext(), PickUpActivity.class);
startActivity(intent);
}
}
When the if statements are executed, the layout is set to splash. However, in cases when the else statement is executed the layout is not set to home and the intent is directly started. Why is this happening and how can I prevent this?
Try this way..
protected boolean active = true;
protected int time = 5000;
Thread thread = new Thread() {
#Override
public void run() {
try {
int waited = 0;
while (active && (waited < time)) {
sleep(100);
if (active) {
waited += 100;
}
}
} catch (InterruptedException e) {
} finally {
finish();
Intent Go_Activity = new Intent(Screen.this, otherActivity.class);
startActivity(Go_Activity);
stop();
}
}
};
thread.start();
It help you.
Thanks.
Set Any Time or Thread to wait some time to go next activity. When else statement executed then layout set but for few time. for this reason you do not able to show it.
Thanks
You know what are you trying to ask ?? After setting content view straightly you are starting the another activity so it will show the new(started)activity layout... what is wrong then ?