i'm making an Android App and in my activity that follows i execute a query to the database and i take the results. I take the results and make TextViews to the Activity. I want when i click the TextView, to pass to the next Activity the name of the Restaurant i click. The problem with my code is that for all the TextViews it save the name of the last Restaurant. Any ideas? Thank you!
public class ViewRestaurants extends Activity{
String name;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.row_restaurant);
DBAdapter db = new DBAdapter(this);
db.open();
Cursor c = db.getSpRestaurants(getIntent().getStringExtra("city"), getIntent().getStringExtra("area"), getIntent().getStringExtra("cuisine"));
View layout = findViewById(R.id.items);
if(c.moveToFirst())
{
do{
name = c.getString(0);
TextView resname = new TextView(this);
TextView res = new TextView(this);
View line = new View(this);
resname.setText(c.getString(0));
resname.setTextColor(Color.RED);
resname.setTextSize(30);
resname.setTypeface(null,Typeface.BOLD);
res.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
res.setText(c.getString(1)+","+c.getString(2)+","+c.getString(3)+"\n"+c.getString(4));
res.setTextSize(20);
res.setTextColor(Color.WHITE);
res.setClickable(true);
res.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent();
i.setClassName("com.mdl.cyrestaurants.guide", "com.mdl.cyrestaurants.guide.RestaurantDetails");
i.putExtra("name",name);
startActivity(i);
}
});
line.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,2));
line.setBackgroundColor(Color.RED);
((LinearLayout) layout).addView(resname);
((LinearLayout) layout).addView(res);
((LinearLayout) layout).addView(line);
}while (c.moveToNext());
}
db.close();
}
}
You'll need to make your name final within your loop and remove it as a class field in order to use it in the OnClickListener the way you are.
if(c.moveToFirst())
{
do{
final String name = c.getString(0);
//other code ...
res.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent();
i.setClassName("com.mdl.cyrestaurants.guide", "com.mdl.cyrestaurants.guide.RestaurantDetails");
i.putExtra("name",name);
startActivity(i);
}
});
//more code...
}while (c.moveToNext());
}
Try making these changes
String name = c.getString(0);
resname.setText(name);
The reason why it is setting to the last restaurant name is because string is being passed by reference rather than by value as it is an object. Creating a unique string within the scope of the do while loop should solve this.
Related
Background:
I have created an Orders table in a database and I am manipulating it in two activities namely CurrentOrders and NewOrders respectively.
CurrentOrders activity shows the current orders stored inside the database in a TableLayout. And to add new orders to the table I have specified a button namely addOrders which when clicked loads NewOrders activity.
CurrentOrders:
public class CurrentOrders extends AppCompatActivity {
private TableLayout table;
populateTable(Cursor records){
TableRow row = new TableRow(this);
TextView product = new TextView(this);
TextView price = new TextView(this);
product.setText(records.getString(1));
price.setText(records.getString(2));
row.addView(product);
row.addView(price);
table.addView(row);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_current_orders);
Cursor cursor = db.query("orders", null, null,
null, null, null, null);
table = findViewById(R.id.tab);
while(cursor.moveToNext())
populateTable(cursor);
}
public void addOrders(View view){
startActivity(new Intent(getApplicationContext(), NewOrders.class));
}
}
NewOrders activity acts like a form by having a TableLayout whose cells/fields are specified as EditText in order to let user type the orders they want to store. And to save the orders inside the database I have specified a submit button which when clicked store the value of EditText inside the Orders table in database and then goes back to parent activity (CurrentOrders) to show all the orders in the database.
NewOrders:
public class NewOrders extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_orders);
}
public void submit(View view){
TableLayout table = findViewById(R.id.newOrders);
int count = table.getChildCount();
for (int idx = 0; idx < count; idx++){
TableRow row = (TableRow) table.getChildAt(idx);
EditText product = (EditText) row.getChildAt(1);
EditText price = (EditText) row.getChildAt(2);
String productVal = product.getText().toString();
double priceVal = Double.parseDouble(price.getText().toString());
long result = db.insert(productVal, priceVal);
}
Toast.makeText(this, "Saved.", Toast.LENGTH_SHORT).show();
onBackPressed();
}
}
Problem:
I don't see new records inserted until an unless I reload the CurrentOrders activity. I want to show all the records (included new ones) without having to reload the activity.
Finally created a simple solution:
First we need to modify our startActivity of CurrentOrder in such a way so that It receives data from NewOrders activity:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
// add newly added orders
if (data != null) {
String response = data.getStringExtra("newOrders");
if (requestCode == RequestCode && resultCode == RESULT_OK && !response.isEmpty()){
String[] orders = response.trim().split(" ");
for (String order : orders) {
// get new orders from the database
Cursor records = db.query("orders", null, "id = ?",
new String[] {String.valueOf(id)},
null, null, null);
records.moveToNext();
populateTable(records);
}
}
}
}
Then in addOrders method you need to replace startActivity with the following code:
startActivityForResult(new Intent(getApplicationContext(), NewOrders.class), 2);
Now coming to NewOrders activity here I have created a string variable that stores id's of the newly created orders:
public class NewOrders extends AppCompatActivity {
// created a string variable
private String newOrdersId = "";
// reset of the code
public void submit(View view){
// rest of the code
for (int idx = 0; idx < count; idx++){
// rest of the code
// record id's of orders inserted into the database
newOrderId += result + " ";
}
// reset of the code
}
}
And lastly you need to send the data to CurrentOrders by overriding onBackPressed method like this:
#Override
public void onBackPressed(){
Intent intent = getIntent();
intent.putExtra("newOrders", newOrdersId);
setResult(RESULT_OK, intent);
finish();
}
I have a listview which consist of items with prices. My listview also has a Delete button. I also have a textview at the bottom part of the layout which is not part of the listview and it shows the total amount. I can successfully remove the item from my listview. What I want is that when the item is removed, the total amount will also change.
Here is a part of my adapter where i must do some actions
holder.del.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
remove(getItem(position));
}
});
and here is my Activity where my textview of amount is found.
public class Cart extends MainActivity {
TextView amount_total;
ListView cartList;
CartCustomAdapter cartCustomAdapter;
String name, price;
static ArrayList<Order> cartArray = new ArrayList<Order>();
static Double total_amount = 0.00d;
static Double temp = 0.00d;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cart);
amount_total = (TextView) findViewById(R.id.total_tv);
Bundle bundle = getIntent().getExtras();
Button checkout = (Button) findViewById(R.id.check_out);
Button add_item = (Button) findViewById(R.id.add_item);
name = bundle.getString("i_name");
price = bundle.getString("i_price");
temp = Double.parseDouble(price);
total_amount = (total_amount + temp);
amount_total.setText("Php" + total_amount.toString());
add_item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Cart.this,MainActivity.class);
startActivity(intent);
}
});
cartList = (ListView) findViewById(R.id.cart_list);
cartCustomAdapter = new CartCustomAdapter(Cart.this,R.layout.list_cart,cartArray);
cartList.setItemsCanFocus(false);
cartList.setAdapter(cartCustomAdapter);
cartArray.add(new Order(name,price,"1"));
cartCustomAdapter.notifyDataSetChanged();
}
}
Define an interface with method like below to update text view in your activity :
updateDeletedItemCount();
and in this method take integer and increase its count like
deletedCount++;
and then update it on text view like this
tvDeletedCount.setText("Deleted Item Count : "+ deletedCount);
This is the easiest way to do that:
//Add a method to your Cart
public void changeTotal(int totalPrice){
if(textView != null) // set total price
}
// Call after remove an item in your listener:
if(getContext() instanceOf Cart){
((Cart)getContext()).changeTotal(newTotalPrice);
}
This is not the best way, but I think it's ok for now :)
i have two activity files in my code, and the first activity file loads the layout search, and the second file loads layout list. I have a textbox in layout search and enter some text. I want to use this text in my second activity file but i can not reach it since it is in the layout search. How can i do this? Here the first activity file, here there is an EditText item called searchedText, and i want to use it in the second activity file.
public class SearchActivity extends Activity{
public EditText searchedText;
public RadioGroup radioGroup;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
}
public void onStart(){
super.onStart();
searchedText = (EditText) findViewById(R.id.searchText);
Button searchinSearchButton = (Button)findViewById(R.id.searchInSearch);
radioGroup = (RadioGroup) findViewById(R.id.radioGroup1);
searchinSearchButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
String searched=searchedText.getText().toString();
Intent myIntent = new Intent(v.getContext(),
SearchListActivity.class);
startActivityForResult(myIntent, 1);
}
});
}
}
And here is the second activity file:
public class SearchListActivity extends Activity{
public DatabaseAdapter db;
public ArrayList<String> myList;
public ListView listview;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list);
db = new DatabaseAdapter(this);
myList = new ArrayList<String>();
getContacts();
// Example of retrieving tweets of the user "mashable" and adding them to
myList
/*
ArrayList<Tweet> tweets= new ArrayList<Tweet>();
tweets.addAll(Twitter.getTimeline("mashable", 10));
for(Tweet t: tweets){
myList.add(t.username + ": " + t.message + " Tweet id: "+ t.id);
}
*/
printList();
}
public void printList(){
listview = (ListView)findViewById(R.id.contactcListView);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1, myList);
listview.setAdapter(adapter);
}
public void getContacts() {
db.open();
Cursor c = db.getContactbyName("y");
if (c.moveToFirst()) {
do {
DisplayContact(c);
} while (c.moveToNext());
}
db.close();
}
public void DisplayContact(Cursor c) {
String entry = "";
// if you add another attribute to your table, you need to change 3 into x
for (int i=1; i<5;i++){
entry += c.getString(i) + "\n";
}
myList.add(entry);
}
}
In this second activity file, you can see the getContacts() method. There, i search by Cursor c = db.getContactbyName("y"); but instead of "y", i want to search whatever user enters the texbox, whic is in the 1st activity file called searchedText. How can i do this?
Thanks
Send the text as an extra in your Intent when you start your second activity.
searchinSearchButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
String searched=searchedText.getText().toString();
Intent myIntent = new Intent(v.getContext(),
SearchListActivity.class);
myIntent.putExtra("SEARCH_STRING",searched);
startActivityForResult(myIntent, 1);
}
});
And in your onCreate get the extra. You could use Intent.getStringExtra(String name)
In other words:
mySearched = getIntent().getStringExtra("SEARCH_STRING");
Just make sure to see if anything is null before using it.
I'm trying to put the contents of List mCartList; into a the sms_body below, eg: Cheeseburger, Hamburger, Fries (so it can be sent through sms). I can pass a string so I know it works. I'm not a programmer at all and it's been a month of me doing trial & error.
Below the activity calls the contents of mCartList into a List so they can be removed. Tell me whatever else you need to help me solve this. Thank you in advance.
private ProductAdapter mProductAdapter;
// This List into the order button below
private List<Product> mCartList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shoppingcart);
mCartList = ShoppingCartHelper.getCart();
// Make sure to clear the selections
for(int i=0; i<mCartList.size(); i++) {
mCartList.get(i).selected = false;
}
// Create the list
final ListView listViewCatalog = (ListView) findViewById(R.id.ListViewCatalog);
mProductAdapter = new ProductAdapter(mCartList, getLayoutInflater(), true);
listViewCatalog.setAdapter(mProductAdapter);
listViewCatalog.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Product selectedProduct = mCartList.get(position);
if(selectedProduct.selected == true)
selectedProduct.selected = false;
else
selectedProduct.selected = true;
mProductAdapter.notifyDataSetInvalidated();
}
});
Button orderButton = (Button) findViewById(R.id.orderButton);
orderButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Uri uri = Uri.parse("smsto:1234567890");
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
// The above List<Product> mCartList ia displayed in the window of the app
intent.putExtra("sms_body", "mCartList"); // I want the results of List<Product> mCartList to go here - I can not just insert the variable I just get errors and can't compile
startActivity(intent);
}
});
Button removeButton = (Button) findViewById(R.id.ButtonRemoveFromCart);
removeButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// Loop through and remove all the products that are selected
// Loop backwards so that the remove works correctly
for(int i=mCartList.size()-1; i>=0; i--) {
if(mCartList.get(i).selected) {
mCartList.remove(i);
}
}
mProductAdapter.notifyDataSetChanged();
}
});
}
Here is how this works. It's a 4 tab list with different items in each tab, 3 of which or products. Customer clicks on the item and they see a description, click add to cart, then your back at the menu. The 4th tab is a the order of what was just selected that is to populate the sms body. I have been able to pass a variable with the text "Hello World". I'm figuring the result of List mCartList can populate the sms body. I'm assuming the List can not just be inserted into the body of a forn without being converter. Let me know if you need anymore info. I'm not a programmer, I have seen similar but nothing that doesn't work without writing other files I got from a tutorial. Thank you in advance.
If all the products are added to your mCartList, it's just a matter of concatenating the String output of the Products together as follows:
orderButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Uri uri = Uri.parse("smsto:1234567890");
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
StringBuilder builder = new StringBuilder();
for(Product p : mCartList){
builder.append(p.toString());
builder.append('\n');
}
intent.putExtra("sms_body", builder.toString());
startActivity(intent);
}
});
make sure your Product has a toString() method defined as follows (example Product guess):
public class Product{
String productName;
public String toString(){
return productName;
}
}
It's hard to explain in the title. Basically as far as I can tell the submit button is taking the name and placing it in the array like I want. What I need now is for the Play(done) Button to transfer the user and the data to the next class (which I believe is coded correctly) and I need it to start a game. The game which you will see in the second class (get the data from the previous) I need it to display the names from the names array 1 at a time and randomly assign them a task to do from the tasks array.
Currently the app is force closing after I click the play button. I'm linking both classes cause I'm pretty sure the problem is in the second class. Thanks for your help ahead of time.
Class1
public class Class1 extends Activity
{
int players=0;
String names[];
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.class1);
final EditText input = (EditText) findViewById(R.id.nameinput);
final ArrayList<String> names = new ArrayList<String>();
Button submitButton = (Button) findViewById(R.id.submit_btn);
submitButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View submit1)
{
players++;
for(int i=0; i < 6; i++)
{
names.add(input.getText().toString());
input.setText("");
}
}
});
Button doneButton = (Button) findViewById(R.id.done_btn);
doneButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View done1)
{
Intent done = new Intent(Class1.this, Game.class);
Bundle bundle = new Bundle();
bundle.putStringArrayList("arrayKey", names);
done.putExtra("players", players);
//done.putExtra("names", names[players]);
startActivity(done);
}
});
}
Game Class
public class Game extends Activity
{
int players, counter=0, score, ptasks,rindex;
String[] names, tasks;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.game);
Bundle bundle = this.getIntent().getExtras();
String[] names = bundle.getStringArray("arrayKey");
Intent game = getIntent();
players = game.getIntExtra("players", 1);
//names = game.getStringArrayExtra("names");
Random generator = new Random();
tasks[0]= "";
tasks[1]= "";
tasks[2]= "";
tasks[3]= "";
tasks[4]= "";
tasks[5]= "";
tasks[6]= "";
tasks[7]= "";
tasks[8]= "";
tasks[9]= "";
while (counter <5)
{
for (int i = 0; i < players; i++)
{
TextView name1 = (TextView) findViewById(R.id.pname);
name1.setText( names[i]+":");
ptasks = 10;
rindex = generator.nextInt(ptasks);
TextView task = (TextView) findViewById(R.id.task);
task.setText( tasks[rindex]);
}
Button failButton = (Button) findViewById(R.id.fail_btn);
failButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View failed)
{
}
});
Button notButton = (Button) findViewById(R.id.notbad_btn);
notButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View notbad)
{
}
});
Button champButton = (Button) findViewById(R.id.champ_btn);
champButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View champp)
{
}
});
counter++;
}
}
Thought I should also mention that these buttons on the 2nd page I would like to assign a score to whichever name array person is up and keep track until the final round where it will display the winner. If anyone has any idea how to make that work.
Have you made sure to include the Game activity as an Application Node in your AndroidManifest?
If not, open your manifest to the application tab, on the bottom hit Add, and add an Activity of the name .Game
Without this, that intent never gets received by the other class.
You've already been told that you use non-initialized arrays here: EditText and using buttons to submit them. But also you're trying to get array extra, however you don't put it inside intent. And you're using uninitialized tasks array in Game class.