Android : how to set DropDown View Resource for Spinner? - java

I wrote a code for Spinner to bind array of USA States with Spinner in Android. But the problem is it shows reference type data in Spinner item, see the pic
I add android.R.layout.simple_spinner_dropdown_item but not know that what to add in layout. I checked many exemples on google and they add simple_spinner_dropdown_item but i could not find that what to add in layout. below is output and code. I want to show states in list instead of this junky data.
Spinner spStates = new Spinner(this);
spStates.setLayoutParams(new LayoutParams(screenWidth, LayoutParams.WRAP_CONTENT));
final USAStates states[] = new USAStates[51];
states[0] = new USAStates("Alabama", "AL");
states[1] = new USAStates("Alaska", "AK");
states[2] = new USAStates("Arizona", "AZ");
ArrayAdapter<USAStates> adapter = new ArrayAdapter<USAStates>(this, android.R.layout.simple_spinner_item, states);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spStates.setAdapter(adapter);
spStates.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
USAStates d = states[position];
Toast.makeText(getApplicationContext(), d.getStateAbrivation(), Toast.LENGTH_LONG).show();
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
public class USAStates {
private String _Statename;
private String _StateAbrivation;
public USAStates(String pStatename, String pStateAbrivation) {
Statename(pStatename);
StateAbrivation(pStateAbrivation);
}
public void Statename(String pStatename) {
_Statename = pStatename;
}
public void StateAbrivation(String pStateAbrivation) {
_StateAbrivation = pStateAbrivation;
}
public String getStatename() {
return _Statename;
}
public String getStateAbrivation() {
return _StateAbrivation;
}
}

Not sure, just doing this off the top of my head but, in your USAState class override your toString method.As is it maybe that the adapter is using the default toString() hence your weird text displaying (which I presume is the class name of the USAStates class)
for example
#Override
public String toString(){
return _Statename
}

I originally accepted the toString() answer but have since found that this doesn't appear to be right.
I had an ActionBar with spinner/drop down list and my adapter items were rendering with String.toString() value instead of of the title I set in the custom adapter. Adding toString() did fix initially until I tried to set a compound drawable in the same layout.
I needed to override getDropDownView as well as getViewin my adapter.
Having to override toString() is symptomatic that you haven't overridden the right methods in your adapter.
When overriding getDropDownView having to override toString() is no longer required and everything works as expected.
And the answer on the following post is a great way to implement by using the super method:
alternating colors of spinner items

Related

Get spinner selected item and passing data

