• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Apps Dynamic Spinner with Database

What layout are you specifying in the cursor adapter? Be sure that is setup to display properly.

Are you still having the error regarding opening the database?
 
The layout I am specifying is the specific spinner for each column.
I have currently fixed the problem.

I changed this:
SimpleCursorAdapter scaType = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, vType,new String [] {DataBaseHelper.POWERSPORTS_TYPE},new int[]{R.id.textView01});

To this:
SimpleCursorAdapter scaType = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, vType,new String [] {DataBaseHelper.POWERSPORTS_TYPE},new int[]{android.R.id.text1});


As for the errors upon opening the database, I have fixed the problem.

What I need to work on now is the SelectionArgs with my queries.
And onItemSelected stuff
 
If you don't mind. Could it be possible to get a sample of your database, just so I can see how to have your id's? Or, do you have multiple tables or just one with all of your data?

It seems that with onItemSelected, it would be easy to reference an id to bring up matching id's on a different table.
 
I have multiple tables. I had to do a little normalization to get the database to work more efficiently. I originally wanted just one table with all the records but that ended up slowing down the app.

You can download the file from the link below. That is the link used in the current app to download my current database. It has an .mp3 extension but it is actually a database that can be saved off and opened with SQLite Browser. That is a "hack" I had to use because older versions of Android weren't able to download files over 5MB unless it was an mp3. I didn't include the database file in the install because around the time of Android version 1.6 and 2.0, disk space was a lot smaller and more of an issue than it is now.

http://www.estmpgapp.com/revisedepaestimates.mp3
 
So what I can tell from your database is that you have a different table for each of the multiple options you give the user to choose on your first screen layout. I also noticed that you do not use ranges of years of a model of a vehicle in your database. You have each year of a model separately. Is this a limitation within SQLite?

I know I am asking a lot but, how are you setting your arguments for each of your queries. I am sure I am doing them incorrectly because no data is shown within my spinners.

What I want is when I select my first choice in the first spinner is the Type of the vehicle I am looking for. Once that happens I want the second spinner to populate with ONLY the choices that fit with the Type I chose in the first spinner.
 
No, that isn't a limitation of SQLite. SQL queries can have multiple variables so you should be able to select multiple years, makes, models, etc.

From what you're explaining, your first query for Type should include all Types. The second query would then require the value of the first spinner after it has been selected and use it in the where condition. The third query would then require the values from the first and second spinner in its where condition. And so on for however many selections you present to the user.

My code is a little different than your app because I use a CursorLoader and create the query as a String. You would just need to update the queries in your database helper to require the arguments you are going to pass from the prior spinners and include them in the where condition.

So what I can tell from your database is that you have a different table for each of the multiple options you give the user to choose on your first screen layout. I also noticed that you do not use ranges of years of a model of a vehicle in your database. You have each year of a model separately. Is this a limitation within SQLite?

I know I am asking a lot but, how are you setting your arguments for each of your queries. I am sure I am doing them incorrectly because no data is shown within my spinners.

What I want is when I select my first choice in the first spinner is the Type of the vehicle I am looking for. Once that happens I want the second spinner to populate with ONLY the choices that fit with the Type I chose in the first spinner.
 
I have had my where arguments set, my only issue is passing the selected value from the previous spinner(s) to get the right data. Without passing the previous spinner(s) value, the 2nd, 3rd, and 4th spinner do not populate.

Here are my queries with the where Args.
[HIGH]
static String MakeWhere = "POWERSPORTS_TYPE=?";
static String YearWhere = "POWERSPORTS_TYPE=? AND POWERSPORTS_MAKE=?";
static String ModelWhere = "POWERSPORTS_TYPE=? AND POWERSPORTS_MAKE=? AND POWERSPORTS_YEARS=?";


public static Cursor getPowersportsType(){

return myDataBase.query(POWERSPORTS_TABLE, new String [] {POWERSPORTS_ID, POWERSPORTS_TYPE}, null, null, POWERSPORTS_TYPE, null, null);
}

public static Cursor getPowersportsMake(){

return myDataBase.query(POWERSPORTS_TABLE, new String [] {POWERSPORTS_ID, POWERSPORTS_MAKE}, MakeWhere, null, POWERSPORTS_MAKE, null, null);
}

