Android: Button's onClick Method not processed linearly? - android

I'm learning Android app coding and thought it would be a nice idea to code TicTacToe. So I got me six buttons aligned linearly in one activity, which change their color when clicked on, depending on the player's turn (orange or blue). The onClickListener's onClick method goes as follows:
public void onClick(View v)
{
if(player == 1)
{
((Button)v).setBackgroundColor(getResources().getColor(android.R.color.holo_orange_dark));
}
else
{
((Button)v).setBackgroundColor(getResources().getColor(android.R.color.holo_blue_light));
}
gameControl();
}
gameControl follows with the game basics: Check if a player won, if it is a draw or not etc.:
public void gameControl()
if(checkForWin())
{
playerWins(player);
}
else if(round == 9)
{
draw();
}
else
{
if(player == 1)
player = 2;
else
player = 1;
}
round++;
}
My problem is that if a player won, that is if the last button to win the game is clicked, the button's color won't change. Rather, the playerWins method (in gameControl) refreshes the "playfield" before the button's color changes. I've tried stuff like Handler.postDelayed and such because it seems like the entire onClick methods is run through before the button's color is addressed, but no success there. Why is the onClick method not processed linearly? Is there any way to refresh the activity or something? Thanks in advance ...
Thanks for the quick response, here are the requested methods:
private void playerWins(int player)
{
if(player == 1)
{
player1Points++;
Toast.makeText(this,"Player 1 wins!", Toast.LENGTH_SHORT).show();
updatePointsText();
resetBoard();
round = 1;
}
if(player == 2)
{
player2Points++;
Toast.makeText(this,"Player 2 wins!", Toast.LENGTH_SHORT).show();
updatePointsText();
resetBoard();
round = 1;
}
}
The resetBoard method:
private void resetBoard()
{
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
buttons[i][j].setBackgroundColor(Color.parseColor("#B0C4DE"));
}
}
}

Yes, it is happening to quickly i guess and that's why you are not seeing it. You have a some approaches:
1- Putting a refresh button somewhere and only refresh when it is clicked (This option would be good for example if users know it will be a draw and they want to start again before finishing). So with this option you will not reset before user see the update.
2- Showing an AlertDialog to say "Player X wins!" and when user press OK you reset the board. It would be something like
AlertDialog dialog = AlertDialog.Builder(context);
dialog.setTitle("Your title");
dialog.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
resetBoard()
}
});
dialog.setCancellable(false);
dialog.show();
Also just check you can reduce some code refactoring, as you are repeating code. For example playerWins() could be
private void playerWins(int player){
if(player == 1)
{
player1Points++;
Toast.makeText(this,"Player 1 wins!", Toast.LENGTH_SHORT).show();
}
if(player == 2)
{
player2Points++;
Toast.makeText(this,"Player 2 wins!", Toast.LENGTH_SHORT).show();
}
updatePointsText();
resetBoard();
round = 1;
}

Related

Condition On Button click

When the button is clicked it should show me some text. This is working. Whenever the limit on the button click is exceeded, it must show some user defined text. After clicking the button 3 times, it is showing me some text not the user defined one. Here is my code for the OnClickListener:
final Button btnca =(Button) findViewById(R.id.btnca);
btnca.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int c=1;
if(c <= 3) //if button click for first three times
{
new FancyShowCaseView.Builder(Playing.this)
.title(questionPlay.get(index).getCorrectAnswer())
.build()
.show();
score -= 10;
txtScore.setText(String.format("%d", score));
c++;
}
if(c>3) //if button click for after three times
{
new FancyShowCaseView.Builder(Playing.this)
.title("Your Limit Exceed")
.build()
.show();
}}
});
The problem is that c is local to the onClick method so it is starting at 1 for every click. Try moving it out to the class level
final Button btnca =(Button) findViewById(R.id.btnca);
btnca.setOnClickListener(new View.OnClickListener() {
int c=1; //initialize here so it's re-used in each onClick
#Override
public void onClick(View v) {
if(c <= 3) //if button click for first three times
{
new FancyShowCaseView.Builder(Playing.this)
.title(questionPlay.get(index).getCorrectAnswer())
.build()
.show();
score -= 10;
txtScore.setText(String.format("%d", score));
c++;
}
if(c>3) //if button click for after three times
{
new FancyShowCaseView.Builder(Playing.this)
.title("Your Limit Exceed")
.build()
.show();
}}
});
Edit: I should mention this isn't a complete solution. I'll assume this code is in Activity(or Fragment).onCreate(). The counter will reset on configuration change when your lifecycle component is re-created, but I'll leave that solution as an exercise for the reader :)
You should initialize counter variable c outside of onClick() method. Of-course you should initialize it as c = 0 instead of c = 1 to get the toast after 4th click.
Try this:
final Button btnca =(Button) findViewById(R.id.btnca);
btnca.setOnClickListener(new View.OnClickListener() {
int c = 0;
#Override
public void onClick(View v) {
if(c <= 3) //if button click for first three times
{
new FancyShowCaseView.Builder(Playing.this)
.title(questionPlay.get(index).getCorrectAnswer())
.build()
.show();
score -= 10;
txtScore.setText(String.format("%d", score));
c++;
}
if(c>3) //if button click for after three times
{
new FancyShowCaseView.Builder(Playing.this)
.title("Your Limit Exceed")
.build()
.show();
// Reset if required
//c = 0;
}}
});
FYI, if you want to reset variable c, then reset(c = 0) it inside your condition if(c>3).
Hope this will help~

