I have this file as an example of a Pet app for Android that showcases profiles of cats or dogs (courtesy of a Udemy course). this is the base file:
package com.delta.generics;
import android.app.Activity;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Bundle;
import android.service.dreams.DreamService;
import android.util.StringBuilderPrinter;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class GenericsActivity extends Activity {
public TextView nameTextView = null;
public TextView descriptionTextView = null;
public RatingBar ratingView = null;
public ImageView portraitView = null;
public Button nextButton = null;
private int currentSelection = 0;
// CatAdapter catAdapter;
AdoptAdapter<Cat> catAdoptAdapter;
// AdoptAdapter<Dog> dogAdoptAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_generics);
nameTextView = (TextView) findViewById(R.id.nameTextView);
descriptionTextView = (TextView) findViewById(R.id.descriptionTextView);
ratingView = (RatingBar) findViewById(R.id.ratingView);
portraitView = (ImageView) findViewById(R.id.portraitView);
nextButton = (Button) findViewById(R.id.nextButton);
nextButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showNext();
}
});
// commenting this out in favour of AdoptAdapter objects
// catAdapter = new CatAdapter(this,nameTextView,descriptionTextView,ratingView,portraitView);
// catAdapter.set(AdoptData.mCatList.get(0));
catAdoptAdapter = new AdoptAdapter<Cat>(this, nameTextView, descriptionTextView, ratingView, portraitView);
// dogAdoptAdapter = new AdoptAdapter<Dog>(this, nameTextView, descriptionTextView, ratingView, portraitView);
catAdoptAdapter.set(AdoptData.mCatList.get(0));
// dogAdoptAdapter.set(AdoptData.mDogList.get(0));
// mCatList and mDogList is an object already exists in AdoptData.java
}
public void showNext(){
int random = currentSelection;
int animal_random = 0;
animal_random = (int )(Math.random() * 2;
while(random == currentSelection){
//avoid same selection twice.
random = (int )(Math.random() * AdoptData.mCatList.size());
random = (int )(Math.random() * AdoptData.mDogList.size());
}
currentSelection = random;
Cat c = AdoptData.mCatList.get(random);
// Dog d = AdoptData.mDogList.get(random);
// commenting in favour of AdoptAdapter object
// catAdapter.set(c);
catAdoptAdapter.set(c);
// dogAdoptAdapter.set(d);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.generics, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
The issue I see is that the way this is formatted, it can only either showcase Cat or Dog profiles, but not together, and I wanted to figure out a way of how to "mix" them so both Cats and Dogs shows up randomly when pressing the "Next" button. And so I figured within the context of Java and this file, I figured I can modify the showNext() method:
public void showNext(){
int random = currentSelection;
int animal_random = 0;
animal_random = (int )(Math.random() * 2);
Log.e("animal_random", String.valueOf(animal_random));
switch(animal_random){
case 0:
while(random == currentSelection){
//avoid same selection twice.
random = (int )(Math.random() * AdoptData.mCatList.size());
}
currentSelection = random;
Cat c = AdoptData.mCatList.get(random);
catAdoptAdapter.set(c);
break;
case 1:
while(random == currentSelection){
//avoid same selection twice.
random = (int )(Math.random() * AdoptData.mDogList.size());
}
currentSelection = random;
Dog d = AdoptData.mDogList.get(random);
dogAdoptAdapter.set(d);
break;
}
}
But I feel like there are way too many "repeated lines" here. If this were in Python I would probably utilize the getAttribute() method to determine which method to use in the object based on a string match. However when I tried to use the supposed Java equivalent getMethod() i keep getting a java.lang.NoSuchMethodException error when i try to use it.
Is there a better way to go about this in Java...? Or would it require a complete restructure for this specific example?
Once you've picked any of the two alternatives below, just update the rest of your code and you'll probably see less duplication across the board since the animals will have a common ground somewhere. :-)
The interface way
Create an Animal interface that gives you access to the common things for animals in your given case, and then implement the interface in both your Dog and your Cat class. Your code in question will probably mostly be talking about Animals instead, unless you explictly need to differentiate between a Dog or a Cat in some way.
One of the neat things about this approach is that while the interface will enforce a contract, it also gives you the wiggle room for if you example want the Dog class to be able to contain stuff that the Cat shouldn't. Maybe it already does?
The enum way
Consolidate your Dog and Cat classes into a single Animal class that carries an enum field called type or something like that. Less classes (hurray?), but with the caveat that the dogs, cats and whatever future animals you add kinda have to fit into the same data structure. Depending on how much weight and meaning the actual type of animal actually has, this may or may not be a really bad idea.
Related
i followed a YouTube tutorial about programming a quiz app using java android studio
in the tutorial you put the question in array list then you get randomly question from it
this can cause a problem of getting the same question many time.
How can i fix that? i thought about instead of using random i use a function to get the next item in the list but it didn't work for me.
Yhis is my code
package com.example.quiz20;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import java.util.ArrayList;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
private TextView questionTV,questionNumberTV;
private Button option1Btn,option2Btn,option3Btn,option4Btn;
private ArrayList<QuizModel> quizModelArrayList;
Random random;
int currentScore = 0 , questionAttempted = 0, currentPos;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
questionTV= findViewById(R.id.idTVQuestion);
questionNumberTV=findViewById(R.id.idTVQuestionAttempted);
option1Btn=findViewById(R.id.idBtnOption1);
option2Btn=findViewById(R.id.idBtnOption2);
option3Btn=findViewById(R.id.idBtnOption3);
option4Btn=findViewById(R.id.idBtnOption4);
quizModelArrayList = new ArrayList<>();
random = new Random();
getQuizQuestion(quizModelArrayList);
currentPos = random.nextInt(quizModelArrayList.size());
setDataToViews(currentPos);
option1Btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(quizModelArrayList.get(currentPos).getAnswer().trim().toLowerCase().equals(option1Btn.getText().toString().trim().toLowerCase())){
currentScore++;
}
questionAttempted++;
currentPos = random.nextInt(quizModelArrayList.size());
setDataToViews(currentPos);
}
});
option2Btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(quizModelArrayList.get(currentPos).getAnswer().trim().toLowerCase().equals(option2Btn.getText().toString().trim().toLowerCase())){
currentScore++;
}
questionAttempted++;
currentPos = random.nextInt(quizModelArrayList.size());
setDataToViews(currentPos);
}
});
option3Btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(quizModelArrayList.get(currentPos).getAnswer().trim().toLowerCase().equals(option3Btn.getText().toString().trim().toLowerCase())){
currentScore++;
}
questionAttempted++;
currentPos = random.nextInt(quizModelArrayList.size());
setDataToViews(currentPos);
}
});
option4Btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(quizModelArrayList.get(currentPos).getAnswer().trim().toLowerCase().equals(option4Btn.getText().toString().trim().toLowerCase())){
currentScore++;
}
questionAttempted++;
currentPos = random.nextInt(quizModelArrayList.size());
setDataToViews(currentPos);
}
});
}
private void showBottomSheet(){
BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(MainActivity.this);
View bottomSheetView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.score_bottom_sheet,(LinearLayout)findViewById(R.id.idLLScore));
TextView scoreTV = bottomSheetView.findViewById(R.id.idTVScore);
Button restartQuizBtn = bottomSheetView.findViewById(R.id.idBtnRestart);
scoreTV.setText("you score is \n"+currentScore + "/4");
restartQuizBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
currentPos = random.nextInt(quizModelArrayList.size());
setDataToViews(currentPos);
questionAttempted = 0;
currentScore = 0;
bottomSheetDialog.dismiss();
}
});
bottomSheetDialog.setCancelable(false);
bottomSheetDialog.setContentView(bottomSheetView);
bottomSheetDialog.show();
}
private void setDataToViews(int currentPos){
questionNumberTV.setText("Question Attempted : "+questionAttempted + "/4");
if(questionAttempted == 4){
showBottomSheet();
}else {
questionTV.setText(quizModelArrayList.get(currentPos).getQuestion());
option1Btn.setText(quizModelArrayList.get(currentPos).getOption1());
option2Btn.setText(quizModelArrayList.get(currentPos).getOption2());
option3Btn.setText(quizModelArrayList.get(currentPos).getOption3());
option4Btn.setText(quizModelArrayList.get(currentPos).getOption4());
}
}
private void getQuizQuestion(ArrayList<QuizModel> quizModelArrayList) {
quizModelArrayList.add(new QuizModel("in which year google released?","1998","2000","2004","1995","1998"));
quizModelArrayList.add(new QuizModel("What does CPU stand for?","Core Processing Unit","Central Processing Unit","Command Processing Unit","Custom Processing Unit","Central Processing Unit"));
quizModelArrayList.add(new QuizModel("what is the name of the first internet search engine?","Google","Yahoo","AOL","Archie","Archie"));
quizModelArrayList.add(new QuizModel("Which Programming language is the most widely used?","JavaScript","JAVA","Python","PHP","JavaScript"));
}
}
To avoid getting the same selection multiple times, you may want to remove it from the list after it was chosen. The syntax could look something like this:
Random rand = new Random();
ArrayList <Type> list = new ArrayList<>();
int selection = rand.nextInt(list.size() + 1);
switch(selection)
{
case X:
do the X stuff;
list.remove(X);
break;
}
The ArrayList knows what index X is at, so calling it by name will remove the entry. Using the size of the ArrayList to create the bounds for Random numbers also helps keep it dynamic
NOTE this is NOT complete code
Information/examples about preserving contents of the ArrayList using list.clone()
https://www.tutorialspoint.com/clone-an-arraylist-in-java -- An ArrayList can be cloned using the java.util.ArrayList.clone() method. This method does not take any parameters but returns a shallow copy of the specified ArrayList instance. This means that the new ArrayList created using the ArrayList.clone() method refers to the same elements as the original ArrayList but it does not duplicate the elements.
If you want to maintain a list of questions, and then some method of identifying if those have been asked, there are multiple ways to do this.
You could add a boolean value inside QuizModel which holds whether the question has been asked or not in this round, and part of the process to starting a new round of the quiz would be to ensure they are all set to false. The value can be set to true when that question has been asked, and you'd check that value before deciding to use this question or getting another.
Alternatively, you could make the problem less specific to your usecase and more generalised. - for example, all you're really asking is how to get a random number, from a set of numbers, minimising the possibility of duplicates. This is a common software problem that has been solved many many times before.
see Creating random numbers with no duplicates for example. Then you could work this solution into your question selection code.
there are two ways to get the next item in the list:
Using the index:
list.get(list.indexOf(item)+1);
list - your list of questions
item - current question
use LinkedList and its methods
You can drop the question from the array list and make the random number 1 smaller each time. You have to make sure the list can be reset and is automatically reset when it gets to 0 if you do this.
For my uni task I have to adapt a piece of code that we are given to create an app that adds up total costs of items and displays them in Java, and i'm very new to mobile development. We were given the code for everything other than the totalling up and displaying the cost. I added a few variables at the top and a total() method.
Currently, when the app runs it will grab all the prices from the items and add/subtract them as required, but the amounts it's adding and subtracting by are wrong, (everything adds and subtracts by 1.5 instead of the prices defined when the objects are created) and i'm not sure why. Any ideas?
Let me know if you need anymore info from the other classes.
Thanks
EDIT: What I am expecting to happen with the app is that it will have 4 rows, each contain an image associated with one of the Dessert objects, text to say which dessert it is, and then a button to increment and decrement the quantity. I also want to display a total cost of all of the currently selected desserts, e.g if a quantity of 1 donut was selected and a quantity of 2 cookies were selected, the expected total should display as £3.88. The total should update whenever another dessert is added or subtracted
The code I received had the functionality of the list and the increment and decrement functions, so I was tasked with adding prices to the objects, and to make them total up.
CODE:
Main-Acitvity.java
package com.example.annascott.buttondemo;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
// quantity of desert
int desertNumber;
Dessert currentDessert;
double totalAmount = 0;
// Create an ArrayList of Dessert objects
final ArrayList<Dessert> desserts = new ArrayList<Dessert>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//CREATE THE DESSERT OBJECTS
desserts.add(new Dessert("Donut", 0, R.drawable.doughnut, 1.99));
desserts.add(new Dessert("Cookie", 0, R.drawable.cookie, 0.99));
desserts.add(new Dessert("PieceOfCake", 0, R.drawable.piece_of_cake, 2.99));
desserts.add(new Dessert("Pastry", 0, R.drawable.pastry, 1.50));
// Create an {#link DessertAdapter}, whose data source is a list of
// {#link Dessert}s. The adapter knows how to create list item views for each item
// in the list.
DesertAdapter flavorAdapter = new DesertAdapter(this, desserts);
// Get a reference to the ListView, and attach the adapter to the listView.
ListView listView = (ListView) findViewById(R.id.listview_dessert);
listView.setAdapter(flavorAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
switch (i) {
case 0:
Intent donut = new Intent(MainActivity.this, Donut.class);
startActivity(donut);
break;
case 1:
Intent cookie = new Intent(MainActivity.this, Cookie.class);
startActivity(cookie);
break;
case 2:
Intent pieceOfCake = new Intent(MainActivity.this, PieceOfCake.class);
startActivity(pieceOfCake);
break;
case 3:
Intent pastry = new Intent(MainActivity.this, Pastry.class);
startActivity(pastry);
break;
}
}
});
}
public void Decrement(View view) {
LinearLayout parentRow = (LinearLayout) view.getParent();
TextView quantityView = (TextView) parentRow.findViewById(R.id.dessert_number);
String quantityString = quantityView.getText().toString();
desertNumber = Integer.parseInt(quantityString);
desertNumber -= 1;
if (desertNumber < 0) {
desertNumber = 0;
Toast.makeText(MainActivity.this, "Can not be less than 0",
Toast.LENGTH_SHORT).show();
}
quantityView.setText(String.valueOf(desertNumber));
total(false);
}
public void Increment(View view) {
// Set the dessert amount to the text view
LinearLayout parentRow = (LinearLayout) view.getParent();
TextView quantityView = (TextView) parentRow.findViewById(R.id.dessert_number);
String quantityString = quantityView.getText().toString();
desertNumber = Integer.parseInt(quantityString);
desertNumber += 1;
quantityView.setText(String.valueOf(desertNumber));
total(true);
}
// Add the total cost of the items to be bought
public void total(boolean change) {
//get all of the desserts
for (int i = 0; i < desserts.size(); i++) {
currentDessert = desserts.get(i);
}
// if increment add price else subtract
TextView shoppingCartView = (TextView) findViewById(R.id.shopping_cart);
if (change) {
totalAmount += currentDessert.getMyPrice();
} else {
totalAmount -= currentDessert.getMyPrice();
}
shoppingCartView.setText(Double.toString(totalAmount));
}
}
Dessert.java
package com.example.annascott.buttondemo;
/**
* {#link Dessert} represents type of desert.
* Each object has 3 properties: name, number, and image resource ID.
*/
public class Dessert {
// Name of the desert
private String mDessertName;
// Number of desserts
private int mDessertNumber;
// Drawable resource ID
private int mImageResourceId;
// Price of desert
private double myPrice;
/*
* Create a new dessert object.
*
* #param vName is the name of the dessert
* #param vNumber is the corresponding number of desserts
* #param image is drawable reference ID that corresponds to the dessert
* */
public Dessert(String vName, int vNumber, int imageResourceId, double price)
{
mDessertName = vName;
mDessertNumber = vNumber;
mImageResourceId = imageResourceId;
myPrice = price;
}
/**
* Get the name of the dessert
*/
public String getDessertName() {
return mDessertName;
}
/**
* Get the number of desserts
*/
public int getDessertNumber() {
return mDessertNumber;
}
/**
* Get the image resource ID
*/
public int getImageResourceId() {
return mImageResourceId;
}
public double getMyPrice() {
return myPrice ;
}
}
Your error is probably in the total function.
//get all of the desserts
for (int i = 0; i < desserts.size(); i++) {
currentDessert = desserts.get(i);
}
you assign the last entry to the variable currentDessert, which is you Pastry with the value of 1.5
How about something like this:
// Add the total cost of the items to be bought
public void total(boolean change) {
//get all of the desserts
for (int i = 0; i < desserts.size(); i++) {
currentDessert = desserts.get(i);
if (change) {
totalAmount += currentDessert.getMyPrice();
} else {
totalAmount -= currentDessert.getMyPrice();
}
}
// if increment add price else subtract
TextView shoppingCartView = (TextView) findViewById(R.id.shopping_cart);
shoppingCartView.setText(Double.toString(totalAmount));
}
But i gotta be honest, i have no clue what you're trying to do here, and what's your problem, or expected output for a certain input.
And that being said, i have no idea what's wrong with your code, because i don't know what it should have done in the first place. If/when seeking debugging help, please put down some sample inputs and expected outputs for them.
you are searching through ALL the desserts in your total function.
So you need to somehow find a way of specifying which desert price you want to add the price off.
I would add a clicked boolean variable to each button in your switch case statement earlier in your code but this is not the only way.
I am making a simple semi-textbased adventure game.
I am trying to get a working inventory switching system.
I have a system where your (up to 14) items appear as the text of radiobuttons, but it leaves a lot of them as repetitive "You have nothing"s.
Is there anyway that I can make X radio buttons come on screen, where X is the number of items you currently have that you can switch to?
I tried creating and then adding radio buttons to the radio group (and then simply deleting the old 14 buttons I originally had), but I need a class called Context, and as I am new to android I don't understand what that is.
package com.blogspot.darokrithia.dungeonfungeon;
import android.content.Intent;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import java.util.ArrayList;
/**
* Created by dtabin17 on 1/21/16.
*/
public class ItemSwitcherActivity extends AppCompatActivity{ //Used to switch items in inventory slots
int itemType = InventoryActivity.itemToSwitch;; // lets the class know what kind of item to switch
RadioGroup listOfItems;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_switcher);
setupItems(itemType);
}
public void onBackClick(View v){ //when player clicks back button
if (v.getId() == R.id.backButton){
Intent i = new Intent(ItemSwitcherActivity.this, InventoryActivity.class);
startActivity(i); // goes back to inventory screen
}
}
public void setupItems(int t){ //gets the proper Radio buttons
int[] equippedInventory = RoomActivity.player.getEquipment(); //here until (look bellow)
int[] inventory = RoomActivity.player.getInventory(); //
ArrayList <Equipment> totalInventory = new ArrayList<>(); //Compiled list of inventory and equipped items
listOfItems = (RadioGroup) findViewById(R.id.inventoryList); //The radio group displayed
ArrayList <Equipment> listedInventory = new ArrayList<>(); //Items already listed.
//
for (int i = 0; i < equippedInventory.length; i++){ //
int ID = equippedInventory[i]; //
Equipment e = new Equipment(ID); //
totalInventory.add(e); //
} //
for (int i = 0; i < inventory.length; i++){ //
int ID = inventory[i]; //
Equipment e = new Equipment(ID); //
totalInventory.add(e); //
} //here gets the players equipment into a one nice and easy to use ArrayList
switch(t){
case(0):
((RadioButton) listOfItems.getChildAt(0)).setText(totalInventory.get(0).getText());
int r = 1;
for (int i = 0; i < (totalInventory.size()-1); i++){
if((totalInventory.get(i).isHelmet) && !(listedInventory.contains(RoomActivity.player.getEquipment()[0]))){
listedInventory.add(totalInventory.get(r));
((RadioButton) listOfItems.getChildAt(i)).setText(totalInventory.get(r).getText());
r++;
}
}
break;
case(1):
//do stuff
break;
case(2):
//do stuff
break;
case(3):
//do stuff
break;
case(4):
//do stuff
break;
default:
Intent i = new Intent (ItemSwitcherActivity.this, InventoryActivity.class);
startActivity(i);
break;
}
}
}
package com.example.mohammed.flagquizgameapp;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.lang.String;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.AssetManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity {
// String used when logging error messages
private static final String TAG = "FlagQuizGame Activity";
private List<String> fileNameList; // flag file names
private List<String> quizCountriesList; //name of countries in quiz
private Map<String, Boolean> regionsMap; // which regions are enabled
private String correctAnswer; // correct country for the current flag
private int totalGuesses; // number of guesses made
private int correctAnswers; // number of correct guesses
private int guessRows; // number of rows displaying choices
private Random random; //random number generator
private Handler handler; // used to delay loading next flag
private Animation shakeAnimation; // animation for incorrect guess
private TextView answerTextView; // displays Correct! or Incorrect!
private TextView questionNumberTextView; // shows current question #
private ImageView flagImageView; // displays a flag
private TableLayout buttonTableLayout; // table of answer Buttons
// called when the activity is first created
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // call the superclass's method
setContentView(R.layout.activity_main); // inflate the GUI
fileNameList = new ArrayList<String>(); // list of flag names
quizCountriesList = new ArrayList<String>(); // flags in this quiz
regionsMap = new HashMap<String, Boolean>(); // HashMap of regions
guessRows = 1; // default to one row of choices
random = new Random(); // initialize the random number generator
handler = new Handler(); // used to perform delayed operations
// load the shake animation that's used for incorrect answers
shakeAnimation = AnimationUtils.loadAnimation(this, R.anim.incorrect_shake);
shakeAnimation.setRepeatCount(3); // animation repeats 3 times
// get array of world regions from strings.xml
String[] regionNames = getResources().getStringArray(R.array.regionsList);
// by default, countries are chosen from all regions
for (String region : regionNames)
regionsMap.put(region, true);
// get references to GUI components
questionNumberTextView = (TextView) findViewById(R.id.questionNumberTextView);
flagImageView = (ImageView) findViewById(R.id.flagImageView);
buttonTableLayout = (TableLayout) findViewById(R.id.buttonTableLayout);
answerTextView = (TextView) findViewById(R.id.answerTextView);
// set questionNumberTextView's text
questionNumberTextView.setText(getResources().getString(R.string.question) + "1"
+ getResources().getString(R.string.of) + "10");
resetQuiz(); // start a new quiz
} // end method onCreate
// set up and start the new quiz
private void resetQuiz()
{
// use the AssetManager to get the image flag
// file names for only the enabled regions
AssetManager assets = getAssets(); // gets the app's AssetManager
fileNameList.clear(); // empty the list
try{
Set<String> regions = regionsMap.keySet(); // get Set of regions
// loop through each region
for(String region: regions) //if region is enabled
{
if(regionsMap.get(region)) {
//get a list of all the flag image files in this region
String[] paths = assets.list(region);
for(String path: paths)
fileNameList.add(path.replace(".png", ""));
} // end if
} // end for
}// end try
catch(IOException e)
{
Log.e(TAG, "Error loading image file names", e);
} // end catch
correctAnswers = 0; // reset the number of correct answers made
totalGuesses = 0; // reset the total number of guesses the user made
quizCountriesList.clear(); // clear prior list of quiz countries
} // end method resetquiz
// after the user guesses a correct flag, load the next flag
private void loadNextFlag() throws IOException
{
// get the file name of the next flag and remove it from the list
String nextImageName = quizCountriesList.remove(0);
correctAnswer = nextImageName; // update the correct answer
answerTextView.setText(""); // clear answerTextView
// display the number of the current question in the quiz
questionNumberTextView.setText(
getResources().getString(R.string.question) + " " + (correctAnswers + 1) + " " +
getResources().getString(R.string.of) + " 10");
// extract the region from the next image's name
String region = nextImageName.substring(0, nextImageName.indexOf('-'));
// use AssetManager to load next image from the assets folder
AssetManager assets = getAssets(); // get app's AssetManager
InputStream stream; // used to read in flag images
try{
// get an InputStream to the asset representing the next flag
stream = assets.open(region + "/" + nextImageName + ".png");]
// load the asset as a Drawable and display on the flagImageView
Drawable flag = Drawable.createFromStream(stream, nextImageName);
flagImageView.setImageDrawable(flag);
} // end try
catch(IOException e)
{
Log.e(TAG, "Error loading " + nextImageName, e);
} // end catch
// clear prior answer Buttons from TableRows
for(int row = 0; row < buttonTableLayout.getChildCount(); ++row)
((TableRow) buttonTableLayout.getChildAt(row)).removeAllViews();
Collections.shuffle(fileNameList); // shuffle file names
// put the correct answer at the end of fileNameList
int correct = fileNameList.indexOf(correctAnswer);
fileNameList.add(fileNameList.remove(correct));
// get a reference to the LayoutInflater service
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// add 3, 6, or 9 answer Buttons based on the value of guessRows
for(int row = 0; row < guessRows; row++)
{
TableRow currentTableRow = getTableRow(row);
// place Buttons in currentTableRow
for(int column = 0; column < 3; column++)
{
// inflate guess_button.xml to create new button
Button newGuessButton = (Button) inflater.inflate(R.layout.guess_button, null);
// get country name and set it as newGuessButton's text
String fileName = fileNameList.get((row*3) + column);
newGuessButton.setText(getCountryName(fileName));
// register answerButtonListener to respond to button clicks
newGuessButton.setOnClickListener(guessButtonListener);
currentTableRow.addView(newGuessButton);
} // end for
} // end for
// randomly replace one Button with the correct answer
int row = random.nextInt(guessRows); // pick random row
int column = random.nextInt(3);// pick random column
TableRow randomTableRow = getTableRow(row); // get the TableRow
String countryName = getCountryName(correctAnswer);
((Button) randomTableRow.getChildAt(column)).setText(countryName);
} // end method loadNextFlag
// returns the specified TableRow
private TableRow getTableRow(int row)
{
return (TableRow) buttonTableLayout.getChildAt(row);
} // end method getTableRow
// parses the country flag file name and reurns the country name
private String getCountryName(String name) {
return name.substring(name.indexOf('-') + 1).replace('_', ' ');
} // end method getCountryName
// called when the user selects an answer
private void submitGuess(Button guessButton)
{
String guess = guessButton.getText().toString();
String answer = getCountryName(correctAnswer);
++totalGuesses; // increment the number of guesses the user has made
// if the guess is correct
if(guess.equals(answer))
{
++correctAnswers; // increment the number of correct answers
// display "Correct!" in green text
answerTextView.setText(answer + "!");
answerTextView.setTextColor(getResources().getColor(R.color.correct_answer));
disableButtons(); // disable all answer Buttons
// if the user has correctly identified 10 flags
if (correctAnswers == 10)
{
// create a new AlertDialog Builder
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.reset_quiz); // title bar string
// set the AlertDialog's message to display game results
builder.setMessage(String.format("%d %s, %.02f%% %s", totalGuesses, getResources().getString(R.string.guesses),
(1000 / (double) totalGuesses), getResources().getString(R.string.correct)));
builder.setCancelable(false);
// add "Reset Quiz" Button
builder.setPositiveButton(R.string.reset_quiz, new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int id)
{
resetQuiz();
} // end method onClick
} // end anonymous inner class
); // end call to setPositiveButton
//create AlertDialog for the Builder
AlertDialog resetDialog = builder.create();
resetDialog.show(); // display the Dialog
} // end if
else // answer is correct but quiz is not over
{
// load the next flag after a 1-second delay
handler.postDelayed(
new Runnable(){
#Override
public void run()
{
loadNextFlag();
}
}, 1000); // 1000 milliseconds for 1-second delay
} // end else
} // end if
else // guess was incorrect
{
// play the animation
flagImageView.startAnimation(shakeAnimation);
// display "Incorrect!" in red
answerTextView.setText(R.string.incorrect_answer);
answerTextView.setTextColor(getResources().getColor(R.color.incorrect_answer));
guessButton.setEnabled(false); // disable the incorrect answer
} // end else
} // end method submitGuess
// utility method that disables all answer Buttons
private void disableButtons()
{
for(int row = 0; row < buttonTableLayout.getChildCount(); ++row)
{
TableRow tableRow = (TableRow) buttonTableLayout.getChildAt(row);
for(int i = 0; i < tableRow.getChildCount(); ++i)
tableRow.getChildAt(i).setEnabled(false);
} // end outer for
} // end method disableButtons
// create constants for each menu id
private final int CHOICES_MENU_ID = Menu.FIRST;
private final int REGIONS_MENU_ID = Menu.FIRST + 1;
// called when the user accesses the options menu
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
super.onCreateOptionsMenu(menu);
// add two options to the menu - "Choices" and "Regions"
menu.add(Menu.NONE, CHOICES_MENU_ID, Menu.NONE, R.string.choices);
menu.add(Menu.NONE, REGIONS_MENU_ID, Menu.NONE, R.string.regions);
return true; // display the menu
} // end method onCreateOptionsMenu
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// switch the men id of the user-selected option
switch(item.getItemId())
{
case CHOICES_MENU_ID:
// create a list of the possible numbers of animal choices
final String[] possibleChoices = getResources().getString(R.array.guessesList);
//
}
return true;
}
}
The above code has a String[] inside a switch statement. The error that I get from this code is as follows:
Incompatible types
Required: java.lang.String[]
Found: java.lank.String
I'm pretty confused by this. I tried searching it online, but only got results that java.lang.string is found but int is required.
Change
final String[] possibleChoices = getResources().getString(R.array.guessesList);
to
final String[] possibleChoices = new String[] { getResources().getString(R.array.guessesList)};
Incompatible types Required: java.lang.String[] Found:
java.lang.String
the possibleChoices object is expecting an array, not an Integer.
I am trying to get a method from the file Duality.java to be run in Min.Java when a button is clicked. Below are the two files and what I am currently trying to do, which is not working. How do I get the method duality() to run when the button is clicked within Min.java?
Duality.java
package com.android.control;
import android.util.Log;
import com.map.AppName.R;
public class duality {
public void duality(){
Log.e("Did It Run","Yes it ran");
}
}
Min.java
package com.android.control;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import com.map.AppName.R;
public class Min extends LinearLayout {
Button but;
private final int ELEMENT_HEIGHT = 60;
private final int ELEMENT_WIDTH = 80;;
private final int TEXT_SIZE = 30;
public Min( Context context, AttributeSet attributeSet ) {
super(context, attributeSet);
this.setLayoutParams( new LinearLayout.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT ) );
LayoutParams elementParams = new LinearLayout.LayoutParams( ELEMENT_WIDTH, ELEMENT_HEIGHT );
createBut( context );
addView( but, elementParams );
}
private void createButton( Context context){
but = new Button( context );
but.setTextSize( TEXT_SIZE );
but.setText( "Go" );
but.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Duality duality = new duality();
}
});
}
}
You're only constructing an instance of the duality class - you're not calling the duality() method on it.
This might be because you wanted that method to be a constructor - but it's not, because you specified a void return type, so it's just a conventional method.
(By the way, it's conventional in Java to give classes names that start with uppercase characters. If you called your class Duality, there may be less chance that you'd get the two confused; though the problem with accidental non-constructors would still stand.)
Both Min and duality are in the com.android.control package so they should be able to see eachother without imports.
It's recommended to capitalize class names. In fact, since your method has the same name as the class it might be conflicting with the constructor name. I suggest this:
public class Duality {
public void duality(){
Log.e("Did It Run","Yes it ran");
}
}
...
but.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Duality d = new Duality();
d.duality();
}
});
make sure that the class name and file name use same case combination in names.
if u want to call the constructor, remove the void from:
public void duality()
if it is supposed to b a function and not constructor, call it using:
object_name.duality();
u r calling createBut() and have given code for createButton().. is that a mistake in copy pasting?