Android - configure Spinner to use array - android

I declare my Spinner in the following manner (it's very static so I
have 2 string arrays in array.xml for titles and values)
<Spinner
android:id="#+id/searchCriteria"
android:entries="#array/searchBy"
android:entryValues="#array/searchByValues" />
I expect spinner.getSelectedItem() to return an array [title, value]
but in fact it returns just a title String. Is it ignoring
android:entryValues? How do I get a value, not a title from it? Is
this doable with XML only or do I need to create adapter and do it
programmatically?

Rather than the dual array method, why not fill your ArrayAdapter programmatically with objects of a known type and use that. I've written a tutorial of a similar nature (link at the bottom) that does this. The basic premise is to create an array of Java objects, tell the spinner about the, and then use those objects directly from the spinner class. In my example I have an object representing a "State" which is defined as follows:
package com.katr.spinnerdemo;
public class State {
// Okay, full acknowledgment that public members are not a good idea, however
// this is a Spinner demo not an exercise in java best practices.
public int id = 0;
public String name = "";
public String abbrev = "";
// A simple constructor for populating our member variables for this tutorial.
public State( int _id, String _name, String _abbrev )
{
id = _id;
name = _name;
abbrev = _abbrev;
}
// The toString method is extremely important to making this class work with a Spinner
// (or ListView) object because this is the method called when it is trying to represent
// this object within the control. If you do not have a toString() method, you WILL
// get an exception.
public String toString()
{
return( name + " (" + abbrev + ")" );
}
}
Then you can populate a spinner with an array of these classes as follows:
// Step 1: Locate our spinner control and save it to the class for convenience
// You could get it every time, I'm just being lazy... :-)
spinner = (Spinner)this.findViewById(R.id.Spinner01);
// Step 2: Create and fill an ArrayAdapter with a bunch of "State" objects
ArrayAdapter spinnerArrayAdapter = new ArrayAdapter(this,
android.R.layout.simple_spinner_item, new State[] {
new State( 1, "Minnesota", "MN" ),
new State( 99, "Wisconsin", "WI" ),
new State( 53, "Utah", "UT" ),
new State( 153, "Texas", "TX" )
});
// Step 3: Tell the spinner about our adapter
spinner.setAdapter(spinnerArrayAdapter);
You can retrieve the selected item as follows:
State st = (State)spinner.getSelectedItem();
And now you have a bona fide Java class to work with. If you want to intercept when the spinner value changes, just implement the OnItemSelectedListener and add the appropriate methods to handle the events.
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
// Get the currently selected State object from the spinner
State st = (State)spinner.getSelectedItem();
// Now do something with it.
}
public void onNothingSelected(AdapterView<?> parent )
{
}
You can find the whole tutorial here:
http://www.katr.com/article_android_spinner01.php

