I'm building a dialog with a spinner. When the dialog is done, it calls a method of the parent activity with a string argument - the argument being the string value that was selected.
My current approach:
I'm setting up the spinner's array adapter like so:
ArrayAdapter<String> adapter =
new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_item,
categoryNames);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mySpinner.setAdapter(adapter);
categoryNames is a string array. When the dialog is done, the selected categoryName is used as the parameter to the method call on the parent activity.
What I really want to do:
What I actually want is to display a list of Category objects. The Category class has 2 properties - categoryId and categoryName. The spinner should still display the categoryNames in the drop-down view, but when the dialog is done, it should be able to unambiguously tell which Category was selected, and call the parent activity's callback method with the categoryId of the category that was selected.
There can be multiple Categoryies with the same categoryName.
Question: How to do the above?
There are a couple different way to do what you want:
Store the extra data in the adapter, like a SimpleAdapter, SimpleCursorAdapter, or custom one.
Use a Collection of custom objects instead of Strings, simply override the toString() method to present user readable Strings in the Spinner.
You seem to want to do the second option, so here's a generic example:
class Category {
int id;
String name;
public Category(int id, String name) {
this.id = id;
this.name = name;
}
#Override
public String toString() {
return name;
}
}
Your ArrayAdapter is almost the same:
List<Category> categories = new ArrayList<Category>();
// Add new items with: categories.add(new Category(0, "Stack");
ArrayAdapter<Category> adapter =
new ArrayAdapter<Category>(getActivity(), android.R.layout.simple_spinner_item,
categories);
...
mySpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Category category = parent.getItemAtPosition(position);
Log.v("Example", "Item Selected id: " + category.id + ", name: " + category.name);
}
public void onNothingSelected(AdapterView<?> parent) {}
});
Related
I have a user data lie names etc. coming from database which is being populated to AutoCompleteTextView but the position in ItemCLickListener is of the position as displayed in the auto complete list.
I want the array index, and getting string from the adapter won't work because the same names can be there too.
Update
eg. In the database I have 4 entries abc, xyz, abc, pqrq along with some other data in other fields. These names are stored in an array.
So when I click abc, I want the other data to be fetched as well which could be done only if I know the array index of selected item.
Help!
Solution :
Customise the auto_complete_tv_adapter for its items.
Adapter list items will be model wich will hold the name with others data.
Any selected item you will have data model with all other values handy.
sample : https://www.androidcode.ninja/android-autocompletetextview-custom-arrayadapter-sqlite/
Instead of using an array of Strings, you should create an array with custom objects in it.
First, create a new class like this:
class CustomObject {
public long id;
public String name;
public CustomObject(long id, String name) {
this.id = id;
this.name = name;
}
#Override
public String toString() {
return name;
}
}
Then, you get data from your database, which will be Strings, instead of storing only a String you can also add a unique id to the array which we will we use later.
So, for example, you can fill the array like this:
// this array should contain the items from your database, and a unique id
final CustomObject[] items = { new CustomObject(0, "test"), new CustomObject(1, "test"),
new CustomObject(2123123, "another name")};
Then make your AutoCompleteTextview click detector look like this:
textView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
CustomObject customObject = (CustomObject) parent.getItemAtPosition(position);
int index = -1;
for (int i = 0; i < items.length; i++) {
if (items[i].id == customObject.id) {
index = i;
break;
}
}
// now we have your index :)
Toast.makeText(MainActivity.this, "Your index = " + index,
Toast.LENGTH_SHORT).show();
}
});
And that's it, there is the index you need. Note that for large arrays, this method will be slow.
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 want to Convert the Languages. So i am using two Spinners one is "From Language" and Another one is for "To Language". If One Language is Selected in "From Language" Spinner, it shouldn't display (or it should be disabled) in 2nd spinner. how can i achieve it?
Ex. if i Select English in 1st Spinner, 2nd Spinner Shouldn't display English in its dropdown.
This is may not be the best way try this.
ArrayList<String> languages = new ArrayList<>();
languages.add("English");
languages.add("Hindi");
languages.add("Telugu");
languages.add("Tamil");
languages.add("Kannada");
languages.add("Malayalam");
// make a array list of languages
String option1 = null;
Spinner spinnerOption1 = (Spinner) findViewById(R.id.spinner1);
final ArrayAdapter<String> adapterOpton1 = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item, languages);
spinnerOption1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerOption1.setAdapter(adapterOpton1);
spinnerOption1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
option1 = adapterOpton1.getItem(position);
}
});
int selectedIndex;
for (String item : languages) {
if (item.equals(option1)) {
selectedIndex == languages.indexOf(item);
}
}
ArrayList<String> languages2 = languages;
languages2.remove(selectedIndex);
Spinner spinnerOption2 = (Spinner) findViewById(R.id.spinner2);
final ArrayAdapter<String> adapterOption2 = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item, languages2);
spinnerOption2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerOption2.setAdapter(adapterOption2);
Explanation:
lets create a arraylist with languages
bind it to the adapter on the spinner, on selection to the spinner one keep a track of that selection, then find the index of the selection in the arraylist.
create second arraylist with the same languages and find and remove the user selected item, create an adapter and bind the data.
Hope it helps.
Use Hashmaps it will be easier. Create an Adapter that uses Key Values for populating adapter.
This is a snippet I found from another link on how to do that, in case you are not familiar
public class HashMapAdapter extends BaseAdapter {
private HashMap<String, String> mData = new HashMap<String, String>();
private String[] mKeys;
public HashMapAdapter(HashMap<String, String> data){
mData = data;
mKeys = mData.keySet().toArray(new String[data.size()]);
}
#Override
public int getCount() {
return mData.size();
}
#Override
public Object getItem(int position) {
return mData.get(mKeys[position]);
}
#Override
public long getItemId(int arg0) {
return arg0;
}
#Override
public View getView(int pos, View convertView, ViewGroup parent) {
String key = mKeys[pos];
String Value = getItem(pos).toString();
//do your view stuff here
return convertView;
}
}
Credit What adapter shall I use to use HashMap in a ListView
Now for your management of the adapters.
LanguageOneMap.put (all your keys 0-whatever) value (english-whatever)
LanguageTwoMap.put (same as above)
LanguageAllMap.put (same as above)
Adapter 1 selects Language Callback(languageSelectedFromOneKey){
LanguageTwoMap.clearAll
LanguageTwoMap.put (all again)
LanguageTwoMap.remove(languageSelectedFromOneKey)
LanguageTwoAdapter.notifyDataSetChanged()
}
The above is just pseudo code meant to give the idea, not exact copy and paste. Hope that is enough to get you going. There are many ways to skin this cat, you could even use the same list for both adapters. Then when one is selected from one or the other, set a property of "selectedOtherLanguage" in the opposite adapter, then in the GetView method if data.get(pos) == selectedFromOtherListItem return, don't draw.
Many ways to do this, just a matter of how you want to do it. Goodluck.
I have a spinner which is populated with Category objects that are retrieved from the db. The Categories table has _id and category_name columns. I want to show the category name in the spinner, but when the user selects an item, I need it to retrieve the selected item's ID. I tried the following:
Declaring variables (in class level):
int currCategoryId;
ArrayAdapter<String> adapter;
NotesManager manager = new NotesManager(this);
ArrayList<Category> arrListCategories;
ArrayList<String> arrListCategoriesString = new ArrayList<String>();
Spinner spCategories;
Instantiating them in onCreate method:
manager.getAllCategories();
arrListCategories = manager.getAllCategories();
for (int i = 0; i < arrListCategories.size(); i++)
{
Category currCategory = arrListCategories.get(i);
arrListCategoriesString.add(currCategory.getCategory_name().toString());
}
adapter=new ArrayAdapter<String> (this, android.R.layout.simple_spinner_item, arrListCategoriesString);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spCategories.setAdapter(adapter);
spCategories.setOnItemSelectedListener(spinnerListener);
And this is the spinnerListener I tried:
OnItemSelectedListener spinnerListener = new OnItemSelectedListener()
{
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
// An item was selected.
//currCategory = (String) parent.getItemAtPosition(pos).toString();
//selectedCategory =
Category selectedCategory = (Category)spCategories.getItemAtPosition(pos);
currCategoryId = selectedCategory.getId();
}
public void onNothingSelected(AdapterView<?> arg0) {
}
};
But in this case the app crashes and I'm getting a "
String cannot be cast to Category" at this line: Category
selectedCategory = (Category)spCategories.getItemAtPosition(pos);
I also tried this:
currCategoryId = view.getId();
But then instead of 1 or 2 (depending on what category I selected, currently I have 2 of them), I'm getting a very long number...
How can I fix it? How can I retrieve the ID of the selected object?
I would use a SimpleCursorAdapter because it stores multiple columns, instead of an ArrayAdapter that only stores one.
First change NotesManager.getAllCategories() to return a Cursor that uses:
"SELECT _id, category_name FROM Table;"
You could alphabetize the results if you want:
"SELECT _id, category_name FROM Table ORDER BY category_name;"
Next bind this Cursor straight to your Spinner:
Cursor cursor = manager.getAllCategories();
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, cursor, new String[] {"category_name"}, new int[] {android.R.id.text1});
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spCategories.setAdapter(adapter);
Finally in your OnItemSelectedListener everything is ready and waiting:
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
// The parameter id already refers to your Category table's id column,
}
No extra get() calls or converting Cursors into Lists necessary!
You can't use the ArrayAdapter anyway because it's for Strings only (not Categories). Hence why you're getting a casting exception. Since you have your Category ArrayList and your String ArrayList (which is used for the ArrayAdapter) in the same order, just use
Category selectedCategory = arrListCategories.get(pos);
in your onItemSelected() method
I have an array of Strings I'm populating a Spinner object with. However, I'd like to attach an ID to each element of the Spinner, so when the user selects an item, I have its ID to use to save to some other piece of data. How can I do this?
Create a class StringWithTag and use in place of the string name in the list like so :-
public class StringWithTag {
public String string;
public Object tag;
public StringWithTag(String stringPart, Object tagPart) {
string = stringPart;
tag = tagPart;
}
#Override
public String toString() {
return string;
}
}
in the add items to spinner part :-
List<StringWithTag> list = new ArrayList<StringWithTag>();
list.add(new StringWithTag("Oldman", "12345"));
list.add(new StringWithTag("Umpire", "987654"));
list.add(new StringWithTag("Squad", "ABCDEE"));
ArrayAdapter<StringWithTag> adap = new ArrayAdapter<StringWithTag> (this, android.R.layout.simple_spinner_item, list);
....
....
in the listener :-
public void onItemSelected(AdapterView<?> parant, View v, int pos, long id) {
StringWithTag s = (StringWithTag) parant.getItemAtPosition(pos);
Object tag = s.tag;
}
voila!
}
What do you mean by id. You can use ArrayAdapter to populate the Spinner. When item is selected just get the element from the adapter and save the data you want.
Spinner spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<MyObject> adapter = ... // initialize the adapter
adapter.setDropDownViewResource(android.R.layout.some_view);
spinner.setAdapter(adapter);
and when item is selected
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
MyObject selected = parent.getItemAtPosition(pos);
// save any data relevant with selected item
}
If you are storing your data in db you can use CursorAdapter and in onItemSelected to fetch the selected item id from the cursor.
I don't think you can attach an arbitrary ID to elements of a text array resource, if that's what you're using.
I think the simplest way to attach such an ID would be to either hard-code (if you're using a static text resource) or dynamically build (if you get the strings at runtime) a mapping from (String position in array)->(primary key).
EDIT: On the other hand, Mojo Risin has a point - you should check to see if the CursorAdapter API already does what you need for you.
Andrew Hi, it's been a long time but it's worth to write.
You can set a tag for each row when you'r inflating spinnerLayout in SpinnerAdapter:
spinnerView = inflater.inflate(spinnerLayout, parent, false);
spinnerView.setTag("Your Tag");
And then you can get the tag with:
yourSpinner.getSelectedView().getTag();
I think The best solution is to add one more spinner and fill it with the ids but make the visibility of it to gone