Nested onClick Listener - java

I have some codes that I need help with. My plan for this code is simple. I have 3 buttons which are the yellowBar, greenBar and redBar. I also have 3 images that is colored yellow, green and red. What I wanted to do is when I start my app, the images I have will randomly pop out and whichever color comes out, I should be able to click the button with the corresponding color. I also have a time, so basically I want to click correctly as much as possible, but my code only runs it one time. my time continues to go down but this code only runs one time. How can I fix this so that it will continue to pop random color images until the time runs out?
while(gameTime > 0){
colorNum = new Random();
colorNumber = colorNum.nextInt(2);
switch (colorNumber){
case 0: colors.setDisplayedChild(0);
break;
case 1: colors.setDisplayedChild(1);
break;
case 2: colors.setDisplayedChild(2);
break;
}
colors.setVisibility(View.VISIBLE);
yellowBar.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if(colorNumber == 0){
points ++;
score.setText(String.valueOf(points));
}
}
});
greenBar.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if(colorNumber == 1){
points ++;
score.setText(String.valueOf(points));
}
}
});
redBar.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if(colorNumber == 2){
points++;
score.setText(String.valueOf(points));
}
}
});
}

The better solution would be to render your graphics onClick event.
When you press a button, you check if the answer was right, then you render the graphics.
using while loop like you do it now is wrong, since your graphics will be rendered all the time (whether button is pressed or not)
Basically (this is not a solution, rather a guideline based on your code):
public void initialize(){
yellowBar.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if(colorNumber == 0){
points ++;
score.setText(String.valueOf(points));
updateColors();
}
}
});
greenBar.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if(colorNumber == 1){
points ++;
score.setText(String.valueOf(points));
updateColors();
}
}
});
redBar.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if(colorNumber == 2){
points++;
score.setText(String.valueOf(points));
updateColors();
}
}
});
}
}
public void updateColors(){
colorNum = new Random();
colorNumber = colorNum.nextInt(2);
switch (colorNumber){
case 0: colors.setDisplayedChild(0);
break;
case 1: colors.setDisplayedChild(1);
break;
case 2: colors.setDisplayedChild(2);
break;
}
colors.setVisibility(View.VISIBLE);
}

Related

Back Button Webview Problem (Delayed work after few clicks)

I made a back button for my webview, but I got a problem.
When I click it more time (for example 5/6) it's back to the main page, but later button work like on delay, so I'm on some page and my app goes back. It's possible to limit the click of the button to only 1 click per page?
Thanks.
Button przycisk_powrot = (Button) findViewById(R.id.przycisk_powrot);
przycisk_powrot.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
You can set the button state to enabled/disabled - and can make a check like this:
backButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (webView.canGoBack()) {
webView.goBack();
// Now check is it still can go back, ?
backButton.setEnabled(webView.canGoBack());
backButton.setAlpha((float)1.0);
}
else {
backButton.setEnabled(false);
// Also make the button little dim, so will show to user that it is currently in disabled state
backButton.setAlpha((float)0.5);
}
}
});
Enjoy..!
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (myWebView.canGoBack()) {
myWebView.goBack();
} else {
finish();
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}

I'm trying to make something like Piano Tiles in android studio and I want the tiles to start coming when play button is pressed with same speed