So if you came here because you want to have both label and value in the Spinner - here's how I did it:
Just create your Spinner the usual way
Define 2 equal size arrays in your array.xml file. One for labels, one for values
Set your Spinner with android:entries="#array/labels"
In your code - when you need a value do something like this (no you don't have to chain it)
String selectedVal = getResources().getStringArray(R.array.values)[spinner
.getSelectedItemPosition()];
And remember - these 2 arrays have to match each other as far as number slots and positions

Abort, abort! I don't know what got into me but Spinner does not support android:entryValues attribute. That one is actually from ListPreference which does a similar thing (displays list of items in pop-up dialog). For what I need I will have to (alas) use the SpinnerAdapter

Related

How to attach an identifier to spinner item?

I have a spinner, which contains language options and its items are named from string resources depending on system language. I need something like an identifier for these languages attached to each item. For example, I need to know that the user selected "English" as an option (or "en" if we are talking about identifiers) even though when he selected it, he chose "Englisch" (if the user is german). So how can I attach these kinds of identifiers to my array-list items?
I'd suggest making a simple class to hold the required data.
public class Language {
private String identifier;
private String name; //localised name
...
//we want to show the localised data in the spinner
#Override
public String toString() {
return name;
}
Then just make a simple ArrayAdapter and overwrite the onItemSelected function of the spinner or just get the selected item whenever you wish to. Something like:
List listWithLanguages = getLanguages();
ArrayAdapter<Language> adapter = new ArrayAdapter<>(this, R.layout.spinner_item, listWithLanguages);
spinner.setAdapter(adapter)
...
String identifier = (Language) spinner.getSelectedItem().getIdentifier();
You can treat your string-array items as an identifier.
And can use get the selected item from setting up the listener
AdapterView.OnItemSelectedListener
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
You can retrieve the selected item using
// parent.getItemAtPosition(pos)
}
Use a custom adapter that encapsulates the information you care about, then instead of building an adapter that creates a list of localized strings, you create an adapter that creates a list of objects that have the identifier and the localized string together.
Kotlin pseudo code:
val strings = loadLocalizedStringsFromArrayItems()
val identifiers = loadIndentifierStringsFromArrayItems()
val listOfPairs = identifiers.zip(string)
val adapter = ArrayAdapter<List<Pair<String, String>>>(listOfPairs)
val spinner.setAdapter(adapter)
// When clicking on the spinner item:
val pair = adapter.getItemAtPosition(clickedPosition)
val identifier = pair.first
val localizedString = pair.second

The right way to save spinner to sharepreferences

I have a spinner that have 3 values populated from array-list.
I want to save the spinner selected value to shared preferences so it can be loaded back again when the use comes back to the app. What is the correct way to do this (to avoid future problems)
1- Save position of the selection
2- Save the text of the selection
3- Get the position/text of the selection, get the corresponding enum, and save the enum name.
I am leaning towards the 3rd option incase the positions/texts changed in later updates but I am wondering what is the correct way of doing such task
Thank you
Save position (1 variant) and text (2 variant) are bad practice. Because text for your spinner items may will change in the future and their position can be changed.
I think, that you need to create enum or #TypeDef element and save it to sharedPreferences. #TypeDef is more performance but enum is more functionality (if you use Kotlin you can use sealed classes). For this solution just write mapper that can map enum to spinner item.
If you use enum, the best way is to save it name ENUM.name().
Read carefully and understand. Get the post and use at your own understanding.
Declare your spinner and sharedPreferences
public Spinner crimeType;
SharedPreferences sharedPreferencesFirstTime;
//////
sharedPreferencesFirstTime = getPreferences
(Context.MODE_PRIVATE);
String firstTime = getResources().getString(R.string.saved_first_time);
firstTimekey = sharedPreferencesFirstTime.getString
(getString(R.string.saved_first_time),
firstTime);
crimeType = v.findViewById(R.id.crimeType);
Initializing a String Array
String[] plants = new String[]{
"Antisocial behaviour",
"Arson",
"Burglary"
};
Initializing an ArrayAdapter
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(
getActivity(), android.R.layout.simple_spinner_item, plants
);
Sets the layout resource to create the drop down views.
/*
Parameters : resource
the layout resource defining the drop down views
*/
spinnerArrayAdapter.setDropDownViewResource
(android.R.layout.simple_spinner_dropdown_item);
Sets the Adapter used to provide the data which backs this
/*
setAdapter(SpinnerAdapter adapter)
Sets the Adapter used to provide the data which backs this Spinner.
*/
crimeType.setAdapter(spinnerArrayAdapter);
crimeType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
//Get the text content
crime_string= parent.getItemAtPosition(position).toString();
//Get Position of the crime
selectionPosition=
parent.getItemAtPosition(position);
SharedPreferences.Editor editor = sharedPref.edit();
String key2 = crime_string;
editor.putString(getString(R.string.saved_login_key), key2);
editor.apply();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
//Another interface callback
}
});

Better solving method other than if -else

