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.
Related
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));
}
});
I have pondered on this for days now, I need help. I have 2 fragments in a viewpager. They are both showing the same values despite feeding them with different data.
Link to image
Fragment A has a spinner dropdown of countries same as Fragment B. Fragment A is supposed to show list of Hospitals when country is selected, Fragment B is supposed to show list of Schools depending on country selected.
PROBLEM
When I select a country in Fragment A, I get the list of hospitals in fragment A. When I swipe to fragment B, I find the list of hospitals which are supposed to be in A displayed. When I select a country in B, the list refreshes and I get the list of schools as should be, but when I swipe back again to fragment A I find the same list of schools instead of list of hospitals previously selected. I am using dagger2 with databinding.
Below code depicts one scenario but they are basically the same just different adapters and also different layouts.
CODE
private void initRecyclerview() {
binding.rvSchools.setHasFixedSize(true);
adapter = new SchoolsAdapter(getContext());
binding.rvSchools.setLayoutManager(new LinearLayoutManager(getContext()));
binding.rvSchools.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
private void countries() {
viewModel.getCountries().removeObservers(getViewLifecycleOwner());
viewModel.getCountries().observe(getViewLifecycleOwner(), new Observer<Resource<List<Countries>>>() {
#Override
public void onChanged(Resource<List<Countries>> countriesList) {
switch (countriesList.status) {
case SUCCESS:
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(getApplicationContext,
R.layout.simple_spinner_item, countriesList);
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
binding.spinner.setAdapter(spinnerAdapter);
spinnerAdapter.notifyDataSetChanged();
break;
}
}
});
binding.spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String country = countriesList.get(position);
schools(country);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {}
});
}
private void schools(String country) {
viewModel.getSchoolsHospitals(country, "School").removeObservers(getViewLifecycleOwner());
viewModel.getSchoolsHospitals(country, "School").observe(getViewLifecycleOwner(), new Observer<Resource<List<SchoolsHospitals>>>() {
#Override
public void onChanged(Resource<List<SchoolsHospitals>> schoolsList) {
switch (schoolsList.status) {
case SUCCESS:
binding.setSchools(schoolsList.data);
}
}
});
}
This is a rather odd behaviour considering how I wanted to re-use code. I was using the same viewModel class because the data is the same. After creating a separate viewModel class for Schools i.e a duplicate ViewModel just different class names, the respective contents were set as needed.
If there is a better approach, it will be much appreciated.
I've been tinkering with some code from udacity.
https://github.com/udacity/ud839_CustomAdapter_Example
I wanted to use my selection from a list in another activity. I usually use a toast message to test if I have successfully selected the correct item etc. But even my toast message is crashing the app.
Below is a shortened version of the arraylist, listview and onitemclicklistener.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create an ArrayList of AndroidFlavor objects
final ArrayList<AndroidFlavor> androidFlavors = new ArrayList<AndroidFlavor>();
androidFlavors.add(new AndroidFlavor("Lollipop", "5", R.drawable.lollipop));
androidFlavors.add(new AndroidFlavor("Nougat", "7", R.drawable.nougat));
androidFlavors.add(new AndroidFlavor("Oreo", "8", R.drawable.oreo));
// Create an {#link AndroidFlavorAdapter}, whose data source is a list of
// {#link AndroidFlavor}s. The adapter knows how to create list item views for each item
// in the list.
final AndroidFlavorAdapter flavorAdapter = new AndroidFlavorAdapter(this, androidFlavors);
// Get a reference to the ListView, and attach the adapter to the listView.
ListView listView = (ListView)findViewById(R.id.listview_flavor);
listView.setAdapter(flavorAdapter);
Below is the code that I believe is causing the problem, the onItemClick works if I manually pass strings but it won't pass the selected list item. androidFlavors.get(position) doesn't appear to be correct but I'm unsure why.
//onClickItemListener to take selected Arraylist component and display the selected component in a toast message
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick( AdapterView<?> parent, View view, int position, long id ) {
Toast.makeText(getApplicationContext(), (CharSequence) androidFlavors.get(position), Toast.LENGTH_SHORT).show();
}
});
}
}
You are trying do you cast new AndroidFlavor("Nougat", "7", R.drawable.nougat) to CharSequence. Instead you should use getVersionName.
Toast.makeText(getApplicationContext(), androidFlavors.get(position).getVersionName(), Toast.LENGTH_SHORT).show();
I have a spinner in my activity which contain Operators name ,what I want when user selected item from spinner I want to send another value to server,like
if user select "Airtel" from spinner I have to send "AR" to server same like other items .how can I do that.
code:-\
<string-array name="operators">
<item>Select Operator</item>
<item>Aircel</item>
<item>Airtel</item>
<item>BSNL</item>
<item>Idea</item>
<item>Vodafone</item>
<item>MTNL Delhi</item>
<item>MTNL Mumbai</item>
</string-array>
here when user select item from above list I have to send value from below list according to above items.
<string-array name="Operators_Code">
<item>AC</item>
<item>AT</item>
<item>BS</item>
<item>ID</item>
<item>VD</item>
<item>MT</item>
</string-array>
A Spinner, similar to ListView, RecyclerView, etc., is an "adapter backed" View. That is, it gets the items to be displayed from an Adapter.
When you set the entries to be shown using android:entries="#array/operators, Spinner internally creates an Adapter with the supplied array items. This simple solution, however, doesn't support complex objects.
For your use case, you'll have to create a custom Adapter for your Spinner.
public class Operator {
String name;
String code;
#Override
public String toString() {
return name;
}
}
final List<Operator> operators = new ArrayList(7);
operators.add(new Operator("Select operator", null));
operators.add(new Operator("Aircel", "AC"));
operators.add(new Operator("Airtel", "AC"));
....
Next, set the adapter on your spinner:
final ArrayAdapter<String> operatorsAdapter = new ArrayAdapter<>(context, android.R.layout.simple_dropdown_item_1line, operators);
spinner.setAdapter(operatorsAdapter);
That's it. Now if you want to listen to user's selections, add a listener to your Spinner by:
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
final Operator selectedOperator = operatorsAdapter.getItem(position);
final String selectedOperatorCode = selectedOperator.code;
// TODO: Send the selected operator to the server.
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
I need to display a list of text items to the screen and make them clickable. So it would be something like a list of links on a web application.
How can I do that in an Android Activity screen?
It would be some random number of items that I have to pull from a db and display all as links.
Any idea how that can be done?
You should read the doc about ListActivity, ListView and follow the Hello ListView tutorial.
Yes you can do it. Create a DataExchange class to fetch it from Db..
Store the Strings in an Array.
Create a ArrayAdapter to display the array of Strings you got from the database.
for Example
public class AndroidListViewActivity extends ListActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// storing string resources into Array
String[] numbers = {"one","two","three","four"}
// here you store the array of string you got from the database
// Binding Array to ListAdapter
this.setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, R.id.label, numbers));
// refer the ArrayAdapter Document in developer.android.com
ListView lv = getListView();
// listening to single list item on click
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// selected item
String num = ((TextView) view).getText().toString();
// Launching new Activity on selecting single List Item
Intent i = new Intent(getApplicationContext(), SingleListItem.class);
// sending data to new activity
i.putExtra("number", num);
startActivity(i);
}
});
}
}
The secondActivity to display the Particular item you have clicked should be
public class SingleListItem extends Activity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.single_list_item_view);
TextView txtProduct = (TextView) findViewById(R.id.product_label);
Intent i = getIntent();
// getting attached intent data
String product = i.getStringExtra("number");
// displaying selected product name
txtProduct.setText(product);
}
}
you have to create various layout files accordingly..
Hope this helps you :)
You should use a ListView. It's very simple, just create a ListActivity, put your items inside an Adapter and then set it as the Adapter of your ListActivity.
You can read more about ListViews here
There is also a new paradigm called ListFragment.
I have used ListViews before but prefer the fragments approach now - it's just very straight forward and quite flexible esp on tablets since the interation with another area on the screen when selecting an item is quite flexible and only requires very little code.
Just one example:
public class Select_FoodCategories_Fragment extends android.app.ListFragment {
private static final boolean DEBUG = true;
#Override
public void onCreate(Bundle savedInstanceState) {
if (DEBUG)
Log.i(this.getClass().getSimpleName(), " ->"
+ Thread.currentThread().getStackTrace()[2].getMethodName());
super.onCreate(savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (DEBUG)
Log.i(this.getClass().getSimpleName(), " ->"
+ Thread.currentThread().getStackTrace()[2].getMethodName());
HoldingActivity a = (HoldingActivity) getActivity();
//accessing a variable of the activity is easy
a.visibleListViewInFragment = getListView();
List<XYZ> listTodisplay = a.getListToDisplay();
MyAdapter adapter = new MyAdapter(
getActivity(), 0, listTodisplay);
setListAdapter(adapter);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
if (DEBUG)
Log.i(this.getClass().getSimpleName(), " ->"
+ Thread.currentThread().getStackTrace()[2].getMethodName());
XYZ item = (XYZ) getListAdapter()
.getItem(position);
}
}
More info here: http://developer.android.com/reference/android/app/ListFragment.html
By the way, I find it really worth it to get familiar with the new fragments concept - it just makes live much easier - esp on tablets!
ps I left the debug statements in on purpose - since it helps alto to understand the whole concept much faster in my experience