How to set multiple click action in a imageview and plus, minus button increment and decrement in android

Hlw,
Problem1:
I am developing a app where I have a ImageView like favorite button where I click and change this image resource(it is done), but I want to set action when user again click this imageview and the image remain same.
Problem2:
I have two image button "plus" and "minus" I set condition to it that when user click + button middle textview increment by 1, and when it reach 10 then the button will unclickable, also for the minus button, when textviw equal=0 then it not works...
I done it by condition but when minus button reach 0 and after plus button click, it increment but not decrement it remain unclickable...
how can i solve this problem?
Image like this
productWrapper.plus.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// Toast.makeText(context, "Plus", Toast.LENGTH_SHORT).show();
try
{
String presentValStr= finalProductWrapper2.selectedQuantity.getText().toString();
int presentIntVal=Integer.parseInt(presentValStr);
presentIntVal++;
if (presentIntVal>=10){
Toast.makeText(context,"You can select max 10 product",Toast.LENGTH_LONG).show();
finalProductWrapper2.plus.setEnabled(false);
}
finalProductWrapper2.selectedQuantity.setText(String.valueOf(presentIntVal));
}
catch(Exception e)
{
e.printStackTrace();
Toast.makeText(context,"Error! please try again",Toast.LENGTH_LONG).show();
}
}
});
final ProductWrapper finalProductWrapper = productWrapper;
productWrapper.heart.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
finalProductWrapper.heart.setImageResource(R.drawable.heart2);
}
});
Point #1.
You can use boolean flag like below
if(flag == true){
flag = false;
// Change your Image Resource here
}
else {
flag = true;
// Do your other action
}
for Minus button put following condition
if(YOUR_POINTS >0){
// Do your action
}
else {
// Ignore
}

Adding point to score

I'm working on a school project in Android Studio (a small game) and I now want to implement scores.
So here is the code where I want to implement the score:
private int score = 0;
final View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
if(v.equals(buttonBigger) && doubleResult1 > doubleResult2) {
Log.v("TAG", "you are right");
// Add 1 point to score
generatorEasy1();
generatorEasy2();
}
else {
Log.v("TAG", "you are wrong");
goToEndscreen(); // Go to Endacreen when wrong
}
}
};
So whenever you pressed the right button I want to add 1 point to the score. I've tried the following:
if(v.equals(buttonBigger) && doubleResult1 > doubleResult2) {
Log.v("TAG", "you are right");
score += 1;
textScore.setText("Score : " + score);
}
The problem is that if I run the app and I press the right button, the score stays 0.
I don't know what I'm doing wrong so it would be nice if someone could help me.
Not sure what you are trying to do with this game. But, you can set an on click listener directly on the buttons that are to be clicked. No need to add an if statement to check which view is initiating the listener.
biggerButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Whatever you want to do when the
// button is clicked in here.
}
});

android setBackgroundColor in onTouch sometimes not working