Thanks in advance for any reply. I currently working on android application that let user select several option from 10 spinner type(dropdownlist). But for every onChanged click in spinner, i have to check other spinner item for making a query in cursor. I thinking to use if-else statement to solve it as if-else statement was the easier way to approach the outcome i need but it will consume too many LOC and is not very efficient when modification of code is needed.
Sorry to demand solution from you guy but i cant figure a better method.
It is possible for you to store the last known value of the dropdown into a variable, and then run through those stored variables on click.
var storedVaribles[10];
OnChanged(int i, var changedVariable)
{
storedVariables[i] = changedVariable;
checkWithAllStoredVariables(storedVariables);
}
This is only pseudocode, but it should give you an idea of the direction to head with the solution.
erhaps this type of question would be more appropriate on CodeReview.
You have control of your spinner Adapters. Try to construct your data such that you directly obtain the information that belongs in your query. The basic idea is to have an object like this:
class SpinnerItem {
String displayTitle;
String querySyntax;
public SpinnerItem(String title, string sql) {
displayTitle = title;
querySyntax = sql;
}
}
Then make a SpinnerAdapter that keeps an array or a list of these objects. In getView(), you would bind the displayTitle to a TextView that the user sees. When you want to compose your query, you can call
SpinnerItem item = adapter.getItem(spinner.getSelectedItemPosition());
// use item.querySyntax in your query
As a very simple example, suppose I have a table with contacts, and each contact has either an email or phone number. I want the query to filter on this type based on the selected spinner item. Here's how I might build it:
List<SpinnerItem> items = new ArrayList<SpinnerItem>();
items.add(new SpinnerItem("All", "1"));
items.add(new SpinnerItem("Phone numbers only", "type = 'phone'"));
items.add(new SpinnerItem("Emails only", "type = 'email'"));
MySpinnerAdapter adapter = new MySpinnerAdapter(items);
spinner.setAdapter(adapter);
// later when building query ...
StringBuilder builder = new StringBuilder("select * from table where ");
SpinnerItem item = adapter.getItem(spinner.getSelectedItemPosition());
builder.append(item.querySyntax);
String sql = builder.toString();

Android: value of one spinner depends on value of other spinner