I'm doing this using handler.postdelayed but whenever i start clicking on tiles postdelayed doesn't work sometimes it comes fast and sometimes slow. Here is the code
private Handler mhandler = new Handler();
private Runnable mcontinue = new Runnable() {
#Override
public void run() {
//row5
RockLocationRow5 = RockLocationRow4;
setRockLocation(RockLocationRow5, 5);
//row4
RockLocationRow4 = RockLocationRow3;
setRockLocation(RockLocationRow4, 4);
//row3
RockLocationRow3 = RockLocationRow2;
setRockLocation(RockLocationRow3, 3);
//row2
RockLocationRow2 = RockLocationRow1;
setRockLocation(RockLocationRow2, 2);
//row1
RockLocationRow1 = r.nextInt(3) + 1;
setRockLocation(RockLocationRow1, 1);
mhandler.postDelayed(this, 3000);
}
};
I'm calling it in initgame function whenever the game starts and if i click on any tile I'm also calling this Runnable their
iv_13.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(RockLocationRow1 == 3){
mcontinue.run();
}
else{
//endGame();
}
}
});
or is their anything else that I can use?? I'm a beginner...
this is how RockLocationRow is initialized
//row3
RockLocationRow3 = 1;
iv_31.setImageResource(tapImage);
//row2
RockLocationRow2 = r.nextInt(3) + 1;
setRockLocation(RockLocationRow2, 2);
//row1
RockLocationRow1 = r.nextInt(3) + 1;
setRockLocation(RockLocationRow1, 1);
and this is setRockLocation
private void setRockLocation(int place, int row){
if(row == 1){
iv_11.setImageResource(emptyImage);
iv_12.setImageResource(emptyImage);
iv_13.setImageResource(emptyImage);
switch (place) {
case 1:
iv_11.setImageResource(tapImage);
break;
case 2:
iv_12.setImageResource(tapImage);
break;
case 3:
iv_13.setImageResource(tapImage);
break;
}
}
same for row 2,3,4 and 5
I think I found the problem.
The problem is when you click a tile. If I have understood good, this code is this:
iv_13.setOnClickListener(new View.OnClickListener() {
//rest of your code...
});
You see, when you click on a tile, you call the method run() of Runnable: mcontinue.run();
By calling this method, you execute AGAIN the postDelayed: mhandler.postDelayed(this, 3000); So, for every click on a tile, you execute the postDelayed. As a result, every 3 seconds FROM THE TIME YOU CLICKED A TILE, new tiles will be showing up. If you click lots of tiles, postDelayed will be executing many times and the tiles we be showing up fast.
A solution that may be correct, is to remove mcontinue.run(); when you click a tile. Like this:
iv_13.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(RockLocationRow1 == 3){
}
else {
//endGame();
}
}
});
Please, feel free to comment any of your thoughts/questions about this issue, and I will help as I can.

Android : how to use single button for multiple task

