I am trying to create a waiter app which allows the waiter to take orders.
I am trying to achieve this using a ListView and setOnItemClickListener.
My idea is that every time a Item is clicked on the ListView it will be added to a ArrayList<Item>. Which later I can pass this List to a method created in DataBaseHelper which then iterates through the List and adds each Item from the order to the SQLite database.
I have not created the method in the DataBaseHelper class yet but I would like to know how to populate the ArrayList<Item> first and then move on to the next step.
The table I will be adding the list to has a manny to many relationship and is called order_item. Which also brings a question to mind as I do not need the full details about the Item and only the IDto save in the table do I need to get all the information of the Item?
Right now what is happening is the app allows me to click and add one Item and then the apps is forced to close.
I am also not sure if I should make the ArrayList a global variable or have it in the Order Object as a variable?
The log says:
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes. [in ListView(2131165292, class android.widget.ListView) with Adapter(class android.widget.ArrayAdapter)]
OrderActivity
public class OrderActivity extends AppCompatActivity {
EditText waiter_id;
Button order;
ListView orderList;
List<Item> itemList = new ArrayList<Item>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order);
waiter_id = (EditText) findViewById(R.id.waiter_id);
order = (Button) findViewById(R.id.order_button);
orderList = (ListView) findViewById(R.id.item_list);
//Showing Items on the ListView
DataBaseHelper dbHelp = new DataBaseHelper(OrderActivity.this);
final List<Item> itemList = dbHelp.getMenu();
ArrayAdapter itemArrayAdaptor = new ArrayAdapter<Item>(OrderActivity.this, android.R.layout.simple_list_item_1, itemList);
orderList.setAdapter(itemArrayAdaptor);
// setOnItemClickListener
orderList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
Item item;
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int pos, long id) {
//Selecting the Item and storing it in a reference variable to add to itemList
Toast.makeText(OrderActivity.this, "Order" + pos , Toast.LENGTH_SHORT).show();
Item item = (Item) adapterView.getAdapter().getItem(pos);
Toast.makeText(OrderActivity.this, item.toString() , Toast.LENGTH_SHORT).show();
itemList.add(item);
}
});
}
}
The problem was I was not notifying the list notifyDataSetChanged() that the item I selected had changed here is the code which now populates the list.
// setOnItemClickListener
orderList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
Order order;
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int pos, long id) {
//Selecting the Item and storing it in a reference variable to add to itemList
Toast.makeText(OrderActivity.this, "Order" + pos , Toast.LENGTH_SHORT).show();
orderItemList.add((Item) adapterView.getAdapter().getItem(pos));
itemArrayAdaptor.notifyDataSetChanged();
Toast.makeText(OrderActivity.this, orderItemList.toString(), Toast.LENGTH_SHORT).show();
}
});
orderList.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
#Override public void onItemClick(AdapterView<?> adapterView, View
view, int pos, long id) {
Toast.makeText(OrderActivity.this, "Added"
,Toast.LENGTH_SHORT).show();
itemList.add(adapterView.getItemAtPosition(pos));
}
});
Related
I have CustomAdapter which I am using for populating ListView with some data.
Each element in ListView has two variables. For each listview (in onItemClick method) I must check this variables and If they are the same - do some code and If they are different - do another code, for example Toast.makeText(EPG.this, "Variables are different", Toast.LENGTH_SHORT).show();
So I have tried this:
private List<SomeItem> items = new ArrayList();
//items were created
SomeAdapter adapter = new SomeAdapter(this, R.layout.list_item, items);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
for(int i=0; i<=items.size(); i++) {
SomeItem item = items.get(position);
String tmpCI = item.getFirstVariable();
String tmpPCI = item.getecondVariable();
if (!tmpCI.equals(tmpPCI)) {
//some code
} else {
Toast.makeText(EPG.this, "Variables are different", Toast.LENGTH_SHORT).show();
}
}
}
});
But all of my listview elements have values of the first element in those two variables.
So how can I do something like item.next(); for validating all of items in listview?
UPD:
Sorry, I will provide more information about what I am doing after checking variables of listview items for understanding my issue.
I have one more adapter:
SomeAnotherAdapter adapterPr = new SomeAnotherAdapter(this, R.layout.list_tem_another, itemsAnother);
and one more listview:
listViewAnother.setAdapter(adapterPr);
First of all I understood, that first variable should be from first listview and the second variable from another listview.
In this listViewAnother I have many items, which has some "id". For example 1st, 5th and 20th elements have id 90 and other elements have id 100.
We can say, that items from the first listview also have "id".
So I must check if(first variable = second variable) and then show in listViewAnother only items that have id which equals ID from clicked item in listView.
I tried: adapterPr.remove(item2); but then I understood, that I need all of items because I can go back to listView and press another item which will need those removed elements.
Now, hope I provided full information and you will be able to help me improve my code.
Do you need to perform the check on every element of the adapter when you click on one element of the adapter? If not, you don't need a loop. If you do, your loop should be iterating over the original list, and does not need adapter position at all.
In general when using adapters and lists, you should use the adapter's position and the adapter's data set to perform any tasks. It's not good practice to use the adapter position to get an item from the original list.
Simply set one onItemClickListener which gets the corresponding item from the adapter, and do what you need to from there:
private List<SomeItem> items = new ArrayList();
//items were created
SomeAdapter adapter = new SomeAdapter(this, R.layout.list_item, items);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
SomeItem item = adapter.getItem(position);
String tmpCI = item.getFirstVariable();
String tmpPCI = item.getecondVariable();
if (!tmpCI.equals(tmpPCI)) {
//some code
} else {
Toast.makeText(EPG.this, "Variables are different", Toast.LENGTH_SHORT).show();
}
}
});
So the spinner I have currently picks from a programmatic array which fetches names and images based on what's in the array.
What I need is to only pick from items in the array if they exist based on the layouts I have.
eg. I have multiple accounts in my main activity list. I only want to be able to pick an account in my spinner based on the accounts I have available (user only has 2 of 3 accounts from the array, thus only display 2 items in the spinner not all 3)
Here's my current spinner code as well as the array:
SpinnerActivity:
public class SpinnerActivity extends AppCompatActivity {
private ArrayList<AccountItem> mAccountList;
private AccountAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_transactions);
//the account_spinner is being pulled from the fragment_transactions xml
initList();
Spinner spinnerAccount = findViewById(R.id.account_spinner);
mAdapter = new AccountAdapter(this, mAccountList);
spinnerAccount.setAdapter(mAdapter);
spinnerAccount.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
AccountItem clickedItem = (AccountItem) parent.getItemAtPosition(position);
String clickedAccountName = clickedItem.getAccountName();
Toast.makeText(SpinnerActivity.this, clickedAccountName + " selected", Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
/**
*This is the array, I need this to link each item to their respective accounts
*that are available
**/
private void initList() {
mAccountList = new ArrayList<>();
mAccountList.add(new AccountItem("Account1", R.drawable.account1_icon));
mAccountList.add(new AccountItem("Account2", R.drawable.account2_icon));
mAccountList.add(new AccountItem("Account3", R.drawable.account3_icon));
}
}
I just need an idea of where to start. As it stands I don't see a way to give my array items individual IDs so I'm not sure if I need to change my array?
You just change the array. If you need to fetch the account list asynchronously, you can call mAdapter.notifyDataSetChanged() in the async completion callback to tell the Adapter that its backing array has changed.
When user clicks on item of ListView I show Edit button at this item of list. lastSelectedPosition has the position of the list item that was clicked last.
code:
public class MainActivity extends Activity {
private ListView listView;
private MyAdapter adapter;
// static - If the activity is re-created, the data
// about list items remain.
private static List<String> items = loadItems();
private MyItemClickListener listener = new MyItemClickListener();
private int lastSelectedPosition = ListView.INVALID_POSITION;
#Override
protected void onCreate(Bundle savedInstanceState) {
listView = (ListView) findViewById(R.id.myListView);
adapter = new MyAdapter(R.layout.my_item, items);
listView.setAdapter(adapter);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
listView.setOnItemClickListener(listener);
if (savedInstanceState != null) {
// Is recreating the activity because
// of the change screen orientation.
lastSelectedPosition = savedInstanceState.getInt("lastSelectedPos");
if (lastSelectedPosition != ListView.INVALID_POSITION) {
// !!! getChildAt() always returns null !!!
View listItem = listView.getChildAt(lastSelectedPosition);
View editButton = listItem.findViewById(R.id.editButton);
// Only selected list item has visible EditButton,
// other list items have not
editButton.setVisibility(View.VISIBLE);
}
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
// Is destroying the activity because
// of the change screen orientation.
outState.putInt("lastSelectedPos", lastSelectedPosition);
}
// Other methods
}
I think that getChildAt() always returns null in Activity.onCreate(), because at that moment the list is not yet fully developed. How I can get View of list item to show Edit button on it?
And sorry for my English.
Thanks
Your adapter needs to know about this selected position so it can be rendered properly in getView(). Just modify the constructor for your adapter to take the int, and update that int value whenever the onclick is called. In general, you should always have all the information you need to recreate the state of your list items within your adapter.
I think it is because you didn't change your lastSelectedPosition's value when user click on item in your listview. Just implement your onItemClickListener like the following code snippet. And change your lastSelectedPosition's value on this. And remove your
private MyItemClickListener listener = new MyItemClickListener();
line.
I think the value of lastSelectedPosition is couldn't changed until you define your listener variable. And also I didn't know where you define your listener variable.
lv1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
lastSelectedPosition = arg2
}
});
I hope this will help you.
I am displaying an arraylist through a listactivity. Also, i have associated id's with these arraylist elements which i can get together in a hashmap maybe. But the problem is i want to obtain that particular id of the element when it is clicked. How to achieve that. Any help is appreciated.
You can return the id based on the clicked position if you an implementation of the getItemId(position) method in your adapter. The id you return here will be the long id argument in the onListItemClick(...) method of your ListActivity.
getItemId(int position) is a member of the ArrayAdapter class. The ListActivity will call that function from the adapter of yourListView. All you have to do is to provide the implementation, the rest will work out just fine.
http://developer.android.com/reference/android/widget/ArrayAdapter.html#getItemId(int)
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapter, View v, int position, long id) {
long pos=lv.getItemAtPosition(position);
//do your stuff here
}
});
if you are using your own ArrayAdapter, you can implement the getItem(position) method..
The answer that worked for me is as follows. Hope it maybe useful for others.
I had the data in Arraylist> testdata. I passed it like this :-
this.setListAdapter(new SimpleAdapter(Grammar_tab_start.this, testdata ,
.layout.tab_single_item, new String[] { "module_name"},
new int[] { R.id.from}));
ListView lv = getListView();
to single list item on click
lv.setOnItemClickListener(new OnItemClickListener()
public void onItemClick(AdapterView<?> parent, View view,
int position, long id)
{
Log.i("check","Module item clicked");
HashMap<String,String> pos=(HashMap<String, String>) lv.getItemAtPosition(position) ;
Log.i("check","----" + position + "id" + id +"actual is "+ pos.get("module_id"));
}
I used the lv.getItemAtPosition() function to retrieve the whole object that was clicked. And then took th eid part from it. Cheers.
I added to my class MyActivity the following :
private void updateMyList(){
listing=new ArrayList<listing>();
for(int i =0;i<10;i++)
{
Users user=new Users();
user.setListingName("Name" + i);
user.setListingPhone("i" + i);
listing.add(user);
}
MyListAdapter lfa = new MyListAdapter(this, listing);
((ListView)findViewById(R.id.listFeed)).setAdapter(lfa);
}
This code generates 10 list views so I'd like to add a click listener, so when I click on one of the 10 lists, I get a message or sthing.
Thank you for your help.
I don't see why you couldn't just add an onItemClickListener in your loop to your ListView. In short, use your Adapter to create the list then just attach the listener:
lv.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, connections.toArray(new String[connections.size()])));
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View item, int position, long id) {
String item = (String) lv.getItemAtPosition(position);
}
});
This is if you want to know which item in each list was clicked, there is an setOnClickListener method as well in case you just want to know whether a ListView has been clicked or not.