I have an app where I handle all the touches myself instead of using touch and gesture detection APIs, because it is a floating window and is the only way that works.
One of the things I do is change the color of the view under the finger.
OnTouch I check which view is under the finger if it is different from the previous I run:
myView.setBackgroundColor(getResources().getColor(R.color.white));
It doesn't work when I go to the view next to the current and return very fast.
I have checked it with logs and the view found is correct. And I have also checked and the line where setBackgroundColor is, is executed.
So I don't know what else to do. Are any cases in which setBackgroundColor doesn't work? Is it that if onTouch takes too much time to execute doesn't finish its tasks?
Any clue of how to fix this?
EDIT:
It only fails when I go to the view next to the current and return fast.
I didn't add the code because I thought it was harder to read than the abstraction I did. I have cleaned it up and posted.
If you think any methods called are relevant I can add them.
EDIT 2:
Code that runs if ACTION is not ACTION_DOWN or ACTION_UP. Those cases are not related.
if ((isPortrait && isPortraitMeasured) || (!isPortrait && isLandscapeMeasured)) {
//Log.d("algor", "Here calculate where it is");
final int lastCol = currentColumn;
final int lastRow = currentRow;
findCell((int) event.getRawX(), (int) event.getRawY());
if ((lastCol == currentColumn && lastRow == currentRow)) {
if (isPortrait && currentRow==-1 || (!isPortrait && currentColumn==-1)
&& !wasPressed && currentTable!=mainTable) {
//is actionBar. Check if finger is over back icon, to go back
//Code not related to the problem...
}
} else {
int currentIndex = getAppsListIndex();
if (currentIndex >= 0) {
View nextApp;
if (isPortrait)
nextApp = cellsP.get(currentTable).get(currentIndex);
else
nextApp = cellsL.get(currentTable).get(currentIndex);
final Object tag = nextApp.getTag();
if (tag instanceof FolderData) {
//Code not related to the problem...
} else {
Log.d("fastf", "time to change color");
//nextApp.setBackgroundColor(getResources().getColor(R.color.white));
nextApp.setBackgroundColor(whiteColor);
//nextApp.setBackground(getResources().getDrawable(R.color.white));
/*final View app = nextApp;
app.post(new Runnable() {
#Override
public void run() {
app.setBackgroundColor(getResources().getColor(R.color.white));
}
});*/
}
} else {
//Code not related to the problem...
}
int lastIndex = getAppsIndexFromInts(lastRow, lastCol);
//lastCol != -2 is because otherwise, on opening the launcher it animates
// the last app launched
if (lastIndex >= 0 && lastCol != -2) {
View lastApp;
if (isPortrait)
lastApp = cellsP.get(currentTable).get(lastIndex);
else
lastApp = cellsL.get(currentTable).get(lastIndex);
ObjectAnimator animator = ObjectAnimator.ofInt(lastApp,
"backgroundColor", getResources().getColor(R.color.clear_gray),
getResources().getColor(R.color.white_overlay_transition));
animator.setDuration(500);
animator.setEvaluator(new ArgbEvaluator());
animator.start();
}
}
}
You should use
nextApp.setBackgroundResource(...) instead of others.
Because of your "R.color.white" is a resource.
Have a nice day.
It was an old question but, I faced same problem and resolved with this change.
try it
myView.setBackground(getResources().getDrawable(R.color.white));
myView.setBackgroundColor(getResources().getColor(R.color.bgcolor));
color.xml
<color name="bgcolor">#ffffff</color>

Preventing Negative Numbers in TextView

I have a TextView that displays a number (in this case, the number is 10).
Now, i have a button so the user has to press that button 10 times in order for the number to hit 0, resulting in moving on to the next level. However,
I can keep hitting that button and it starts its way back into the negatives (-1, -2, etc.).
I tried to think of how I would prevent this but I'm at loss.. any ideas?
-----------------------------------EDIT-----------------------------------------
Okay, so here is my update (I got it to stop at 0):
public void onClick(View v) {
// TODO Auto-generated method stub
if (scr >= 1) {
scr = scr - 1;
TextView Score = (TextView) findViewById(R.id.Score);
Score.setText(String.valueOf(scr));
}
if (scr == 10)
{
aCounter.start();
}
if (scr == 1)
{
aCounter.cancel();
new AlertDialog.Builder(Tap_Game_Activity.this)
.setTitle("Congratulations!").setMessage("Go to Level 2?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface AlertDialog, int PositiveButton) {
setContentView(R.layout.activity_level02_activity);
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface AlertDialog, int NegativeButton) {
}
}).show();
}
}});
}
(EDIT!): I fixed the AlertDialog by changing the 2 'Else If' statements to just 'If' statements. However, my timer still doesn't work :(, any help?
suppose number is the variable you are showing in the TextView, consider following code,
int number = 10;
if ( number > 0 )
{
yourTextView.setText ( String.valueOf ( number ) );
}
else
{
// do not set text
}
int i=10;
b1.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0)
{
i--;
t1.setText(""+i);
int s1=(Integer.parseInt(t1.getText().toString()));
if(s1<=0)
{
b1.setEnabled(false);
}
}
});
Its all about Logic.
You have to check condition if ( YourCount < 0 ) then you have to disable that button or do not set value in textView as per condition.
This doesn't seem to have anything to do with Android, but more with Java specifically. You just want to make sure that your code doesn't allow you to get below 0.
Your code probably goes something like this:
if button is hit
then subtract 1 from x and setText to x
You want to just throw in something that also checks if number is greater than zero
Like:
If button is hit && x is greater than 0
then subtract 1 from x and setText to x
If that is the case, then I recommend that you step away from the Android platform, and do some Java tutorials and examples.

Categories

Resources