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.
Related
I display the user data from SQLite database using a custom CursorAdapter.
Each ListView item is actually a layout with many TextViews.
in the CursorAdapter.bindView() method I get database data from the Cursor, and display their modified, prettier versions to the user. Here's what I mean:
public void bindView(View view, Context context, Cursor cursor) {
//get listview items Views
TextView dayTextView = (TextView)view.findViewById(R.id.listview_item_day);
//...
//get data from cursor
int day = cursor.getInt(1);
//...
//display data nicely to the user
String sDay = "Day number " + String.valueOf(day) " was a very nice day";
dayTextView.setText(sDay);
}
I want that when the user long clicks an item (I'll use OnItemLongClickListener for that), the item will be deleted (easy peasy) but I also want to delete the day record from the database.
When the ListView item gets clicked, I have the next parameters supplied to me (in OnItemLongClickListener):
AdapterView<?> adapterView, View view, int position, long id
How do I get to the database record from all these parameters? I could use TextView.getText() and apply some string manipulation methods to the result (remember I added strings to the data before setting it in ListView), but I feel like there's another, more clever way.
You might use a List<Integer> days = new Arraylist<>(); to keep days you are modifying and so the index of the list alway will be same as position and you can get your day content by days.get(position) and get item from your database.
you should define your list out of bindView
I am learning how to create a spinner that loads dropdown from SQLite. I have an UI that consists of a spinner and a table. If user clicks spinner, the table's content will load according to the database based on the selected ID on spinner. If name not selected, it will load all contents in table.. However I can't find the way how to make the table reload based on the ID / name selected on spinner. Anyone can guide me?
The table itself is a joined table, which has following structure:
Table A : ID_Person | Name | Age
Table B : ID_Account | ID_Person | Amount
Spinner shows Person's name. Meanwhile the table will show the following structure:
Name | Age | Amount
My code for spinner:
public List<String> getAllDealers()
{
List<String> contentdealer = new ArrayList<String>();
// Select All Query
String selectQuery = "SELECT * FROM " +Dealer_TABLE;
cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
contentdealer.add(cursor.getString(1));
} while (cursor.moveToNext());
}
// closing connection
return contentdealer;
}
Here is how I build my Table for looping:
Cursor c = in.getViewInfo(); //method in db consists of query that i want table show
int rows = c.getCount();
int cols = c.getColumnCount();
c.moveToFirst();
// outer for loop
for (int i = 0; i < rows; i++)
{
//looping all rows based .getCount()
//looping all columns
for (int j = 0; j < cols; j++)
{
}
}
in.close();
See a similar but not exact same answer here
https://stackoverflow.com/a/11920785/1116836
I believe what you want is
spinner.setOnItemSelectedListener(new OnItemSelectedListener()
{
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id)
{
Toast.makeText(context, "item selected, load some sql", Toast.LENGTH_LONG).show();
// position should match the index of the array in the items list you used for which item is selected, or here you could do
String selected = spinner.getSelectedItem().toString();
// or
String anotherway = spinner.getItemAtPosition(position).toString();
if (selected.equals("what ever the option was")) {
}
}
#Override
public void onNothingSelected(AdapterView<?> parentView)
{
Toast.makeText(context, "nothing selected, load some sql", Toast.LENGTH_LONG).show();
}
});
likely to be able to select nothing, you will have to insert a view with no text, and allow that to be selected.
onNothinSelected is more for when a list is modified, or the currently selected item becomes unselected, e.g. when it is in in between selections it may call this method.
Callback method to be invoked when the selection disappears from this
view. The selection can disappear for instance when touch is activated
or when the adapter becomes empty.
So basically, when a new item is selected, call a method that loads some sql rows, clear your table and then display the new data.
EDIT: for comment
What you are trying to do is an event drive function. When someone selects a new option in the spinner, it is an event. You listen for this event by, as I showed above, implementing the OnItemSelectedListener().
One you implement this, you can find out what item is selected, as soon as it happens. Once a new item is selected, you need to determine what that item means you should do.
Once you have figured that out, run your SQL statement and query your database, load the data, set it in the adapter and then the user will see it.
If you are using a ListView, which you should be, then you need to clear the adapter to the ListView, and then add the new items.
You need to research ArrayAdapter, BaseAdapter, ViewHolder pattern, and ListView's.
A quick google search will have you up and running in no time.
I'm starting to learn how to work with SQL database and ContentProviders. I'm developing an app which consists on a ListActivity where I've got some items. I know how to insert a new element on the database, but the problem is...
When I want to update or delete one element, I long click on it and on the ContextMenu I select one of booth options.
These are the methods to update/delete a item via Content Provider:
public void updateTravel(String city, String country, int year, String note, String id {
ContentValues updateValues = new ContentValues();
updateValues.put(Travels.CITY, city);
updateValues.put(Travels.COUNTRY, country);
updateValues.put(Travels.YEAR, year);
updateValues.put(Travels.NOTE, note);
getContentResolver().update(TravelsProvider.CONTENT_URI, updateValues, Travels._ID+"="+id, null);
}
private void deleteTravel(String id){
getContentResolver().delete(TravelsProvider.CONTENT_URI, Travels._ID+"="+id, null);
I'm not sure if this is correct, but I see that I have to pass the ID of the element to update or delete it. My doubt is, how I get one item's ID?
Normally we will do somthing like this
public class DataHolder
{
private int id;
private String data;
// Getters and setters for the insatance variables
}
For each listItem we will hold an object of DataHolder then store this in a ArrayList<DataHolder>
Then on OnItemClick you can get the position of elemnt and get the object from ArrayList and get the id and use it.
Don't forget to remove from list after removal from db
So my situation is this. I have two tables. A main table where data is added using a form, this form has a spinner which is powered from the second table (this part is working correctly). I then want the selected item in the spinner to be stored in a foreignkey field in the main table.
I have been using the following code:
private Spinner mSpinner;
mSpinner = (Spinner) findViewById(R.id.spinCat);
and in my populate fields method I have the following:
mSpinner.getSelectedItem();
but this stores something like "android.database.sqlite.SQLiteCursor#43e5be60" in to the database rather than the name.
If anyone can offer some help it would be great, this has been bothering me for some days now and has halted development somewhat. If you need to see more code, then please don't hesitate to ask.
Any help is much appreciated.
EDIT: new code:
mSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View vw,
int pos, long id) {
LinearLayout rowll = (LinearLayout) vw;
TextView test = (TextView) rowll.getChildAt(0);
Toast t = Toast.makeText(parent.getContext(), test
.getText().toString(), Toast.LENGTH_SHORT);
t.show();
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// Do nothing..
}
});
getSelectedItem returns an Object (which is what your output looks a lot like).
Did you try simply calling toString like this?
mSpinner.getSelectedItem().toString();
I personally just set a variable in the onItemSelected listener, but this should work too. What I use is:
#Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
myIP = parent.getItemAtPosition(position).toString();
}
Variable is then continuously updated and I just add it to the DB when I connect to the IP in question.
Cursor data extraction:
while (cursor.moveToNext()) {
ipList.add(cursor.getString(1));
}
getString(int columnIndex) does: Returns the value of the requested column as a String.
http://developer.android.com/reference/android/database/Cursor.html
Don't use .getChildAt(), use .getItemAtPositon(). See how the code does it at http://developer.android.com/resources/tutorials/views/hello-spinner.html.
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