glaukon
Chapter 3: Java - Part 9
Now that the addDinerButton's more or less done, let's add functionality to the buttons that add additional orders for each Diner. These are addButton1 for the first Diner, and ib for all future Diners. These are the buttons that the user clicks to create a new row that only has 1 EditText, which will be used to store the amount for a new order for a particular Diner. Before we write code that creates this row, we should add some organization that allows each Diner object to keep track of every order EditText associated with it. Go back to the Diner class.
Import ArrayLists again, and then declare the following ArrayList variable called orderList:
public ArrayList<EditText> orderList;
Then assign it to a new ArrayList for EditTexts in the constructor.
orderList = new ArrayList<EditText>();
We'll use this ArrayList to hold all the EditTexts that represent individual orders for any one particular Diner. Given that, let's add etFirstOrder to orderList in the constructor, since that's an order that is created automatically when a Diner is created.
orderList.add(etFirstOrder);
Now let's write the code that takes care of all future new order EditTexts. Create the newOrder method in the Diner class:

public void newOrder(EditText newOrder) {

orderList.add(newOrder);

}

The newOrder method takes an EditText as an argument, and adds that EditText to orderList. We can use this method whenever the user creates a new order. Okay, great, let's go back to MainActivity. Make MainActivity listen to clicks from addButton1 in onCreate.
addButton1.setOnClickListener(this);
Now go to addDinerButton's onClick method. Make sure that all future ImageButtons we create for adding new orders is also being listened to.
ib.setOnClickListener(this);
Next, still in onClick, go to the end of the if block that checks to see if v is equal to addDinerButton, and add the following code, such that it looks like this:

if (v == addDinerButton) {

...

} else {

for (int i = 0; i < dinerList.size(); i++) {

if (v == dinerList.get(i).ibAddOrder) {

TableRow row3 = new TableRow(this);

EditText emptyEditText = new EditText(this);

emptyEditText.setVisibility(4);

EditText newOrder = new EditText(this);

newOrder.setText("$0.00");

newOrder.setSelectAllOnFocus(true);

newOrder.setInputType(amount1of1.getInputType());

newOrder.setGravity(amount1of1.getGravity());

newOrder.setLayoutParams(amount1of1.getLayoutParams());

newOrder.setWidth(amount1of1.getWidth());

newOrder.requestFocus();

row3.addView(emptyEditText);

row3.addView(newOrder);

mainTable.addView(row3, dinerList.size() + 1);

dinerList.get(i).newOrder(newOrder);

}

}

}

The ... represents all the code that we wrote earlier if v is equal to addDinerButton. However, if v is not addDinerButton, we want to check if v is a different button. That's what the else is for. The computer first checks to see if the if conditional is true. If it's not, it skips the if block, and goes to the else block, and runs that code block. If there's an else code block, it always runs when the if conditional is false.
Now let's look at what's inside the else block. It should look very familiar. It's the same for loop we used for onFocusChange. It iterates once for every Diner in dinerList. And what does it do in each iteration? Similar to the onFocusChange block, we first check to see if the v that was clicked is equal to the ibAddOrder ImageButton of a particular Diner. Since we're iterating through every Diner, if the user clicked any of the add order buttons, this loop will eventually hit on the correct ibAddOrder. Once it finds that ImageButton, it runs the code inside the if block. Here, we create another TableRow, row3. We then make 2 EditTexts, emptyEditText and newOrder. We know we just want one new EditText for the rows that represent additional orders for an already existing Diner. However, we need that EditText to be in the second column of mainTable, to line up properly with the other order EditTexts. There are many ways to achieve this, but I find the easiest way is to create a dummy EditText and add it to row3 before the real EditText. The dummy EditText, emptyEditText, will take up the first column, and therefore make the real EditText, newOrder, go to the second column.
Of course, we don't care about any of emptyEditText's properties, which is why we don't bother setting any of them. In fact, we don't even want to see emptyEditText, so we use the setVisibility method to make it invisible. Passing setVisibility an argument of 4 ensures this. No, I don't know why the Android developers chose the number 4 to mean invisible. You can check out the glossary link if you're really curious.
We do, however, care about newOrder's properties. That's why we set the Text, SelectAllOnFocus, InputType, Gravity, LayoutParams, and Width. We also give it focus with requestFocus. With that done, we add both emptyEditText and newOrder to row3 (in that order), and add row3 to mainTable using the same method we used for addDinerButton earlier. Finally, we add newOrder to the relevant Diner object's orderList by calling its newOrder method.
Glossary
setVisibility(int visibility): The setVisibility method makes the View it's called on either visible, invisible, or gone.