I'm trying to make a small Android game. My on click function however is not getting repeated... It adds one point the first time and then stops working. It looks correct to me.
addButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
playerScoreField = (TextView)findViewById(R.id.playerScore);
int playerScore = 0;
if(playerScore != target){
playerScore++;
playerScoreField.setText("You are at: " + playerScore);
} else {
addButton.setClickable(false);
addButton.setEnabled(false);
countDown.onFinish();
}
}
});
I think you might have a logic error. You are setting playerScore to zero on each click. This will result in the score always being 1. Declare your playerScore variable in a different way.
Related
I don't fully understand what is going on behind the scene, and therefore, what I can do to correctly code this issue. I'm looking for an explanation that will lead me to figure it out myself. This is just a fun home based project(I'm not a student), where I'm coding a turn based app. However, the battle scenes are randomly calculated durations, rather than turn based, so my desire is as follows:
Present initial battle count on screen for 2 seconds
Calculate first skirmish
Present updated battle count on screen for 2 seconds
Calculate 2nd skirmish
...
...
Present Victory or Defeat on screen
The problem I'm having is that the app is performing as follows currently:
Present initial battle count on screen
Calculate all skirmishes
Page displays null for the number, since it's apparently already returned?
Code looks like this:
void fightBattle(){
setContentView(R.layout.brigands);
boolean winnerDetermined = false;
while(!winnerDetermined) {
boolean brigandsWon = brigandsWon(player, brigandCount);
if(brigandsWon) {
player.removeWarriors(2);
}
displayWarriors(player);
if(brigandsWon){
if(player.getWarriors() < 2){
winnerDetermined = true;
}
}
if(!brigandsWon) {
brigandCount = brigandCount / 2;
}
displayBrigands();
if(brigandCount == 0){
winnerDetermined = true;
}
}
}
private void displayWarriors(Player player){
final Player currentPlayer = player;
new CountDownTimer(2000, 2000) {
public void onTick(long millisUntilFinished) { }
public void onFinish() {
setContentView(R.layout.warriors);
TextView warrior_count_tv = findViewById(R.id.warrior_count_tv);
warrior_count_tv.setText(currentPlayer.getWarriors());
}
}.start();
}
private void displayBrigands(Player player){
new CountDownTimer(2000, 2000) {
public void onTick(long millisUntilFinished) { }
public void onFinish() {
setContentView(R.layout.brigands);
TextView brigand_count_tv = findViewById(R.id.brigand_count_tv);
brigand_count_tv.setText(Integer.toString(brigandCount));
}
}.start();
}
Ultimately, what I want to see is something like the below sudo-code:
displayPage1For2Seconds;
while(somethingIsTrue){
calculateNumber;
displayPage2For2Seconds;
displayPage3for2Seconds;
}
displayPage4For2Seconds;
Calculate all skirmishes
Your current code does this because the while loop doesn't actually stops to wait. The flow will be like this:
enter while loop -> call displayWarriors() -> create CountDownTimer() to do something after 2 seconds -> return to while loop -> call displayBrigands() -> create CountDownTimer() to do something after 2 seconds -> return to while loop -> do the same until you exit while
With this code you'll end up with a bunch of CountDownTimers that are created and executed at the same(almost) time so after two seconds they all try to set a view to some value(with an indefinite behavior like you mention it happens).
There are several ways to do what you want. You could use a Thread for example:
void fightBattle(){
setContentView(R.layout.brigands);
new Thread(new Runnable() {
public void run() {
// I assume R.layout.brigands is the initial screen that you want to show for 2 seconds?!? In this case wait 2 seconds
TimeUnit.Seconds.sleep(2);
boolean winnerDetermined = false;
while(!winnerDetermined) {
// ...
// from your code it seems you want to show this for 2 seconds?
displayWarriors(player);
TimeUnit.Seconds.sleep(2);
//...
displayBrigands();
// also show this for 2 seconds
TimeUnit.Seconds.sleep(2);
// ...
}
}
}).start();
}
Then your display methods will be something like this:
private void displayWarriors(Player player){
// you need to wrap this code in a runOnUiThread() method(from the activity)
// because we are on a background thread and we are changing views!
final Player currentPlayer = player;
setContentView(R.layout.warriors);
TextView warrior_count_tv = findViewById(R.id.warrior_count_tv);
warrior_count_tv.setText(currentPlayer.getWarriors());
}
Another approach would be to use a Handler and break your code in Runnables that you then schedule at appropriate times.
I have a problem that i can't work out. I have a button that when clicked changes the text view. It then activates a postdelayed process that returns the textview to its original text after 2 seconds.
If i press the button once, and then again within this 2 second interval the postdelay will continue to count down from the first press and not restart itself from the second press. This results in the original text being shown when i want the changed text to be.
Each time the button is pressed it creates a delay from that instance. I want it to cancel the previous postdelay and start a new one. This is my code so far but its not finished because i can't work out how to finish it (so it does not work).
p1AddL.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
counter1 ++;
count1 ++;
Handler h = new Handler();
if ('PREVIOUS_DELAY_HAS_STARTED') {
h.removeCallbacks(clickButton);
h.postDelayed(clickButton, 2000);
} else {
h.postDelayed(clickButton, 2000);
}
if (count1 > 0) {
lifepointsP1.setText("+" + count1);
lifepointsP1.setTextColor(Color.argb(220, 0, 188, 0));
}
}
});
Runnable clickButton = new Runnable() {
#Override
public void run() {
count1 = 0;
lifepointsP1.setTextColor(Color.WHITE);
lifepointsP1.setText(counter1);
}
};
the PREVIOUS_DELAY_HAS_STARTED text needs to be some sort of checking method and i'm pretty sure i need something between the h.removeCallbacks and h.postDelayed commands under that text.
If their is a simpler way/better way to write this method to make it work please let me know. I have tried so many ways and i feel i am very close here.
removeCallbacks won't do anything if clickButton isn't registered on h. So you can simply replace
if ('PREVIOUS_DELAY_HAS_STARTED') {
h.removeCallbacks(clickButton);
h.postDelayed(clickButton, 2000);
} else {
h.postDelayed(clickButton, 2000);
}
with
h.removeCallbacks(clickButton);
h.postDelayed(clickButton, 2000);
could anyone explain, what i'm doing wrong?
in this case below, "tt" is my TexView.
On my Oncreate() method, I have:
tt = (TextView) findViewById(R.id.ni);
tt.setText("This is a try");
and then
tt.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
String vi = tt.getText().toString().substring(tt.getSelectionStart(),tt.getSelectionEnd());
Toast.makeText(getApplicationContext(), vi,Toast.LENGTH_LONG).show();
}
});
Nothing is Shown at Onclick.
thanks.
I encountered the same problem a few days ago and I could find the following solution in the end. Delaying the process even 10 milliseconds could help interestingly. Put this in your onClick/onLongClick method, wherever you want to fetch the selected text.
For the original answer: textView.getSelectionEnd() returning start index value on Samsung Marshmallow 6.0 devices
I hope this helps those who have similar problem in the future.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
int startIndex = textView.getSelectionStart();
int endIndex = textView.getSelectionEnd();
if ((endIndex - startIndex) <= 0) {
return;
}
// UI related code here
}
}, TIME_IN_MS_TO_DELAY);
return false;
I'm writing a quiz application which presents the user with a question and 4 choices. When the user clicks on a choice, the app should change the colour of the correct choice to green and the colour of the incorrect choice to red. It should then wait a second before displaying the next question.
The problem is that it doesn't do the colour changes (except for the last question) and I don't understand why. I know that my android.os.SystemClock.sleep(1000) has something to do with it.
I'd appreciate it if you could tell me where I've gone wrong or if I'm going about this an incorrect way. Thanks :)
public void onClick(View v) {
setButtonsEnabled(false);
int answer = Integer.parseInt(v.getTag().toString());
int correct = question.getCorrectAnswer();
if(answer == correct)
numCorrect++;
highlightAnswer(answer,correct,false);
android.os.SystemClock.sleep(1000);
MCQuestion next = getRandomQuestion();
if(next != null) {
question = next;
highlightAnswer(answer,correct,true);
displayQuestion();
setButtonsEnabled(true);
}
else {
float percentage = 100*(numCorrect/questionsList.size());
QuizTimeApplication.setScore(percentage);
Intent scoreIntent = new Intent(QuestionActivity.this,ScoreActivity.class);
startActivity(scoreIntent);
}
}
private void setButtonsEnabled(boolean enable) {
for(Button b: buttons)
b.setEnabled(enable);
}
private void highlightAnswer(int answer, int correct, boolean undo) {
if(undo) {
for(Button button : buttons) {
button.setTextColor(getResources().getColor(R.color.white));
button.setTextSize(FONT_SIZE_NORMAL);
}
return;
}
buttons[correct].setTextColor(getResources().getColor(R.color.green));
buttons[correct].setTextSize(FONT_SIZE_BIG);
if(answer!=correct) {
buttons[answer].setTextColor(getResources().getColor(R.color.red));
buttons[answer].setTextSize(FONT_SIZE_BIG);
}
}
SystemClock.sleep(1000);
will give unexpected behaviour and may not work good for your requirement. It is better you use Handler with a delay like below.
Handler h = new Handler();
h.postDelayed(new Runnable(){
#Override
public void run()
{
//your code that has to be run after a delay of time. in your case the code after SystemClock.sleep(1000);
},YOUR_DELAY_IN_MILLISECONDS
);
I am making an Android game modeled after the old Simon game. It is a little different in the layout as it is using a 3x3 layout of buttons. I am trying to get the buttons to light up one at a time inside the loop that randomly selects a button. The trouble I have is that all of the buttons light up at once and only the last (or first, not sure) changes back to the original color. I have tried very thoroughly to find an appropriate answer to my situation but have had no luck here or elsewhere. The button id(s) are in the butts[]. butts[0] is button 1, butts[2] ... Below is my attempt.
public void play()
{
for(int x = 0; x <= numButtons; ++x)
{
spot = randomGenerator.nextInt(9);
playMe[x] = spot;
//butts[spot].setBackgroundColor(Color.parseColor("#540115"));
handler.postDelayed(new Runna(spot), (x+1)*1000);
}
}
class Runna implements Runnable
{
public Runna(int j2)
{
butts[j2].setBackgroundColor(Color.parseColor("#540115"));
}
public void run()
{
butts[spot].setBackgroundColor(Color.LTGRAY);
}
}
I think it has to do with the value of spot. It is global to the functions and you change it every time. It runs, but at the end there is still only one spot and EVERY runnable is trying to change that same spot.
Perhaps save spot in your runnable?
class Runna implements Runnable
{
int s;
public Runna(int j2)
{
s = j2;
butts[s].setBackgroundColor(Color.parseColor("#540115"));
}
public void run()
{
butts[s].setBackgroundColor(Color.LTGRAY);
}
}
Have you tried to invalidate the button each time?
public Runna(int j2)
{
butts[j2].setBackgroundColor(Color.parseColor("#540115"));
butts[j2].invalidate();
}