public static Cursor getPowersportsYear(){

return myDataBase.query(POWERSPORTS_TABLE, new String [] {POWERSPORTS_ID, POWERSPORTS_YEARS}, YearWhere, null, POWERSPORTS_YEARS, null, null);
}

public static Cursor getPowersportsModel(){

return myDataBase.query(POWERSPORTS_TABLE, new String [] {POWERSPORTS_ID, POWERSPORTS_MODEL}, ModelWhere, null, POWERSPORTS_MODEL, null, null)[/HIGH]
 
I don't think you're going to be able to do it that way.

For your getPowersportsMake you'd want to do it like this:

[HIGH]
public static Cursor getPowersportsMake(String s){
return myDataBase.query(POWERSPORTS_TABLE,
new String [] {POWERSPORTS_ID, POWERSPORTS_MAKE},
POWERSPORTS_TYPE+"='"+s+"'",
null,
POWERSPORTS_MAKE,
null,
null);
}
[/HIGH]

Then in your main activity you would need to get the string value of the selection on the first spinner and pass it when creating the cursor. Like this:

vMake = (Cursor)DataBaseHelper.getPowersportsMake(string);
 
When implementing your code, it gives an error that string in vMake = (Cursor)DataBaseHelper.getPowersportsMake(string); cannot be resolved to a variable
 
You'll need to create the "string" and assign it the value from the first spinner after it has been selected.

When implementing your code, it gives an error that string in vMake = (Cursor)DataBaseHelper.getPowersportsMake(string); cannot be resolved to a variable
 
Okay, I am having a bit of problems. I am trying to have an onItemSelectedListener for each of my cursors and I am having issues of having the first spinner selection being sent to a variable. I am not sure how I reference the variable into my getPowersportsMake() query.

I thought this would work, but it still gives me cannot be resolved to a variable.

[HIGH]//POWERSPORTS TYPE Cursor
vType = (Cursor) DataBaseHelper.getPowersportsType();
this.startManagingCursor(vType);

SimpleCursorAdapter scaType = new SimpleCursorAdapter(this,
android.R.layout.simple_spinner_item,
vType,
new String [] {DataBaseHelper.POWERSPORTS_TYPE},
new int[] {android.R.id.text1});

scaType.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
vTypeSpinner = (Spinner) findViewById(R.id.typeSpinner);
vTypeSpinner.setAdapter(scaType);

vTypeSpinner.setOnItemSelectedListener(new OnItemSelectedListener(){

@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub

}

@Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
// TODO Auto-generated method stub
String typeSelection = vTypeSpinner.getSelectedItem().toString();
}
});;

//POWERSPORTS MAKE Cursor
vMake = (Cursor) DataBaseHelper.getPowersportsMake(typeSelection);
this.startManagingCursor(vMake);

SimpleCursorAdapter scaMake = new SimpleCursorAdapter(this,
android.R.layout.simple_spinner_item,
vMake,
new String [] {DataBaseHelper.POWERSPORTS_MAKE},
new int[]{android.R.id.text1});

scaMake.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
vMakeSpinner = (Spinner) findViewById(R.id.makeSpinner);
vMakeSpinner.setAdapter(scaMake);[/HIGH]

[HIGH]public static Cursor getPowersportsMake(String typeSelection){
return myDataBase.query(POWERSPORTS_TABLE,
new String [] {POWERSPORTS_ID, POWERSPORTS_MAKE},
POWERSPORTS_TYPE+"='"+typeSelection+"'",
null,
null,
null,
null);
} [/HIGH]
 
This is where I am. I am now passing values to my second spinner. But only the first selection works.
I tried having an onItemSelected on my code to pass the string value but having the onItemSelected makes the string not be able to be passed to my next cursor because for some reason it is passing null (checked with a toast of the variable being passed).

I appreciate the help as always.
 
Update:

I am now passing the correct string values through all of my spinners.
The issue I am facing now is passing the multiple values to my DataBaseHelper activity. I am trying to use intents on each listener for the string values but as of right now, I am having no luck getting it to work.
 
Glad to see your making progress. Haven't been able to check on this lately.