What I want to do is set the texts depends on the spinner item selected by users. But there is nothing that showed up when running the app and there is no errors either. Did I miss any steps that cause the outcome didn't come out?? I'm still new to android.
UPDATE:
I forgot to say that I have three different spinners depending on which button users liked in 1st activity so I think its because I only declare for the spinner's item but didn't declare which spinner is "Japan" referring to.
So this is my code for 1st activity, I will just put only one first :
btnAsia.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(),MainActivity2.class);
intent.putExtra("continent", "asia");
startActivity(intent);
}
});
This is the string array in strings.xml:
<string-array name="asia">
<item>Japan</item>
<item>Thailand</item>
<item>Vietnam</item>
<item>South Korea</item>
</string-array>
and this is the code in 2nd activity:
private void DestinationSpinner()
{
Bundle bundle=getIntent().getExtras();
if(bundle!=null) {
String continent = bundle.getString("continent");
switch (continent) {
case "asia":
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(MainActivity2.this, R.array.asia, android.R.layout.simple_spinner_item); // Create an ArrayAdapter using the string array and a default spinner layout
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // Specify the layout to use when the list of choices appears
spinnerDestination.setAdapter(adapter); // Apply the adapter to the spinner
break; }
and lastly this is the code for retrieve selected item from spinner:
public void AvailableAirlines()
{
spinnerDestination.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String selected=spinnerDestination.getItemAtPosition(position).toString();
if (continent.equals("asia") && selected.equals("Japan"))
{
availableAirlines.setText("Available airports");
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
and I also want to pass the keyidentifer from 1st activity to 2nd activity but I tried using getExtras and it didn't work maybe I do it wrongly or what.
I think the issue is this line if(selected=="Japan")
In Java you will need to use equals instead of the == operator.
The == checks if the two pointers are pointing to the same memory location.
Equals will compare their content.

Android ArrayList: Store Multiple Values Into A Profile

I have multiple variables, we'll call them varA, varB, varC, and varD. When a button is pressed these 4 variables are to be stored in an ArrayList, together. This creates a single entry which can be viewed by variable varA. All the entries can be viewed in a ListView which is done through an ArrayAdapter.
onCreate
ArrayAdapter<String> profileAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, arrayList);
profileList.setAdapter(profileAdapter);
When a button is pressed
// Add data to a new profile in #+id/profileList ListView
ArrayList<String> arrayList= new ArrayList<>();
arrayList.add(varA);
System.out.println("varA's");
System.out.println(arrayList);
((ArrayAdapter)profileList.getAdapter()).notifyDataSetChanged();
Layout
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/overviewLayout">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/profileList"/>
</RelativeLayout>
I am having issues with the ListView showing the items that were added. Also, I was trying to use TinyDB to store these items so they can be referenced later since that ArrayList used on button press is just temporary. I also I'm having trouble figuring out how to set this up so that each time the button is pressed those 4 vars will stay together in a "profile" so they don't get mixed up with some other data that might be added later.
To avoid repeated values from getting stored check if it already exists :
if(!arrayList.contains(varA)){
arrayList.add(varA);
}
For listview updation problem ,use notifyItemInserted(position) instead of notifyDataSetChanged()
yourAdapter.notifyItemInserted(position);
As I understand, you want to display a list which contains 4 datas in one entry and showing just the first of them.
If it is, you could create a custom Model, it will be easier. This will store your datas in one object:
ProfileModel
|
|-- varA
|-- varB
|-- varC
'-- varD
Your custom model could look like something like this:
public class ProfileModel {
private String varA;
private float varB;
private int varC;
private String varD;
// getters
...
// setters
...
public ProfileModel() { }
}
Initialize the list of profiles at start:
ArrayList<ProfileModel> list = new ArrayList<>();
To populate the main list do as follows:
// create a list of object to the datas
ProfileModel profile = new ProfileModel();
profile.setVarA(varA);
profile.setVarB(varB);
profile.setVarC(varC);
profile.setVarD(varD);
// then fill the first list
list.add(profile);
Since you want to fill the adapter with other datas than a simple String but a custom model, I'd prefer to use a custom adapter. It's not that hard to create one, and because sometimes, you maybe want a different behavior on an update, I'd also prefer to use a custom notifyDataSetChanged method.
So, here's a simple adapter with the same layout as the one you used:
public class ProfileAdapter extends BaseAdapter {
private Context context;
private ArrayList<ProfileModel> listProfiles;
public ProfileAdapter(Context context, ArrayList<ProfileModel> listProfiles) {
super();
this.context = context;
this.listProfiles = listProfiles;
}
private class ViewHolder {
private TextView textVarA;
}
#Override
public int getCount() {
return listProfiles != null ? listProfiles.size() : 0;
}
#Override
public Object getItem(int i) {
return listProfiles.get(i); // will return the profile model from position
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int position, View view, ViewGroup viewGroup) {
ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = LayoutInflater.from(context)
.inflate(android.R.layout.simple_list_item_1, null);
holder.textVarA = (TextView) view.findViewById(android.R.id.text1);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
ProfileModel profile = listProfiles.get(i);
holder.textVarA.setText(profile.getVarA()); // get varA value
return view;
}
public void addEntry(ProfileModel newEntry) {
listProfiles.add(newEntry);
this.notifyDataSetChanged();
}
}
Then, you can set the adapter as follows:
ProfileAdapter profileAdapter = new ProfileAdapter(this, list);
profileList.setAdapter(profileAdapter);
To update this adapter:
// create a list of object to the datas
ProfileModel profile = new ProfileModel();
profile.setVarA(varA);
profile.setVarB(varB);
profile.setVarC(varC);
profile.setVarD(varD);
profileAdapter.addEntry(profile); // this will call notifyDataSetChanged
Finally, I'm not very aware about TinyDB, but I saw it's using some JSON file to store data. So you could create a method to convert your datas to JSONArray which its name is varA and has values varB, varC, varD. There is many examples how to convert datas to JSON (as using Gson to convert your model to a JSON format).
Hope this will be useful.

findViewById not working in static function

I found error in findViewById in static function.
my function is--
public static void onYearSelect() {
Spinner yearSelector;
String yearName;
yearSelector = (Spinner) findViewById(R.id.year_submit);
yearName = yearSelector.getSelectedItem().toString();
}
is there any way to solve this error!
can i store value of Spinner in yearName as String
You need to add view inside function as parameter.
public static void onYearSelect(View view) {
Spinner yearSelector;
yearSelector = (Spinner) view.findViewById(R.id.year_submit);
yearName = yearSelector.getSelectedItem().toString();
}
The view which contains your layout data.
When you call that function add onYearSelect(rootView) here rootView have the layout view.
EDIT 1:
What is View here ?
A View in Android is a widget that displays something. Buttons, listviews, imageviews, etc. are all subclasses of View. When you say "change view" I assume you mean change the layout by using setContentView(). This usually only needs to be done once per activity. An Activity is basically what you are referring to as a screen.
You can read more here.
Set setOnItemSelectedListener on spinner object and inside onItemSelected() you can set value of yearName. Like below,
yearSelector.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
String yearName = parentView.getItemAtPosition(position).toString()
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
// your code here
}});