I have a problem on Android Spinner.In my application I created two Spinner on main layout. 'State' Spinner and 'District' Spinner. All the data on Spinner are stored in SQLite database. I want do display list of 'District' on second spinner depending on selection of particular 'State' in the first spinner.
Example: Suppose when I select Karnataka in the first spinner then application first retrieve all the district from SQLite database related to karnataka state and then it display on second Spinner.
For this I do all the database activity correctly means creating two table 'state' and 'district' in which one column in district table is foreign key which is refereed to one of the primary key of 'state table'
db.execSQL("create table "+STATE_TABLE+" ("+
STATE_ID+" integer primary key autoincrement not null, "+
STATE_NAME+" text"+")");
db.execSQL("create table "+DISTRICT_TABLE+" ("+DISTRICT_ID+
" integer primary key autoincrement not null,"+DISTRICT_NAME
+" text,"+STATE_ID+" integer, FOREIGN KEY("
+STATE_ID+") REFERENCES "+STATE_TABLE
+"("+STATE_ID+")"+")");
Now in the Activity Class:
spinnerState = (Spinner)findViewById(R.id.spinner1);
spinnerDistrict = (Spinner)findViewById(R.id.spinner2);
stateList = new ArrayList<String>();
districtList = new ArrayList<String>();
Suppose all the data are all ready stored in database.
Now I need to retrieve all the 'State' data from database and add it in the statelist which is ArrayList.
Cursor stateCursor = database.query(STATE_TABLE, new String[]{STATE_ID, STATE_NAME},
null, null, null, null, STATE_NAME);
stateCursor.moveToFirst();
if(! stateCursor.isAfterLast()){
do{
int id = stateCursor.getInt(0);
String stateName = stateCursor.getString(1);
stateList.add(stateName);
}while(stateCursor.moveToNext());
}
stateCursor.close();
after this I create one ArrayAdapter and put this state list into this.
spinnerState.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, stateList));
Next i put the following code in the activity class:
spinnerState.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View v,
int pos, long id) {
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
Now My problem is here:
How I get the StateId for executing the select query for taking all the district related to particular state in database.
How the adapter will generate for District.
where I put all these code.
Here what I need creating the districtList after getting the value from state Spinner.
Similar Question which asked earlier in this website, what they do:
they already create two adapter for two spinner and then apply setOnItemSelectedListener.
Please Help me because here my mind totally stop working.
I refer lot of book and website but not they even mention these type of problem.
I see a couple of solutions here:
Option 1:
Instead of declaring stateList as an ArrayList<String>, create a custom POJO StateInfo and designate stateList as ArrayList<StateInfo>
public class StateList {
private int id;
private String stateName;
//Constructors, getters and setters
}
Then,
if(! stateCursor.isAfterLast()){
do{
int id = stateCursor.getInt(0);
String stateName = stateCursor.getString(1);
stateList.add(new StateInfo(id, stateName));
}while(stateCursor.moveToNext());
}
Now, you can do this:
public void onItemSelected(AdapterView<?> parent, View v,
int pos, long id) {
int id = stateList.get(pos).getId();
//Use This ID to construct your next SQLite query; and populate the district spinner.
}
If you do this, you will have to create a custom ArrayAdapter and implement the getView() method. Look at the Android docs for how to do this.
Option 2:
Why do you even need the stateID? I suppose you can write a Query to get the districts list given a state Name only. In that case, you can retain the stateList as an ArrayList<String> and you don't even need the StateInfo class at all. Just do this:
public void onItemSelected(AdapterView<?> parent, View v,
int pos, long id) {
String stateName = stateList.get(pos);
//Use this name to construct your next SQLite query; and populate the district spinner.
}
For problem 1:
You just need to keep track of which state user selects into the spinner and according to its position,you have to find its related id.then you can query for district accordingly.obviously you will have to use onItemSelectedListener of that spinner to get position of state selected.
For problem 2:
You need to make a method in helper class which accepts stateId(which you would compute as i said above) and return you according district names in a String array.So in your main activity,in onItemSelectedListener of a state spinner,you will have to grab that string array and prepare a adapter for the same. There,you will have to set adapter to your district spinner.
This will always give you your district spinner updated with what user selects in state array.
For problem 3:
Almost all code would be in onItemSelectedListener of your state spinner only.Just a method to fetch related district names would be in your helper class.

Get the values from one layout to next layout?

I've listed some items in list that extends Activity and the list are listed using Custom Adapter. My question is, this is my xml File I've added some items to this spinner. How can i get the spinner values to next layout. Anyone knows then please tell me? Advance thanks.
I'm not clear on what you're actually asking here, but as a guess there are two possible things you're asking
How to get the currently selected value out of the Spinner
How to set the same value to a spinner in the next layout
1.
Is simple enough
((Spinner)findViewById(R.id.spinner1)).getSelectedItem()
Will return the object selected by your spinner.
Is slightly more complex, you'll need to determine what index in the data supplied corresponds to the result you get from getSelectedItem(), for example if you had an array of Strings then you could search through until you found the index and then set it on the new spinner.
For example:
String[] options = new String[] {"One","Two","Three","Four"};
String val = (String)((Spinner)findViewById(R.id.spinner1)).getSelectedItem();
//.......pass this to a layout/activity etc.........
for (int i=0; i<options.length; i++)
{
if (options[i].equals(test))
{
((Spinner)findViewById(R.id.spinner2).setSelection(i);
break;
}
}
But your best bet would be to try and explain more clearly what you're asking.
first you have to select data from spinner using
spinnerobject.setOnItemSelectedListener(
new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent,
View view, int position, long id)
{
Spinner spinnerobject = (Spinner) findViewById(R.id.Spinner02);
string value = (String)spinnerobj.getSelectedItem();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
// TODO Auto-generated method stub
}
});
then u hava to use intent for sending it to next activity..
Use
Intent.putExtra(..):
intent.putExtra("keyName", "somevalue");
This method is overloaded and takes various types as second argument: int, byte, String, various arrays..
To get the data out use appropriate getXYZExtra(). For String this is:
getStringExtra(String keyName)
First thing :: you can pass value from one activity to second activity not one layout to second
second :: if you need to pass value from one activity to second use
first activity::
activity.putExtra("lastpage", lastscore5);
*here lastpage is key which unique for aplication
second activity::
Intent i1 = getIntent();
var = i1.getIntExtra("lastpage", 1);

Categories

Resources