Alright guys, this is a pretty basic question, but it's something I'm not completely sure about. In the example below, I have built a simple calculator with two edittexts (for number entry) and two buttons (add and subtract). At the moment, I am having to declare all the variables/components (e.g. buttons, edittexts etc) in both the btnAdd and btnSub OnClick methods. I mean, this is only a really simple program, but having to re-declare all these variables/components (or whatever you call them?) would obviously be really tedious. You can see the code I've currently got:
Button btnAdd = (Button)findViewById(R.id.btnAdd);
Button btnSub = (Button)findViewById(R.id.btnSub);
btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TextView textViewAns = (TextView)findViewById(R.id.TextViewAns);//here
EditText editText1 = (EditText)findViewById(R.id.editText1);//...
EditText editText2 = (EditText)findViewById(R.id.editText2);//...
int num1 = Integer.parseInt(editText1.getText().toString());//...
int num2 = Integer.parseInt(editText2.getText().toString());//...to here
int total = num1 + num2;
textViewAns.setText(Integer.toString(total));
}
});
btnSub.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
TextView textViewAns = (TextView)findViewById(R.id.TextViewAns);
EditText editText1 = (EditText)findViewById(R.id.editText1);
EditText editText2 = (EditText)findViewById(R.id.editText2);
int num1 = Integer.parseInt(editText1.getText().toString());
int num2 = Integer.parseInt(editText2.getText().toString());
int total = num1 - num2;
textViewAns.setText(Integer.toString(total));
}
});
So you can see all the duplication. What I'm trying to achieve is something like what I'm posting below, though is there anyway that I can do that?
Button btnAdd = (Button)findViewById(R.id.btnAdd);
Button btnSub = (Button)findViewById(R.id.btnSub);
final TextView textViewAns = (TextView)findViewById(R.id.TextViewAns);
EditText editText1 = (EditText)findViewById(R.id.editText1);
EditText editText2 = (EditText)findViewById(R.id.editText2);
final int num1 = Integer.parseInt(editText1.getText().toString());
final int num2 = Integer.parseInt(editText2.getText().toString());
btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int total = num1 + num2;
textViewAns.setText(Integer.toString(total));
}
});
btnSub.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
int total = num1 - num2;
textViewAns.setText(Integer.toString(total));
}
});
At the moment, I get an error in eclipse saying "Cannot refer to a non-final variable inside an inner class defined in a different method", hence I have added the "final" keyword in front of the variables that I was getting the error for. The problem now though is that whenever I try running the program, it simply freezes as soon as it loads. I'm hopin this will be a quick-fix, though who knows. Anyway, thanks in advance for any answers :)
Could it be a simple as wrapping your code in a loop then using a switching statement at the end to choose between the two options you could save allot of code that way
do {Button btnAdd = (Button)findViewById(R.id.btnAdd);
Button btnSub = (Button)findViewById(R.id.btnSub);
TextView textViewAns = (TextView)findViewById(R.id.TextViewAns);
EditText editText1 = (EditText)findViewById(R.id.editText1);
EditText editText2 = (EditText)findViewById(R.id.editText2);
int num1 = Integer.parseInt(editText1.getText().toString());
int num2 = Integer.parseInt(editText2.getText().toString());
if(btnAdd.setOnClickListener(new View.OnClickListener()) {
#Override
public void onClick(View v) {
int total = num1 + num2;
textViewAns.setText(Integer.toString(total));
break
}
});
else if(btnSub.setOnClickListener(new View.OnClickListener()) {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
int total = num1 - num2;
textViewAns.setText(Integer.toString(total));
break;
}
});
else continue;
}while (true)
that's been my experience with writing less code for stuff like that
I think the best solution is to move the code from anonymous class to other class, like:
class Foo{
int things;
void doSth(){}
}
class Bar{
final Foo foo = new Foo();
...
btnSub.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
foo.doSth();
}
});
}
Related
I am the beginner of the Android SDK programming.
What I have is,a calculator that doesn't show decimals when i press calculate button and is there if there is any way to do it?Also crashes if I didn't fill the EditText.
Button cal;
EditText n1,n2,n3;
TextView answer;
int x,y,r,z;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
answer = (TextView)findViewById(R.id.res);
n1 = (EditText)findViewById(R.id.n1);
n2 = (EditText)findViewById(R.id.n2);
n3 = (EditText)findViewById(R.id.n3);
cal = (Button)findViewById(R.id.calc);
cal.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
x=Integer.parseInt(n1.getText().toString());
y=Integer.parseInt(n2.getText().toString());
z=Integer.parseInt(n3.getText().toString());
r=(x+y+z)/3;
answer.setText("" + r);
}
});
You are using Integer.parseInt , to get decimal use Double.parseDouble
set this for edit texts -
n1.setInputType(InputType.TYPE_CLASS_NUMBER);
n2.setInputType(InputType.TYPE_CLASS_NUMBER);
n3.setInputType(InputType.TYPE_CLASS_NUMBER);
for crashing put checks that user can calculate only when edit texts have values
cal.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(!n1.getText().toString().isEmpty()&&!n2.getText().toString().isEmpty()&&!n3.getText().toString().isEmpty())
calculateResult();
else{ //show error message
}
}
});
public void calculateResult()
{
x=Double.parseDouble(n1.getText().toString());
y=Double.parseDouble(n2.getText().toString());
z=Double.parseDouble(n3.getText().toString());
r=(x+y+z)/3;
answer.setText("" + r);
}
and change data types of x,y,z,r to double
I have been trying to use two OnClickListeners but I cant figure out how to do it right.
Could anyone help me fix my code?
btnClear.setOnClickListener(new View.OnClickListener() {
public void onClick(View paramView) {
numBase.getText().clear();
numNikotin.getText().clear();
}
btnAdd.setOnClickListener(new View.OnClickListener() { // I basically want this onClick Listener for the btnClear aswell, but I just cant get both to work. If I take away the btnClear setOnCLickListener Event then btnAdd works just fine.
public void onClick(View v) {
num1 = Double.parseDouble(numBase.getText().toString());
num2 = Double.parseDouble(numNikotin.getText().toString());
sum = num1 / 20 * num2;
String resultN = String.format("%.2f%%", Double.toString(sum));
addResult.setText(resultN);
sum = num1 - sum;
String resultB = String.format("%.2f%%", Double.toString(sum));
addResult2.setText(resultB);
}
}
});
}
}
No you cannot do that. Just split the shared code between two button to another method and call in inside two listener.
private foo() {
num1 = Double.parseDouble(numBase.getText().toString());
num2 = Double.parseDouble(numNikotin.getText().toString());
sum = num1 / 20 * num2;
String resultN = String.format("%.2f%%", Double.toString(sum));
addResult.setText(resultN);
sum = num1 - sum;
String resultB = String.format("%.2f%%", Double.toString(sum));
addResult2.setText(resultB);
}
btnClear.setOnClickListener(new View.OnClickListener() {
public void onClick(View paramView) {
numBase.getText().clear();
numNikotin.getText().clear();
foo();
}
});
btnAdd.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
foo();
}
});
Try this,
btnClear.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
numBase.getText().clear();
numNikotin.getText().clear();
btnAdd.performClick();
}
});
btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
num1 = Double.parseDouble(numBase.getText().toString());
num2 = Double.parseDouble(numNikotin.getText().toString());
sum = num1 / 20 * num2;
String resultN = String.format("%.2f%%", Double.toString(sum));
addResult.setText(resultN);
sum = num1 - sum;
String resultB = String.format("%.2f%%", Double.toString(sum));
addResult2.setText(resultB);
}
});
try this
use performClick()
public boolean performClick ()
Added in API level 1
Call this view's OnClickListener, if it is defined.
Call this view's OnClickListener, if it is defined. Performs all normal actions associated with clicking: reporting accessibility event, playing a sound, etc
btnClear.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
btnAdd.performClick();
numBase.getText().clear();
numNikotin.getText().clear();
}
});
than create a separate click listener for btnAdd
btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
num1 = Double.parseDouble(numBase.getText().toString());
num2 = Double.parseDouble(numNikotin.getText().toString());
sum = num1 / 20 * num2;
String resultN = String.format("%.2f%%", Double.toString(sum));
addResult.setText(resultN);
sum = num1 - sum;
String resultB = String.format("%.2f%%", Double.toString(sum));
addResult2.setText(resultB);
}
});
In an Android Studio app, I have following code:
boolean clicked = true;
Button btnumb1 = (Button) this.findViewById(R.id.numb1);
Button btnumb2 = (Button) this.findViewById(R.id.numb2);
Button btnumb3 = (Button) this.findViewById(R.id.numb3);
Button btnumb4 = (Button) this.findViewById(R.id.numb4);
btnumb1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
clicked = false;
}
});
Button Start = (Button) this.findViewById(R.id.Start);
Start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (clicked == false) {
Random rand = new Random();
int n = rand.nextInt(4) + 1;
TextView textView = (TextView) findViewById(R.id.randOutput);
textView.setText("" + n);
}
else{
Toast.makeText(getApplicationContext(), "You have to choose a number", Toast.LENGTH_LONG).show();
}
}
});
The idea is that when one of the 4 buttons is clicked, the int clicked is set to 1 and so the final button can only be clicked when it is 1.
But the code doesn't work like this; int clicked = 0; can't be accessed in other public void.
If one of the numbers 1,2,3,4 is clicked then final button can be clicked
The fix: Put public static boolean clicked = false;
under your public class YourClassName { line.
Reasoning: You need to learn how to scope your variables properly. You declared boolean clicked inside the onCreate() function, so the variable is gone after onCreate() is done running.
You should have put the clicked variable inside the class scope level, via public boolean clicked or public static boolean clicked so that even after the function returns, the value is saved.
I highly recommend a beginners java course or textbook before continuing on with your project(s).
Java does not have any concept of global variables. There is either an instance variable or a class variable. To define Global Variable you can make use of static Keyword.
static boolean clicked = true;
Button btnumb1 = (Button) this.findViewById(R.id.numb1);
Button btnumb2 = (Button) this.findViewById(R.id.numb2);
Button btnumb3 = (Button) this.findViewById(R.id.numb3);
Button btnumb4 = (Button) this.findViewById(R.id.numb4);
btnumb1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
clicked = false;
}
});
Button Start = (Button) this.findViewById(R.id.Start);
Start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (clicked == false) {
Random rand = new Random();
int n = rand.nextInt(4) + 1;
TextView textView = (TextView) findViewById(R.id.randOutput);
textView.setText("" + n);
}
else{
Toast.makeText(getApplicationContext(), "You have to choose a number", Toast.LENGTH_LONG).show();
}
}
});
Yes the variable int clicked = 0; has to be declared final before it is accessible in the other public void functions.
Try this declared a class say ClassClicked
public class ClassClicked {
int clicked;
public int getClicked() {
return clicked;
}
public void setClicked(int clicked) {
this.clicked = clicked;
}
}
Then changed
int clicked = 0;
to
final ClassClicked clicked = new ClassClicked();
clicked.setClicked(0);
And
clicked = 1;
to
clicked.setClicked(1);
Finally
clicked == 1
to
clicked.getClicked() == 1
This part of my program is supposed to be a user input field for the quantity of an item to purchase. What I'm unable to do is to make it so when the program finally runs on the emulator and I change the textfield number in the EditText, named "etxtQuantity" in my case, the number I use is ignored and it reverts to using the default entry. Also my if statement isn't working like I expect either, it accepts everything.
private void setupAddRecordButton() {
Button button = (Button) findViewById(R.id.btnAddCart);
button.setOnClickListener(new View.OnClickListener() {
final TextView countText = (TextView) findViewById(R.id.txtAddCartCount);
EditText quantity = (EditText) findViewById(R.id.etxtQuantity);
String quantity2 = quantity.getText().toString();
final TextView text2 = (TextView) findViewById(R.id.txtQuantityCheck);
#Override
public void onClick(View v) {
if (! quantity2.equals(".") || quantity2.equals("") || quantity2.equals("-")) {
count++;
long newId = myDb.insertRow("GTX 950", 140, quantity2);
myDb.getRow(newId);
countText.setText("Successfully added " + count + " Times");
}
else
{
text2.setText("Quantity needed!");
}
}
});
}
initailize your edit text in onCreate() callback function of your activity and use String quantity2 = quantity.getText().toString(); in onClick() function of your button
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText quantity = (EditText) findViewById(R.id.etxtQuantity);
Button button = (Button) findViewById(R.id.btnAddCart);
TextView text2 = (TextView) findViewById(R.id.txtQuantityCheck);
TextView countText = (TextView) findViewById(R.id.txtAddCartCount);
button.setOnClickListener(new View.OnClickListener() {
String quantity2 = quantity.getText().toString();
#Override
public void onClick(View v) {
if (! quantity2.equals(".") || quantity2.equals("") ||quantity2.equals("-")) {
count++;
long newId = myDb.insertRow("GTX 950", 140, quantity2);
myDb.getRow(newId);
countText.setText("Successfully added " + count + " Times");
}
else
{
text2.setText("Quantity needed!");
}
}
});
}
please move the this line
String quantity2 = quantity.getText().toString();
inside the onClick()
Try to use
quantity .addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
quantity2=charSequence.toString();
if (! quantity2.equals(".") || quantity2.equals("") || quantity2.equals("-")) {
count++;
long newId = myDb.insertRow("GTX 950", 140, quantity2);
myDb.getRow(newId);
countText.setText("Successfully added " + count + " Times");
}
else
{
text2.setText("Quantity needed!");
}
}
#Override
public void afterTextChanged(Editable editable) {
}
});
1.first a random number is selected.
2.the random number corresponds to a case (trivia question) in a switch statement.
3.the case has an onClick() for every possible answer.
4.when the correct answer (and it's corresponding onClick) is selected
I want the dice to roll again and progress the game to the next question.
5.My debug log says tells me the value of this dice rolled. However, I cannot get the view to change for the corresponding case in the switch.
`public class BeginGame extends Activity {
Random generator = new Random();
private static final String TAG = "MyActivity";
boolean dupe = true;
boolean done = false;
int intitializedQuestionValue = -2;
final int rows = 3;
final int columns = 25;
final int RIGHT = -2000;
final int WRONG = -1000;
int score = 0;
int num;
//define array of three rows and 25 columns
int[][] questionArray = new int [rows][columns];
int[] questionNumber = new int [25];
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
final Button button0 = (Button) findViewById(R.id.button0);
final Button button1 = (Button) findViewById(R.id.button1);
final Button button2 = (Button) findViewById(R.id.button2);
final Button button3 = (Button) findViewById(R.id.button3);
final TextView text = (TextView) findViewById(R.id.TextView01);
//initialize "dice"
for (int i=0; i<25; i++){
questionNumber[i] = -1;
}
for(int i=0; i < columns; i++)
questionArray[0][i] = intitializedQuestionValue;
//set all questions to answered WRONG
for (int i=0; i <columns; i++)
questionArray[1][i] = WRONG;
rollDice();
loop: while (!done)
switch (num) {
case 0:
text.setText("press Virginia0:");
button0.setText("Alabama");
button0.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Toast.makeText(BeginGame.this, "fail", Toast.LENGTH_SHORT).show(); rollDice();
//questionArray[2][0]= score -2;
}
});
button1.setText("Mississippi");
button1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(BeginGame.this, "fail", Toast.LENGTH_SHORT).show(); rollDice();
//questionArray[2][0]= score - 2;
}
});
button2.setText("Philadelphia");
button2.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Toast.makeText(BeginGame.this, "fail", Toast.LENGTH_SHORT).show(); rollDice();
//questionArray[2][0]= score -2;
}
});
button3.setText("Virginia");
button3.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Toast.makeText(BeginGame.this, "success", Toast.LENGTH_SHORT).show(); rollDice();
//questionArray[1][0]=RIGHT;
//questionArray[2][0]= score + 5;
}
});
break loop;
case 1:
text.setText("press alabama1:");
button0.setText("Alabama");
button0.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Toast.makeText(BeginGame.this, "success", Toast.LENGTH_SHORT).show(); rollDice();
}
});
button1.setText("Mississippi");
button1.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
}
});
button2.setText("Philadelphia");
button2.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
}
});
button3.setText("Virginia");
button3.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
}
});
break loop;
`
your program won't work this way. You have to understand more of android.
The onCreate method is called when an activity is created. ie : when it comes to front. It is executed on the UI thread : a thread that interacts with the user and should never be blocked. So, you are basically blocking the UI thread with your loop (does num ever change by the way ?).
What you should do is remove your while loop from the onCreate method. Just use it to initialize your activity, maybe data structures like questions and widgets and their listeners.
And now give more logic to your listeners : when a button is clicked then change your question and refresh the interface so that the new questions display. Do that until there is no more question to ask.
Do never block the UI Thread, make it free so users can use your app.