Spinner in Custom Function for Android with java

I am confused about calling the spinner widget through a custom function. I am create an app in which I use spinner 20-35 times a spinner widget in single layout or activity. So for this i want to avoid the spinner code repetition again and again. i am creating a method for this i add the items to the spinner but i want to pass item value on select to other activity which bind to that class
Here is my code
Spin_tester.class
public class Spin_tester {
public String result;
public Context ctx;
public Spin_tester(Spinner spinner, final ArrayList<String> arraylist, final Context ctx , final String value) {
this.ctx= ctx;
ArrayAdapter<String> adpts =
new ArrayAdapter<String>(ctx, android.R.layout.simple_dropdown_item_1line,arraylist);
spinner.setAdapter(adpts);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
result = arraylist.get(position);
value = result ; // This is not working
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}
Test_Activity.class
public class Test_Activity extends AppCompatActivity {
ArrayList<String> data_list = new ArrayList<>();
Spinner spins;
String value;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
spins = (Spinner)findViewById(R.id.spinner);
data_list.add("1");
data_list.add("2");
data_list.add("3");
data_list.add("4");
Spin_tester asd = new Spin_tester(spins,data_list,this,value);
TextView txt = (TextView)findViewById(R.id.textView17);
}
}
Please help
Thanks in advance
Java is a pass-by-value language, not pass-by-reference. What this means is that setting value in setOnItemSelectedListener will only change value within that method — the result won't be passed back anywhere.
I see that you've place the result in result. That is where the calling program will find the answer.
Remove all instances of value from Spin_tester and Test_Activity and then have your main activity get the result from asd.result
I'm going to get a little meta at this point: I've only answered the question you actually asked, but this code is wrong on so many levels that you're never going to get it to work. I strongly suggest you work your way through the examples and tutorials in the documentation before you try to proceed any further.

Pass String variables by reference to setOnItemSelectedListener of multiple Spinners