Passing the values to the DataBaseHelper?? As long as you setup the methods to require a string or multiple strings, you should be able to pass them to the methods. How are you getting the string values and how are you executing the databasehelper methods from your activity?
 
Here is the code for receiving the string values, it is basically the same for all of my spinners.

[HIGH]vTypeSpinner.setOnItemSelectedListener(new OnItemSelectedListener(){

public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int
pos, long id) {
if(pos!=0){

Cursor vTypeChose = (Cursor)(vTypeSpinner.getSelectedItem());
if (vTypeChose != null) {
String typePicked = vTypeChose.getString(
vTypeChose.getColumnIndex(DataBaseHelper.POWERSPORTS_TYPE));
vMake = (Cursor) DataBaseHelper.getPowersportsMake(typePicked);
scaMake.changeCursor(vMake);
Log.e("SpinnerTest", "Type Selected: " + vType.getString(vType.getColumnIndex(DataBaseHelper.POWERSPORTS_TYPE)));
// Toast.makeText(getBaseContext(), "Selected: " + typePicked,Toast.LENGTH_LONG ).show();

}
}
}[/HIGH]

And here is on of my databasehelper methods:

[HIGH]public static Cursor getPowersportsMake(String typePicked){
return myDataBase.query(POWERSPORTS_TABLE,
new String [] {POWERSPORTS_ID, POWERSPORTS_MAKE},
POWERSPORTS_TYPE+"='"+typePicked+"'",
null,
POWERSPORTS_MAKE,
null,
null);
}[/HIGH]

It's having the multiple string values on my other DataBaseHelper methods that is my issue, right now only one string variable is being used in my queries.

I just noticed something within my spinners... For some reason I cannot select the very first value in my spinner. EX: I have ATV in the #1 position in my spinner and it will not populate the 2nd spinner with the ATV Manufacturers. But this happens in every #1 position of my spinners, without the OnItemSelectedListeners, the first value works fine, just one time though because of the OnItemSelectedListeners being toggled out.
 
Okay, I now have all of my variables being passed to my queries and all the spinners work.

It's the issue that the first values in my spinners are not being seen for some odd reason.
 
Update: 12/26/13

I am now having all of my spinners populate with the first position items in the spinner working. I am so happy.

Trying to work on that the spinners only update when I select an item, not when they populate.
 
Nice job! All the work you put in with the database and cursors will make any future projects a lot easier.

I was never able to figure out a solution for only having the first spinner populate when the activity starts. Good luck with it.


Update: 12/26/13

I am now having all of my spinners populate with the first position items in the spinner working. I am so happy.

Trying to work on that the spinners only update when I select an item, not when they populate.
 
It seems by digging within StackOverflow, users have found ways of doing it by creating a custom spinner class. My only issue with that is for some reason I am getting errors inflating the custom class.
 
An example of someone's custom spinner class:

[HIGH]public class NDSpinner extends Spinner {

public NDSpinner(Context context)
{ super(context); }

public NDSpinner(Context context, AttributeSet attrs)
{ super(context, attrs); }

public NDSpinner(Context context, AttributeSet attrs, int defStyle)
{ super(context, attrs, defStyle); }


private void ignoreOldSelectionByReflection() {
try {
Class<?> c = this.getClass().getSuperclass().getSuperclass().getSuperclass();
Field reqField = c.getDeclaredField("mOldSelectedPosition");
reqField.setAccessible(true);
reqField.setInt(this, -1);
} catch (Exception e) {
Log.d("Exception Private", "ex", e);
// TODO: handle exception
}
}

@Override
public void setSelection(int position, boolean animate)
{
boolean sameSelected = position == getSelectedItemPosition();
ignoreOldSelectionByReflection();
super.setSelection(position, animate);
if (sameSelected) {
// Spinner does not call the OnItemSelectedListener if the same item is selected, so do it manually now
getOnItemSelectedListener().onItemSelected(this, getSelectedView(), position, getSelectedItemId());


}
}
@Override
public void setSelection(int position) {
ignoreOldSelectionByReflection();
super.setSelection(position);
}

}[/HIGH]

But I get: [HIGH]android.widget.Spinner cannot be cast to com.example.productguide.lithiumbatteryguide.PowersportsEquivalent$NDSpinner[/HIGH] in my logcat
 
Back
Top Bottom