I have a problem with my application. I just want to set a limit of 2 checked checkboxes but I don't know how.
I have 4 checkboxes and a button. When the button is pressed, if there are only 2 checked checkboxes do something, if are 3 or more do something else. Here is my code:
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(chk1.isChecked()){
counter++;}
else{
counter--;
}
if(chk2.isChecked())
{ counter++;}
else{
counter--;
}
if(chk3.isChecked())
{ counter++; }
else{
counter--;
}
if(chk4.isChecked())
{ counter++; }
else{
counter--;
}
if ( (chk1.isChecked() || chk2.isChecked() || chk3.isChecked() || chk4.isChecked()) && counter >2 ) {
Toast.makeText(StartingPoint.this, "boo", Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(StartingPoint.this, "no boo", Toast.LENGTH_LONG).show();
}
}
});
If I understand you correctly, you nearly got it already.
Declare your counter
Forget about the decrements, only use increments
Use a 1st if/then statement to check how many checkboxes have been checked (the value of counter)
Use a nested if/then statement to apply logic based on the specific checkboxes
Edit - here's a simplified example.
/*
* This will check the number of CheckBoxes checked when your
* button is pressed, and perform some logic consequently.
*
* ALTERNATIVE (not shown here):
* If you wish to disable the button based on how many CheckBoxes
* are checked, you should add an OnClickListener for each CheckBox
* (I'm over-simplifying here on purpose).
* Each CheckBox click would increase the counter if checked,
* decrease it if not.
* Each listener would decide whether or not to enable the button
* after computing the counter's value.
*/
Button myButton = null; // TODO initialize properly
// TODO initialize all CheckBoxes properly
final CheckBox cb0 = null;
final CheckBox cb1 = null;
final CheckBox cb2 = null;
// ... and so forth ...
// Initializing the anonymous listener class attached to the Button
myButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// initializing the counter each click
int counter = 0;
// incrementing the counter for each CheckBox checked
if (cb0.isChecked()) counter++;
if (cb1.isChecked()) counter++;
if (cb2.isChecked()) counter++;
// ... and so forth ...
// Verifying number of CheckBoxes checked...
// ...up to 2 CheckBoxes checked
if (counter < 3) {
// TODO logic depending on which CheckBox(es)
}
// ...more than 2 CheckBoxes checked
else {
// TODO logic depending on which CheckBox(es) or anything else
}
}
});
Related
I am writing a class that has certain variables that don't need to be set except in certain fringe cases. As such, I am working on writing a requestVariable() method that asks for user input to set that variable when it is needed. However, I am struggling to figure out how to wait for that input before moving on. Let me show you what I have.
SkillApplication AR_D_Atk_Def_1_app = (Unit) -> {
if (Unit.getAttackStatus() != com.codecademy.myapplication.Unit.AttackStatus.DEFENDER) {
return;
}
else {
// Make sure structuresAR is set
Unit.setStructuresAR(requestVariable( /* some parameters */ );
int X;
if (Unit.getStructuresAR() >= 5) {
X = 4;
}
else if (Unit.getStructuresAR() == 4) {
X = 3;
}
else if (Unit.getStructuresAR() == 3) {
X = 2;
}
else {
X = 1;
}
Unit.addCombatAtk(X);
Unit.addCombatDef(X);
}
};
This is a lambda function for a certain skill's application. If this skill needs to be applied, it will run this lambda function. This is one of the fringe cases where the member "structuresAR" of Unit needs to be used. It's very rarely used, and rather than having the user set it every time, I have it set in this lambda function.
VariableRequest<Integer> requestInteger = (VariableRequest<Integer>) (questionMessage, choices, layout) -> {
final Integer[] retVal = new Integer[1];
TextView questionView = new TextView(layout.getContext());
questionView.setText(questionMessage);
EditText textEntry = new EditText(layout.getContext());
textEntry.setInputType(InputType.TYPE_CLASS_NUMBER);
Button submitButton = new Button(layout.getContext());
submitButton.setText("Submit");
layout.addView(questionView);
layout.addView(textEntry);
layout.addView(submitButton);
submitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
retVal[0] = Integer.parseInt(String.valueOf(textEntry.getText()));
}
});
};
Here's what I have written so far for that function. It sets a question, options, and submit button to a layout that updates a return value with what is in the entry box when a button is clicked.
This problem is, this just keeps going. The rest of whatever I've written will be run while the onClickListener is still there, and I don't know how to wait until that's been clicked. I'm coming from C++ knowledge where just writing cin >> variable would pause and wait for you to enter. I'm trying to replicate that with a button.
There's also other problems I can spot with this such as getting the layout from inside a static method, but I struggle to come up with another method as I'm very new to Android development.
I have a button that is a type Button that is gonna be clicked. When this is clicked, It is changing color to green.
When I click the button it changes color to green, but when I click it again, it should go back to the standard color.
I have 2 drawable files with names checked_list and not_checked_list.
These two are working good.
But when I click the button, the click has happened. And I can't click it again for some reason.
I have a Button field with a public void sendMessage method that is hooked to the buttons onClick. Is it better to just set an onClickEvent for the button in the code instead.
Here is the code I have so far.
int checked = 0;
Button gotIt;
gotIt = (Button)findViewById(R.id.got_it);
switch(checked) {
case 0:
gotIt.setBackgroundResource(R.drawable.checked_list);
checked = 1;
break;
case 1:
gotIt.setBackgroundResource(R.drawable.not_checked_list);
checked = 0;
break;
}
So here I want it to change between these two colors when I click it.
Any suggestions?
If all of the code you posted is inside your onClick method, then checked int is always 0 and will never be 1 because it is set in the first line of the method. Move your checked int outside of this method and it should work.
Setting click listener dynamically will have same result as setting in XML layout.
int checked = 0;
Button gotIt;
void sendMessage(View v) {
gotIt = (Button)findViewById(R.id.got_it);
switch(checked) {
case 0:
gotIt.setBackgroundResource(R.drawable.checked_list);
checked = 1;
break;
case 1:
gotIt.setBackgroundResource(R.drawable.not_checked_list);
checked = 0;
break;
}
}
You have to keep track of the last value for checked. Right now you are resetting it every time to 0 because it is a local field in your method call. Make checked as a class field and it will work as expected.
You can try this method
//global variables
boolean isChecked = true;
Button gotIt;
//put this in onCreate()
gotIt = (Button)findViewById(R.id.got_it);
gotIt.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if(isChecked == true){
gotIt.setBackgroundResource(R.drawable.checked_list);
isChecked = false;
}else{
gotIt.setBackgroundResource(R.drawable.not_checked_list);
isChecked = true;
}
}
});
when I run my app it will continuously be stuck in a while loop. It should leave the while loop when a button is pressed, however even after pressing a button it continues to loop.
View.OnClickListener listener11 = new View.OnClickListener() {
#Override
public void onClick(View view) {
temp1 = button[0];
temp3 = button[0].getBackground();
state++;
}
};
while(state == 0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
button[0].setOnClickListener(listener11);
}
variable:
state is an int temp1 is a button temp3 is a Drawable
the delay is there because I actually have 20 buttons and I have the setOnClickListeners for all the buttons inside that while loop so I think it causes it to crash without the delay. Another question would be is it possible to have the setOnClickListeners outside the while loop but still be able to check for button clicks inside the loop?
The problem is you are pressing the button while the thread is in a sleeping state causing the event to not be triggered and therefor the state to never change.
You should remove the while loop and just set all the listeners in a for loop:
for(int i = 0; i< button.length; i++) {
button[0].setTag(i);
button[0].setOnClickListener(listener11);
}
And then change your listener to be something like:
private boolean firstClick = true;
View.OnClickListener listener11 = new View.OnClickListener() {
#Override
public void onClick(View view) {
if(firstClick) {
firstClick = false;
temp1 = button[(int)view.getTag()];
} else {
temp2 = button[(int)view.getTag()];
}
}
};
I'm not sure exactly what the code is supposed to be doing because I have no idea of the context, but I think think you could remove the while loop altogether:
// initialize the listener
View.OnClickListener listener11 = new View.OnClickListener() {
#Override
public void onClick(View view) {
// add code that runs when button is clicked here
}
};
// now that we have the listener all set up we add it to the button, at which point it just keeps listening for you, no need to put the thread to sleep
button[0].setOnClickListener(listener11);
UPDATE:
So because you want to see if the second value matches the first value you could use a helper method:
private String firstValue = "";
public boolean isMatch(String mostRecentValue) {
boolean match = false;
if (firstValue.isEmpty()) {
firstValue = mostRecentValue;
} else {
match = firstValue.equals(mostRecentValue);
firstValue = "";
}
return match;
}
This method takes a value and if it is the first click the value is saved, if it is the second click it compares it with the first click and then resets the method. A boolean is returned false for no match, and true for a match. Call this method from within the onClick() method and pass in the buttons value. I've used String as an example value but you could use any object type.
I think you might be misunderstanding what setOnClickListener is doing. It's not handling the click, it is setting up the click handler. The line button[0].setOnClickListener(listener11); would be part of your activity initialisation and then not called again.
The reason you get stuck is because the main thread is busy in the while loop and isn't given an opportunity to process click events. Click events are handled on the main thread but only when it's not already busy doing something. In this case, it's forever busy in the while loop. For example, if the main thread was processing a method that would take 10 seconds to complete and you tap on a button 3 seconds into it, the button press wouldn't be handled for another 7 seconds. At which point, the previously set listener11 would be executed.
What you seem to be trying to achieve is already handled by the Looper. You need to be thinking in terms of event handling. So in other words, all your logic needs to go in listener11 or something similar.
I have been trying to built a Math Flash Card App, the user inputs two numbers and then chooses one button depending if it wants the numbers add, subtract or multiply.
Image:http://i.stack.imgur.com/83FdN.png
The problem seem to be the OnClickListener. I have created other projects with one button and they work perfectly but with two buttons i don't know how to do it.
I have tried:
Creating OnclickSListener for each button, the code doesn't show any error but when i try to run the app it force closes.
I have tried the methods on this post: Android - multiple OnClickListener? and this one http://blog.idleworx.com/2011/06/build-simple-android-app-2-button.html and stil the app shows no errors but can't run.
I have taken the button code out and run it and then it works. I don't know what else to do.
This is the last code that I have tried just trying with one button, app still force closed.
public class MainActivity extends ActionBarActivity implements OnClickListener{
int num1, num2, total;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText txtInt1 = (EditText)findViewById(R.id.txtInt1);
final EditText txtInt2 = (EditText)findViewById(R.id.txtInt2);
final TextView result = (TextView) findViewById(R.id.txtResult);
num1 = Integer.parseInt(txtInt1.getText().toString());
num2 = Integer.parseInt(txtInt2.getText().toString());
final Button btnAddition = (Button) findViewById(R.id.btnAddition);
Button btnSubstraction = (Button) findViewById(R.id.btnSubstraction);
Button btnMultiplication = (Button) findViewById(R.id.btnMultiplication);
/*
btnSubstraction.setOnClickListener(this);
btnAddition.setOnClickListener(this);
btnMultiplication.setOnClickListener(this); */
btnAddition.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (v == btnAddition){
if (num1 <=0 || num1 >20 || num2 <=0 || num2 >20 ){
Toast.makeText(MainActivity.this, "The numbers shoudl be between 1 and 20",
Toast.LENGTH_SHORT).show();
}
else {
total = num1+num2;
result.setText(num1+" + "+num2+" = "+total);
}
}
}
});
Thank you!
Since you are implementing OnClickListener, it is required that you have the Override method onClick(View arg). By using switches you can setup individual cases for each button you want clickable actions for. Here are the steps
1) After instantiation of button widgets: Set onClickListener to each button widget
btnSubstraction.setOnClickListener(this);
btnAddition.setOnClickListener(this);
btnMultiplication.setOnClickListener(this);
2) Create your cases in onClick() method: Make sure that this is outside of your onCreate()
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnAddition:
// do some action for addition
break;
case R.id.btnSubstraction:
// do some action for substraction
break;
case R.id.btnMultiplication:
// do some action for multiplication
break;
default:
break;
}
}
3) Be sure that you implement OnClickListener
For a great tutorial on buttons you should check out http://ljtatum.blog.com/buttons/. You can download free example code. But what I have posted above will work for you. Cheers!
Its better to move them to a single OnClick block of code .
Check whether the v.getId() is the button id .
Try by changing the code to
btnSubstraction.setOnClickListener(this);
btnAddition.setOnClickListener(this);
btnMultiplication.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.btnAddition){
if (num1 <=0 || num1 >20 || num2 <=0 || num2 >20 ){
Toast.makeText(MainActivity.this, "The numbers shoudl be between 1 and 20",
Toast.LENGTH_SHORT).show();
}
else {
total = num1+num2;
result.setText(num1+" + "+num2+" = "+total);
}
}
}
});
Have you tried setting Logs? u can do this by:
Log.e("TAG","MSG");
Then you can watch the LogCat and hunt the error down! ;)
I would implement the other Buttons exactly like you did your first one with the anonymous inner class.
btnSubstraction.setOnClickListener(new OnCLickListener() {
#Override
public void onClick(View v){
Your Code goes here or u trigger another Method for readability for example:
Substraction();
...
You should keep an Eye on the ID of the Buttons:
R.findViewById...
But you don't even need this if you trigger the onClick on the buttonobject. ;)
Yeah I guess that's it, try to leave the:
if(v==btnAddition)
The System already knows this by triggering the onClick over the buttonObject.
SO your code should go like this:
btnAddition.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (num1 <=0 || num1 >20 || num2 <=0 || num2 >20 ){
Toast.makeText(MainActivity.this, "The numbers shoudl be between 1 and 20",
Toast.LENGTH_SHORT).show();
}
else {
total = num1+num2;
result.setText(num1+" + "+num2+" = "+total);
}
}
}
});
btnSubstraction.setOnClickListener(new OnCLickListener() {
#Override
public void onClick(View v){
//Substractioncode here
}
});
What DaveS. is saying is that you are probably getting an exception in onCreate() on these two lines
num1 = Integer.parseInt(txtInt1.getText().toString());
num2 = Integer.parseInt(txtInt2.getText().toString());
these should be moved to the onClick() because in onCreate() they have not yet been given values so you will get a NumberFormatException. You also should do some error-checking such as
try {
num1 = Integer.parseInt(txtInt1.getText().toString());
num2 = Integer.parseInt(txtInt2.getText().toString());
} catch (NumberFormatException e) {
// log the error and possibly print a message to the user
}
You should always post your stacktrace when your app crashes so we can find the answer easily. The issue with the code you posted is not due to the way you are setting the OnClickListener which is what you indicated.
This SO answer shows how to set the OnClickListener for Buttons. All will work fine so you decide which works best for you.
You are trying to getText and convert that string in int in onCreate(). In onCreate() you will get "" which is a blank string while you trying to convert it you will get a NumberFormatException. Solution is move these two inside onClick method of button.
num1 = Integer.parseInt(txtInt1.getText().toString());
num2 = Integer.parseInt(txtInt2.getText().toString());
cameraOn();
while (counter == 1){
if(counter == 0){
cameraOn();
counter += 1;
}else{
cameraOff();
counter -= 1;
}
}
The methods are:
private void cameraOff() {
// TODO Auto-generated method stub
parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(parameters);
camera.release();
camera = null;
}
private void cameraOn() {
// TODO Auto-generated method stub
camera = Camera.open();
parameters = camera.getParameters();
parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameters);
}
and I have a button who have to break the loop and finish the activity:
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (camera == null){
finish();
}else{
parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(parameters);
camera.release();
camera = null;
finish();
}
I'm a beginner and I don't understand how does the loop work, I tought with the counter I could do it, but it didn't work.
What I'm trying is to make the camera flash blink every second in a loop until I will press the button. please help me. Thanks
if (counter == 0) will never be true as your loop will exit in that case.
As others have said, entering a loop only when counter == 0 means it will never enter the inner loop requiring counter == 1, and never enter cameraOn().
Try this:
Clear out your onClick method and replace it with:
#Override public void onClick(View v) {
cameraOff();
/* or 'toggle();' if you prefer, see below */
}
(Since it appears to do exactly the same things.)
Comment out / delete that whole nested loop, and be sure to call cameraOn() or toggle() somewhere to get things started.
For setting up the toggle, you can add a static Boolean isFlashActive; (or otherwise detect the flash state, I haven't used that api yet)
..and add a function:
private toggle(){
if ( isFlashActive ) {
cameraOff();
} else {
cameraOn();
}
/* delay? */
}
For the toggle delay, you have a couple options:
First, you can call toggle() from another thread via a Runnable or one of the android options like AsyncTask while adding a wait() into the toggle function to provide the delay;
Second is my personal favorite, which is to setup an intent receiver then use setRepeating() with a PendingIntent.
The following part of your code will never be executed because you only enter the while block if counter == 1.
if(counter == 0){
cameraOn();
counter += 1;
So if you ever entered your while block while (counter == 1), you will always end up calling cameraOff() method. In other words your if statement will never be true and the else statement will be the one to be always executed.