OK, I've read around and see that Java only passes by value, not by reference so I don't know how to accomplish this.
I've 6 Spinners in an Android Activity that are populated with different SQLite queries.
The code to populate each Spinner and set the OnItemSelectedListener is very similiar so I was hoping to refactor to one method and call it 6 times with each Spinner ID and Sqlite query.
How do I get the Spinner onItemSelectedListener to change the right instance member on each different Spinner?
public void fillSpinner(String spinner_name, final String field_name) {
// This finds the Spinner ID passed into the method with spinner_name
// from the Resources file. e.g. spinner1
int resID = getResources().getIdentifier(spinner_name, "id",
getPackageName());
Spinner s = (Spinner) findViewById(resID);
final Cursor cMonth;
// This gets the data to populate the spinner, e.g. if field_name was
// strength = SELECT _id, strength FROM cigars GROUP BY strength
cMonth = dbHelper.fetchSpinnerFilters(field_name);
startManagingCursor(cMonth);
String[] from = new String[] { field_name };
int[] to = new int[] { android.R.id.text1 };
SimpleCursorAdapter months = new SimpleCursorAdapter(this,
android.R.layout.simple_spinner_item, cMonth, from, to);
months.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s.setAdapter(months);
// This is setting the Spinner Item Selected Listener Callback, where
// all the problems happen
s.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
Cursor theCursor = (Cursor) parent.getSelectedItem();
// This is the problem area.
object_reference_to_clas_member_of_field_name = theCursor
.getString(theCursor.getColumnIndex(field_name));
}
public void onNothingSelected(AdapterView<?> parent) {
// showToast("Spinner1: unselected");
}
});
}
You call this method like this fillSpinner("spinner1","strength");.
It finds the spinner with id spinner1 and queries the database for the strength field. field_name, which is strength in this example had to be declared a final variable to be used in the onItemSelectedListener or I'd get the error Cannot refer to a non-final variable field_name inside an inner class defined in a different method.
But how do I get the onItemSelectedListener to change the value of a different instance member when each different Spinner is used? This is the all important line of code:
object_reference_to_clas_member_of_field_name = theCursor .getString(theCursor.getColumnIndex(field_name));
I can't use a final String as the variable will obviously change when the user selects a different value. I've read around a good bit and am stumped to a solution. I can just copy and paste this code 6 times and forget about refactoring but I'd really like to know the elegant solution. Post a comment if you don't understand my question, I'm not sure if I explaned myself well.
You can do it, by passing additional class as parameter of fillSpinner method:
A. Create interface
public interface OnSpinnerValueSelected {
void onValueSelected(String selectedValue);
}
B. Change your method a bit:
public void fillSpinner(String spinner_name, final String field_name,
final OnSpinnerValueSelected valueChangeListener) {
// Prepare spinner
s.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
Cursor theCursor = (Cursor) parent.getSelectedItem();
valueChangeListener.onValueSelected(theCursor
.getString(theCursor.getColumnIndex(field_name)));
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
C. provide listener:
fillSpinner("spinner1","strength", new OnSpinnerValueSelected() {
public void onValueSelected(String selectedValue) {
yourObject.setField(selectedValue);
}
});
Refactor your listener to a new "class". Initialize with the right arguments/instances as required so that the repeated "code" is reusuable.
Right, this is how I managed it but I'm still open to new suggestions for an accepted answer and I also created a bounty.
I didn't create a new class like panzerschreck suggested so I'm posting this as a new answer to my own question. Bit of a hack but I just created an if..then..else statement in the listener to check what spinner was selected and then set a different instance member.
s.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
Cursor theCursor = (Cursor) parent.getSelectedItem();
if (field_name.equalsIgnoreCase("strength")) {
strength=theCursor.getString(theCursor.getColumnIndex(field_name));
} else if (field_name.equalsIgnoreCase("ring")) {
ring_gauge=theCursor.getString(theCursor.getColumnIndex(field_name));
} else if (field_name.equalsIgnoreCase("country")) {
country=theCursor.getString(theCursor.getColumnIndex(field_name));
} else if (field_name.equalsIgnoreCase("wrapper")) {
wrapper=theCursor.getString(theCursor.getColumnIndex(field_name));
} else if (field_name.equalsIgnoreCase("length")) {
length=theCursor.getString(theCursor.getColumnIndex(field_name));
} else if (field_name.equalsIgnoreCase("price")) {
price=theCursor.getString(theCursor.getColumnIndex(field_name));
}
// showToast(category);
}
public void onNothingSelected(AdapterView<?> parent) {
// showToast("Spinner2: unselected");
}
});
Here are the class members
private String strength,ring_gauge,country,wrapper,length,price;
Bit of hack but without Java allowing objects to be really passed by reference, it's all I could do.

Categories

Resources