I have 1 button in activity. i want to use this 1 button for multiple task.
So how can i do ?
If i pressed 1st time this button then it's change 2 button
if i pressed 2nd time then it's update my data
but it's only work 1st time 2nd time it's not work
see my code what i tried
Intent extras = getIntent();
{
if (extras.hasExtra("edit")) {
if (extras.getStringExtra("edit").equals("home")) {
etCompanyName.setEnabled(false);
etWebsite.setEnabled(false);
etEmail.setEnabled(false);
etPhoneHome.setEnabled(false);
etPhonePrimary.setEnabled(false);
etAddressLine1.setEnabled(false);
etAddressLine2.setEnabled(false);
etCity.setEnabled(false);
spStates.setEnabled(false);
etZip.setEnabled(false);
spContries.setEnabled(false);
//1st time use hear
txtSave.setText(getResources().getString(R.string.label_edit));
txtClose.setText(getResources().getString(R.string.label_back));
txtSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
txtSave.setText(getResources().getString(R.string.label_add));
txtClose.setText(getResources().getString(R.string.label_cancel));
etCompanyName.setEnabled(true);
etWebsite.setEnabled(true);
etEmail.setEnabled(true);
etPhoneHome.setEnabled(true);
etPhonePrimary.setEnabled(true);
etAddressLine1.setEnabled(true);
etAddressLine2.setEnabled(true);
etCity.setEnabled(true);
spStates.setEnabled(true);
etZip.setEnabled(true);
spContries.setEnabled(true);
}
});
if (extras != null) {
Company value = (Company) extras.getSerializableExtra("company");
etCompanyName.setText(value.getName());
etWebsite.setText(value.getWebsite());
etEmail.setText(value.getEmail());
etPhoneHome.setText(value.getPhoneHome());
etPhonePrimary.setText(value.getPhonePrimary());
etAddressLine1.setText(value.getAddressLine1());
etAddressLine2.setText(value.getAddressLine2());
etCity.setText(value.getCity());
etZip.setText(value.getZipcode());
}
} else {
//2nd time use hear
txtSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Company company = new Company();
company.setName(etCompanyName.getText().toString().trim());
company.setWebsite(etWebsite.getText().toString().trim());
company.setEmail(etEmail.getText().toString().trim());
company.setPhoneHome(etPhoneHome.getText().toString().trim());
company.setPhonePrimary(etPhonePrimary.getText().toString().trim());
company.setAddressLine1(etAddressLine1.getText().toString().trim());
company.setAddressLine2(etAddressLine2.getText().toString().trim());
company.setZipcode(etZip.getText().toString().trim());
company.setCity(etCity.getText().toString().trim());
company.setState(spStates.getSelectedItem().toString());
company.setCountry(spContries.getSelectedItem().toString());
company.setDate(Util.getInstance(AddCompanyActivity.this).getCurrentDate());
long isUpdated = myDb.updateCompany(company);
if (isUpdated != -1) {
Toast.makeText(getApplicationContext(), "Company Update Successfully: " + isUpdated, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Something wrong", Toast.LENGTH_SHORT).show();
}
finish();
}
});
}
}
}
You can see my above code i can used txtSave button for perform 2 task but it's only change two buttons and i'll change data and click on button then it's can't perform
Try this way, first declare global variable on your activity class file like below :
int count = 0;
After that add your click listener like that:
yourButton.setOnClickListener(v -> {
if (count == 0) { // the first click
count++;
// do your stuff
}else { // the second click
count = 0; // initialize the count to limit the button click just for the first and the second time only
// do your stuff
}
});
You should not create multiple OnClickListener for Button , Create only 1 and use it
example:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(btn.getText().equals("1")){
//perform action for 1
btn.setText("2");
//change button1 to button2
}else if(btn.getText().equals("2")){
//perform action for 2
btn.setText("3");
}
}
});
you could use single onclicklistener with switch case
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
swtich(extras.getStringExtra().toLowerCase(){
case "1":
// do something
break;
case "2":
// do something else
break;
}
});
}

Changing color of a button in an array of buttons and return the other buttons to default

#Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.btnA:
runOnUiThread(new Thread(new Runnable() {
#Override
public void run() {
btnA.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.button_pressed));
btnB.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary));
btnC.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary));
btnD.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary));
}
}));
break;
case R.id.btnB:
runOnUiThread(new Thread(new Runnable() {
#Override
public void run() {
btnB.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.button_pressed));
btnA.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary));
btnC.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary));
btnD.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary));
}
}));
break;
}
So I am currently implementing my code like this it does the job fine, but I have 6 buttons so I have to do this 6 times. I've read about array of buttons and tried to implement it but could not make it work. What isn't clear to me is how do I know which button I clicked and changed it to another color while the other button that is not clicked goes back to their default color.
EDIT:
Sorry if I wasn't clear, this buttons are used for multiple choices. The buttons are already set to default on creation. Not using the switch statement would make the two buttons the same color if I click on another button after the other, they would be the same color. It's more of a display problem..
No need for a switch statement. Just set all buttons to the default color, then set the selected button to the selected color.
Consider moving the test into the setBackgroundColor call and keeping it all in a single new Runnable
#Override
public void onClick(View v) {
runOnUiThread(new Thread(new Runnable() {
#Override
public void run() {
btnA.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), (v.getId() == R.id.btnA ? R.color.button_pressed : R.color.colorPrimary));
btnB.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), (v.getId() == R.id.btnB ? R.color.button_pressed : R.color.colorPrimary));
...
I guess what FredK meant was something like that:
#Override
public void onClick(View v) {
runOnUiThread(new Thread(new Runnable() {
#Override
public void run() {
// Reset all buttons
btnA.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary));
btnB.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary));
btnC.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary));
btnD.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary));
.
.
.
btnZ.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary));
// Set only the clicked button
v.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.button_pressed));
}
}));
}
UPDATE:
You can also iterate over the ViewGroup so you won't need to write down each Button manually.
ViewGroup viewGroup = (ViewGroup) v.getParent();
for(int i=0;i<viewGroup.getChildCount();i++){
Object child = viewGroup.getChildAt(i);
if(child instanceof Button){
((Button) child).setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary));
}
}

