I am new to Android application development and am trying to find a way to proceed through a series of screens that take in user input. I'm making a small math game where the user would answer basic two integer addition problems. So far the main menu is created. It has a New Game button which launches my GameActivity and it runs just fine for one math problem. However, after the user inputs their answer to the simple math problem, I would like to be able to continue on to another math problem once the user had answered the current problem and the method would return a correct/incorrect value. Initially I thought of doing something like a basic FOR loop from within the GameActivity :
for(int i = 0; i < 10; i++){ gameMethod(); }
gameMethod() is a JAVA method that simply generates 2 random numbers, adds them to get the correct answer and then prompts the user using an EditText field to type in their guess. It displays the random numbers and answer using TextView boxes created in an XML layout file.
Each call to the gameMethod would, at least I think, just re-input the randomized numbers into the TextView fields displayed on the screen each iteration. I really don't care what the previous numbers were so I figured I would just overwrite them. I wan't able to get the code to do that though. I put in a Log.d() statement or two and found that the FOR loop was in fact running through correctly 10 times, but it was not waiting for user input before firing off its next gameMethod().
In doing some looking around, I found the startActivityForResult() and wondered if this was a more appropriate way of approaching this. So in this way, I foresee having three Activities, the Main menu which calls the GameActivity which would then iterate through, say 10 times, each iteration calling yet another activity GameScreenActivity which would actually put the numbers on the screen, read in user input and then return 1 for a correct answer and 0 for an incorrect answer. So far in reading up on StarActivityForResult() I'm getting somewhat confused by the process and wondered if this was even a plausible path to be exploring.
Again, I'm very new at this Android programming and appreciate any and all help that I can get.
Thank you.
Sorry for not including the gameMethod() initially, I've added it below.
// Create and initialize arrays of integers
int[] a = {0,1,2,3,4,5,6,7,8,9,10};
int[] b = {0,1,2,3,4,5,6,7,8,9,10};
// Creates random number generator
Random randy = new Random();
// Generates two random values to add
int r1 = randy.nextInt(10);
int r2 = randy.nextInt(10);
// Calculates correct answer
int an = a[r1] + a[r2];
// Displays 1st number
TextView number1 = (TextView) findViewById(R.id.firstNumber);
number1.setText(Integer.toString(a[r1]));
// Displays 2nd number
TextView number2 = (TextView) findViewById(R.id.secondNumber);
number2.setText(Integer.toString(b[r2]));
// Displays correct answer
TextView answer1 = (TextView) findViewById(R.id.answerNumber);
//hide answer until user puts in theirs
answer1.setVisibility(View.INVISIBLE);
answer1.setText(Integer.toString(an));
//hide the answer place holder value
TextView uAnswerDisplay = (TextView) findViewById(R.id.userAnswerNumber);
uAnswerDisplay.setVisibility(View.INVISIBLE);
//Get the EditText field that the user will input their answer to
EditText inputText = (EditText) findViewById(R.id.userInput);
//set up a listener to run once the ENTER key is hit after their answer has been entered
inputText.setOnKeyListener(new EditText.OnKeyListener(){
public boolean onKey(View v, int keyCode, KeyEvent event){
//only go on the ENTER key when pressed DOWN
if((event.getAction() == KeyEvent.ACTION_DOWN) &&
(keyCode == KeyEvent.KEYCODE_ENTER)){
EditText innerInputText = (EditText) findViewById(R.id.userInput); //get the EditText box reference
TextView innerUAnswerDisplay = (TextView) findViewById(R.id.userAnswerNumber); //get the TextView box that the answer will go in
String inputString = innerInputText.getText().toString(); //capture the user's input
int uAnswer = Integer.parseInt(inputString); //parse user answer to an integer
int cAnswer = Integer.parseInt((((TextView) findViewById(R.id.answerNumber)).getText()).toString());
innerUAnswerDisplay.setText(Integer.toString(uAnswer)); //display the string after converting from integer
//change colors of text based on correctness
if (uAnswer == cAnswer){ innerUAnswerDisplay.setTextColor(Color.GREEN); } //green for correct
else { innerUAnswerDisplay.setTextColor(Color.RED); } //red for incorrect
innerUAnswerDisplay.setVisibility(View.VISIBLE); //make the user input answer visible
TextView innerAnswer1 = (TextView) findViewById(R.id.answerNumber);
innerAnswer1.setVisibility(View.VISIBLE); //hide answer until user puts in theirs
} //end of if
return false; //return false
} //end of onKey
}); //end of setOnKeyListener
Sorry for all the edits, I couldn't get the edits to include the code and post correctly so I broke it up into chunks and added a little at a time.
From what you say, I'd consider two ways of letting the user answer questions:
have an onclick listener on the input EditText that triggers a new loop;
have a dialog activity that gets started in the beginning of the loop, which prompts the user for a new answer, your game activity would receive the answer via its onActivityResult.
Related
In my app, I want a counter from 0 to 8 to decide the number of players in a game.
Below there are 8 possible fields to write a name inside, which are all set to invisible. If the players-counter is set to 3 players, there should be the first 3 fields visible. Depending on the actual number of the counter, the visibility of the fields changes (1player = first field, 5 players = first 5 fields).
When the +1 (player) button is clicked, a certain method is activated. I tried to run a for-loop everytime the button is clicked. In this for-loop from 0 to "whatever amount" (max. 8 players) the actual fields should be found with "findById" and set to visible.
I tried it with a string resource (.xml) and I can get the text of the resource but with my thought process, I have to update the string resource to every number of the field (if 3 players: "field_" + "1", "field_" + "2", "field_" + "3").
How can I get and (most importantly) set/update a string resource for this specific purpose?
(Switch is too inefficient and I can't use a string with the findViewBy Id()-method by updating the String (not string resource) like mentioned before.
Please help, and accept the fact that I'm new to Android Studio for one week!)
You can use "getIdentifier" which takes a String parameter. So you can set the type as "id" in the second parameter of this method. This method returns the id of the view you want, but beware, it will throw a "FATAL EXCEPTION" if the id of the View doesn't exist. With this id, you can use findViewById to fetch the TextView and change its visibility. The "getIdentifier" method can be called from the "getResources()" method.
Below you can see what it would be like to make visible a TextView that has the id "textView1":
int id = getResources().getIdentifier("textView1", "id", getPackageName());
TextView textView = findViewById(id);
textView.setVisibility(View.VISIBLE);
Below you can see how you would make 8 TextView with id 1 to 8 visible:
TextView textView;
for (int i = 1; i <= 8; i++) {
int id = getResources().getIdentifier("textView" + i, "id", getPackageName());
textView = findViewById(id);
textView.setVisibility(View.VISIBLE);
}
So, just put the limit at i <= x , with x being the limit of players who will play:
TextView textView;
for (int i = 1; i <= totalPlayers; i++) {
int id = getResources().getIdentifier("textView" + i, "id", getPackageName());
textView = findViewById(id);
textView.setVisibility(View.VISIBLE);
}
Do you just want to make some EditTexts visible and others not? Personally I'd keep it simple, do the lookups once (in onCreate or wherever) and store the references in a list. Then when you need to display n fields, you can just iterate over the list and set the first n to VISIBLE and the rest to INVISIBLE.
I feel like it's fine to just list all the EditText IDs (R.id.field_1 etc) and generate your list of actual Views from that, but if that repetition bothers you, there's a few things you could do. Like:
set a tag attribute on each field in the XML, and use findViewWithTag to look them up, generating the lookup strings programmatically, like "field_" + i
do a similar thing with the resource ID, like in #Moises's answer
lookup their containing layout, use getChildCount and [getChildAt] to iterate over the views in that layout, and use isInstance to collect all the EditTexts in order3
create and add the EditTexts in code - you probably don't want to do this, but you could!
I'm not really sure what you mean about the string resource or what you're trying to do - I'd honestly just make a list of R.id.field_1 etc, iterate over that to do findViewById on each and store those in a new list, and you're done. Also my Java's a bit rusty so sorry no example code!
I am making a budget app and each time the user enters a new expense, I just append a TextView. I need to add each expense together, but I'm not sure how to do this on each click.
First, I thought to simply add all the numbers from the TextView, but I couldn't find a way to do this since they're all in just one TextView (as opposed to creating a new TextView on each click). So, I decided to simply parse the expense each time the user types it then add them together. But how can I add them after parsing in this way?
Thanks so much for the help
addExpenseButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//TODO: Transfer this info to line in scroll view showing expenses
if (TextUtils.isEmpty(enterExpensesEditText.getText()) || TextUtils.isEmpty(enterExpensesNamesEditText.getText())) {
Toast.makeText(Expenses.this, "Expense Amount or Name Empty", Toast.LENGTH_SHORT).show();
} else {
String income = enterExpensesEditText.getText().toString() + "\n";
String incomeName = enterExpensesNamesEditText.getText().toString() + "\n";
expenseAmountTextView.append(income);
expenseNameTextView.append(incomeName);
//parse income to double in order to add it and later feed to EverydayBudget
totalIncome = Double.parseDouble(income);
}
enterExpensesNamesEditText.setText("");
enterExpensesEditText.setText("");
}
});
You parse only the current expense : totalIncome = Double.parseDouble(income);
maybe replace by totalIncome += Double.parseDouble(income);
Sorry guys but i don't understand your question where is the problem ? you append your textview when you have a new expense no ?
And why not use a ListView rather TextView ?
I have searched for an answer to this question with my time in my Computer Science lab. We are using Android Studio for this app.
What I want to do is to use randomization to make a set of screens be randomized when you click a button. My duo is working on a dice rolling app, and we had the idea to make six different screens for each of the sides of the die. Basically, when we click the button to "roll the dice", it think for a second, then brings you to a random page with a picture of the number on the die which you got.
This is incredibly weird, and I have searched for at least 3 hours straight for a solution to this problem but to no avail. If anybody needs more information on the problem (because I do not know how to properly phrase it), then just ask me.
Just use Random.nextInt() to get a random number up to 6, and use that to choose one image of the 6 for each die side. You do not need to create 6 different screens, you just need 6 different images where the number indicates which image to use. For example:
// A list of drawables you've defined in /res/drawable folder for each die side
final int[] images = new int[6] {
R.drawable.die_side_1,
R.drawable.die_side_2,
R.drawable.die_side_3,
R.drawable.die_side_4,
R.drawable.die_side_5,
R.drawable.die_side_6
};
int random = Random.nextInt(6); // Get random value, 0-5
int dieSideDrawable = images[random]; // Pick image to show based on random value
mDieImageView.setImageResource(dieSideDrawable); // Show image on an image view
Hope that helps!
The easiest way to do exactly what you want would be to put the Activities in an Array, and select by using the Random class' nextInt method to choose the appropriate activity from the Array.
That being said, most likely you want to create a single activity with two images, and instead of selecting an activity or Fragment to show, you'd select the images you'd load into the Activity.
I would recommend using Fragments to achieve this.
create a list of fragments
ArrayList<Fragment> fragmentList = new ArrayList<>();
Now use the java Random class to generate the random number.
Random rand = new Random();
int n = rand.nextInt(fragmentList.size());
then just show that fragment.
getSupportFragmentManager()
.beginTransaction()
.replace(containerViewId, fragmentList.get(n))
.addToBackStack(null)
.commit();
Using multiple activities seems unnecessary here (and will significantly slow down your app). If you want to show a different image based on the result of a random number that's been generated, then just .setImageResource() for your Image View based on the result of that random number.
In the example below I separated the random number generation (the generateRandomInt() method which stores a random integer in the thisRoll variable) and only called it when the changeImageView() method runs onClick.
public void changeImageView(View view){
generateRandomInt();
if (thisRoll == 1) {
mainImage.setImageResource(R.drawable.s1);
} else if (thisRoll == 2) {
mainImage.setImageResource(R.drawable.s2);
} else if (thisRoll == 3) {
mainImage.setImageResource(R.drawable.s3);
} else if (thisRoll == 4) {
mainImage.setImageResource(R.drawable.s4);
} else if (thisRoll == 5) {
mainImage.setImageResource(R.drawable.s5);
} else {
mainImage.setImageResource(R.drawable.s6);
}
Toast.makeText(DiceRollActivity.this, thisRoll + " ...But The House Always Wins!", Toast.LENGTH_SHORT).show();
}
I have a simple screen with two EditText Boxes and 1 button. I want users to be able to enter various integers into the boxes and the program will perform different operations based on the specific number entered into the box. I'm trying to have them only enter one number at a time but the code wont seem to execute unless both boxes have something in them. And I'm having the if statements check for nulls on the respective boxes before executing to determine which piece of code to execute.
public void button(View view) {
double x, y;
EditText freq1 = findViewById(R.id.freq1);
EditText freq2 = findViewById(R.id.freq2);
TextView str1 = findViewById(R.id.freqanswer);
TextView str2 = findViewById(R.id.injVolt);
TextView error1 = findViewById(R.id.error1);
String strf1, strf2;
strf1 = freq1.getText().toString();
strf2 = freq2.getText().toString();
try {
f1 = Double.parseDouble(strf1);
f2 = Double.parseDouble(strf2);
if ((f1 >= 225) & (f1 <= 312) & (strf1.isEmpty())) {
x = f1 + 20.6;
y = x / 4;
str1.setText(String.format("%.3f", y));
}
}
catch (Exception e){
error1.setText("splat");
}
finally {
InputMethodManager input = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
input.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
I included only 1 formula for the sake of brevity, but I'm going to be putting about 6 if statements, checking for number ranges and nulls on this button and I just need it to run with one box being empty. I know the formula works by having play with various outputs, it just won't run with the strf1.isEmpty(). Something has to be in that second box for the formula to execute.
Would appreciate any help
I think you should check before assigning:
if(strf1.isEmpty()){strf1="0";} //if assuming zero does not change the formula's output
if(strf2.isEmpty()){strf2="0";}
f1 = Double.parseDouble(strf1);
f2 = Double.parseDouble(strf2);
this way you are assured of a default value.
I'm making a simple quiz program. I need to display my Correct and Wrong it depends on the answer of the user. I think it is in the IF else. That's why I can't get it through. When I run it. I choose the correct answer. It is still displaying "Wrong!" and it counts it as correct. and Then change to different number. It is still displaying "Wrong!". I'm using checkbox as the multiple choice of the quiz.
Here's my code:
if(C1.getState()) // if the user chooses the checkbox c1
{
outputlabel.setText("Correct\n");
CorrectAnswer++; // it will count one point per correct answer.
}else
outputlabel.setText("Wrong!\n");
if(C13.getState()) // if the user chooses the checkbox C13
{
outputlabel.setText("Correct\n");
CorrectAnswer++;
}else
outputlabel.setText("Wrong!\n");
if(C19.getState()) // if the user chooses the checkbox C19
{
outputlabel.setText("Correct\n");
CorrectAnswer++;
}else
outputlabel.setText("Wrong!\n");
if(C21.getState()) // if the user chooses the checkbox C21
{
outputlabel.setText("Correct\n");
CorrectAnswer++;
}else
outputlabel.setText("Wrong!\n");
if(C27.getState()) // if the user chooses the checkbox C27
{
outputlabel.setText("Correct\n");
CorrectAnswer++;
}else
outputlabel.setText("Wrong!\n");
CorrectLabel.setText("Correct Answers: "+CorrectAnswer);
score =(CorrectAnswer*100)/5; // average of the quiz
if (score>=75)
{
scorelabel.setText("Grade: "+score+ "% ");
}else{
scorelabel.setText("Grade: "+score+"%.");
repaint();}
}
}
I'm not entirely sure what you're trying to do in the code. For each you're checking if it is set, and then you're setting the outputlabel value. So if the first checkbox is checked it will set the outputlabel text to "Correct". And if any of the other checkboxes are not checked it will then simply override what you did before and set the label to "Wrong".
Maybe you want separate outputlabels for each of the checkboxes?
You should have one final output label, after you check the state of all the correct answers. And based on the correct answers count, you can set the final output label.