Make app more effecient by eliminating extra codes

I currently have the following code which starts from A all the way to Z :
if (someId.matches("A") || someId.matches("a")) {
tvLetCap.setText("A");
tvLetLow.setText("a");
ivLetterIcon.setImageResource(R.drawable.apple);
btnDisplayWord.setText("A is for APPLE");
btnPlay.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
stopPlaying();
mpSound = MediaPlayer.create(MyClass.this, R.raw.a);
mpSound.setLooping(false);
mpSound.start();
btnPlay.setVisibility(View.GONE);
btnStop.setVisibility(View.VISIBLE);
btnStop.setOnClickListener(stopSound);
mpSound.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
btnPlay.setVisibility(View.VISIBLE);
btnStop.setVisibility(View.GONE);
}
});
}
});
}
if (someId.matches("B") || someId.matches("b")) {
tvLetCap.setText("B");
tvLetLow.setText("b");
ivLetterIcon.setImageResource(R.drawable.ball);
btnDisplayWord.setText("B is for BALL");
btnPlay.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
stopPlaying();
mpSound = MediaPlayer.create(MyClass.this, R.raw.b);
mpSound.setLooping(false);
mpSound.start();
btnPlay.setVisibility(View.GONE);
btnStop.setVisibility(View.VISIBLE);
btnStop.setOnClickListener(stopSound);
mpSound.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
btnPlay.setVisibility(View.VISIBLE);
btnStop.setVisibility(View.GONE);
}
});
}
});
}
Would this work as oppose to the above:
switch(someId) {
case A:
setLetter("A");
addIcon("apple");
break;
case B:
setLetter("B");
addIcon("ball");
break;
default:
break;
}
public void setLetter(String strLetter) {
tvLetCap.setText(strLetter);
tvLetLow.setText(strLetter.toLowerCase());
}
public void addIcon(String iconLetter) {
ivLetterIcon.setImageResource(R.drawable. + iconLetter);
btnDisplayWord.setText(iconLetter.charAt(0).toUpperCase() + " is for " + iconLetter.toUpperCase());
}
I am guessing the only issue might be with this line and how would I fix it?:
ivLetterIcon.setImageResource(R.drawable. + iconLetter);
Also will it be possible to take the entire btnPlay function to a different function and just pass the letter like I did with the other functions so it's not repeated over?
I don't know what R and R.drawable are; and what are R.drawable.apple, R.drawable.ball, etc.? Assuming those all have the same type, you might want to make R.drawable an array where the index is 0 for 'A', 1 for 'B', etc., and initialize it so that R.drawable[0] = (whatever the "apple" is supposed to be), R.drawable[1] = (same for "ball"); then use something like
R.drawable[someId.charAt(0).toUpperCase() - 'A']
and similarly for R.raw. Then you wouldn't need a switch at all.
EDIT by kcoppock:
For example:
int[] icons = {
R.drawable.a,
R.drawable.b,
//etc.
};
int[] sounds = {
R.raw.a,
R.raw.b,
//etc.
}
and use icons[index] and sounds[index] to map your values.
Simplest solution: add another parameter to addIcon:
public void addIcon(String iconLetter, int iconResource){
ivLetterIcon.setImageResource(iconResource);
btnDisplayWord.setText(iconLetter.charAt(0).toUpperCase() + " is for " + iconLetter.toUpperCase());
}
Then call it with
setIcon("apple", R.drawable.apple);
As far as reusing the on click listener, it's certainly possible. You could have a single onClick listener that's listening to all the views. When a view is clicked, it's passed in as the argument to the onClick(View view) method. You can use that to find the start/stop button for that view and do whatever to them. Also, there's a useful (and often abused) method pair: setTag(Object object), and getTag(). You might want to look into using those to store the resource ID for the raw audio file you want to play when a button is clicked.

Categories