Newbie question. I'm using a SimleCursorAdapter to populate a spinner from an SQLite table, as shown in the Android dev docs:
Spinner list=(Spinner)findViewById(R.id.cboModel);
SimpleCursorAdapter ModelAdapter = new SimpleCursorAdapter(this,
android.R.layout.simple_spinner_item, model,
new String[] {"Drug"},
new int[] {android.R.id.text1});
ModelAdapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
list.setAdapter(ModelAdapter);
list.setOnItemSelectedListener(onModelSelect);
I've set up a listener, but I can't figure out how to get the selected item text, it pulls up the SQLiteCursor, not the actual text in the spinner.
private AdapterView.OnItemSelectedListener
onModelSelect= new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?>
parent, View view, int position, long id) {
ModelName = parent.getSelectedItem().toString();
android.util.Log.w("OnItemSelect.cboModel", ModelName);
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
};
Google turns up the question on several message boards, but no answers, so it appears to be a common newbie question. It may be painfully obvious to some, but if you could point me in the right direction I would appreciate it. Thank you.
Since the selected item is a Cursor, you can easily get the value by calling getString with the index of the column in the original database query that you used to populate the Spinner.
String spinnerString = null;
Cursor cc = (Cursor)(yourSpinner.getSelectedItem());
if (cc != null) {
spinnerString = cc.getString(
cc.getColumnIndex("Drug"));
}
This technique definitely works when the Spinner is populated from the database. I have not tried it with a resource array.
Figured it out... get the id, then make a DB query:
String id_string = String.valueOf(id);
thismodel=Pkmodel.getById(id_string, dbModel);
ModelName=thismodel.getDrug();
Related
In my app, I have a few AutoCompleteTextView widgets that use an ArrayAdapter.
private List<String> adapterList = new ArrayList<String>();
ArrayAdapter<String> dropdownAdapter;
dropdownAdapter = new ArrayAdapter<>(getContext(), R.layout.simple_dropdown_item, adapterList);
autoCompleteTextView.setAdapter(dropdownAdapter);
It works beautifully. As I type into the View, I get words-starting-with results in the dropdown.
I want to do this with another AutoCompleteTextView, but this time using a SimpleCursorAdapter.
nameSearchCursor = dbHelper.getChecklistTabDataByChecklistId(outingId, checklistId, nameColumn);
NameSearch = root.findViewById(R.id.SearchNames);
String[] nsColumns = new String[]{nameColumn};
int[] nsTo = new int[]{R.id.simpleDropdownItem};
nameSearchCursorAdapter = new SimpleCursorAdapter(getContext(), R.layout.simple_dropdown_item,
nameSearchCursor, nsColumns, nsTo, 0);
NameSearch.setAdapter(nameSearchCursorAdapter);
If I start typing in this new View, the dropdown appears and shows the entire list, and nothing changes as I type. No filtering occurs. What do I need to do differently (and perhaps why) to get a CursorAdapter to work with this View that I didn't need to do when using an ArrayAdapter. I have searched this site and read the Developer Docs and there must be something I just don't get. Please enlighten me.
This site allowed me to answer this question: http://www.outofwhatbox.com/blog/2010/11/android-simpler-autocompletetextview-with-simplecursoradapter/
Here is my completed code:
private void setUpNameSearch() {
// Get AutoCompleteTextView
nameSearchView = root.findViewById(R.id.SearchNames);
// Define from/to info
final String[] nsColumns = new String[]{nameColumn};
final int[] nsTo = new int[]{R.id.simpleDropdownItem};
// Create adapter. Cursor set in setFilterQueryProvider() below.
nameSearchCursorAdapter = new SimpleCursorAdapter(getContext(), R.layout.simple_dropdown_item,
null, nsColumns, nsTo, 0);
// Set adapter on view.
nameSearchView.setAdapter(nameSearchCursorAdapter);
// OnItemClickListener - User selected value from DropDown
nameSearchView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View view, int position, long id) {
// Get the cursor. Positioned to the corresponding row in the result set.
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
// Get the name selected
String selectedName = cursor.getString(cursor.getColumnIndexOrThrow(nameColumn));
// Do something with this value...
}
});
// Set the CursorToStringconverter, to provide the values for the choices to be displayed
// in the AutoCompleteTextview.
nameSearchCursorAdapter.setCursorToStringConverter(new SimpleCursorAdapter.CursorToStringConverter() {
#Override
public CharSequence convertToString(Cursor cursor) {
final String name = cursor.getString(cursor.getColumnIndexOrThrow(nameColumn));
return name;
}
});
// Set the FilterQueryProvider, to run queries for choices
nameSearchCursorAdapter.setFilterQueryProvider(new FilterQueryProvider() {
#Override
public Cursor runQuery(CharSequence constraint) {
Cursor cursor = dbHelper.getMatchingNames(outingId, checklistId, nameColumn,
(constraint != null ? constraint.toString() : null));
return cursor;
}
});
}
I wanted to duplicate the word-starting-with default functionality of the AutoCompeteTextView using the SQLite Cursor, only to find that REGEXP are not fully supported. So this StackOverflow topic gave me the LIKE workaround. SQLite LIKE alternative for REGEXP, Match Start of Any Word
I hope this helps others.
I have a Spinner which is filled from a query using a SimpleCursorAdapter, this works fine... but now I need to put an option "Please Select" before all the items retrieved from the query, just for usability issues... but I'm not quite sure of how to do so... HELP please...
Here is my code...
private Spinner comboForm;
...
comboForm = (Spinner) findViewById(R.id.comboFormularios);
...
mDbH.abrir();
final Cursor cu = mDbH.consultaFormularios(idU);
if(cu.moveToFirst() == false){
cu.close();
mDbH.cerrar();
}else{
SimpleCursorAdapter adapter2 = new SimpleCursorAdapter(getApplicationContext(),R.layout.spinner,cu,new String[] {"nombre"},new int[] {R.id.textoCombo});
adapter2.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
comboForm.setAdapter(adapter2);
}
mDbH.cerrar();
...
comboForm.setOnItemSelectedListener(new OnItemSelectedListener(){
public void onItemSelected(AdapterView<?> parentView, View selectedItemView,int position, long id) {
idF = (int) id;
obtenerDatosRutas(idU,idF);
tabla.removeAllViews();
llenarTabla();
}
public void onNothingSelected(AdapterView<?> arg0) {}
});
Where mDbH is an instance of the class I'm using to manipulate the Database... as you can see the Spinner is filled up from Cursor resulting of the query consultaFormularios(idU)
When you create your cursor, one possible solution would be to use a SQL UNION and construct second SELECT that simply contains the label you need (adding hard-coded dummy fields for ordering).
Alternatively, and this is most likely the simplest solution. Instead of using a cursor adapter, use an array adapter and start by populating the array with your default value you want, then stick in all the items from your cursor. Something like,
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("Please select");
final Cursor cu = mDbH.consultaFormularios(idU);
while(cu.moveToNext()) {
arrayList.add(cu.getString(0)); // assuming you want a
//string from the first column
}
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, arrayList);
comboForm.setAdapter(spinnerArrayAdapter);
I've been reading stuff about this for hours and still haven't figured out how to do it.
I managed to populate a spinner from a cursor reading the database and now I'm trying to get the selected item on the spinner to help fill a listview.
Here's my code:
Cursor cursorpf = DatabaseHelper.getPFunc();
startManagingCursor(cursorpf);
Spinner spinnerpf = (Spinner) findViewById(R.id.spinner1);
String[] frompf = new String[] { "Designacao" };
int[] topf = new int[] { android.R.id.text1 };
SimpleCursorAdapter scaPFunc = new SimpleCursorAdapter(this,
android.R.layout.simple_spinner_item, cursorpf, frompf, topf);
scaPFunc
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerpf.setAdapter(scaPFunc);
spinnerpf.setOnItemSelectedListener(new MyOnItemSelectedListener());
final String stringpf = MyOnItemSelectedListener.getSelected();
long id = spinnerpf.getSelectedItemId();
String stringpf = String.valueOf(id);
DatabaseHelper.setPF(stringpf);
MyOnItemSelectedListener class:
public class MyOnItemSelectedListener implements OnItemSelectedListener {
private static String selected = "";
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
selected = String.valueOf(id);
Toast.makeText(parent.getContext(), "Escolha: " + selected, Toast.LENGTH_LONG).show();
}
#SuppressWarnings("unchecked")
public void onNothingSelected(AdapterView parent) {
// Do nothing.
}
}
The toast on this class returns the cursor position. Now, I know I must compare it against the database to get the value I want, but I just can't do it. Would you please help me out?
Thanks in advance.
Edit:
Guys, would you help me out?
I managed to get the selected item by implementing the code above, but it happens that the listview is only filled when the app starts. When I select something on the spinner, nothing happens. :|
If you want to retrieve selected item from database, just pass the fourth argument of onItemSelected (id) to you SQL query. It's the row id of the record, aka _ID.
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 am using the following code to set the adapter (SimpleCursorAdapter) for an AutoCompleteTextView
mComment = (AutoCompleteTextView) findViewById(R.id.comment);
Cursor cComments = myAdapter.getDistinctComments();
scaComments = new SimpleCursorAdapter(this,R.layout.auto_complete_item,cComments,new String[] {DBAdapter.KEY_LOG_COMMENT},new int[]{R.id.text1});
mComment.setAdapter(scaComments);
auto_complete_item.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
and thi is the xml for the actual control
<AutoCompleteTextView
android:id="#+id/comment"
android:hint="#string/COMMENT"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="18dp"/>
The dropdown appears to work correctly, and shows a list of items. When I make a selection from the list I get a sqlite object ('android.database.sqlite.SQLiteCursor#'... ) in the textview.
Anyone know what would cause this, or how to resolve this?
thanks
Ok I am able to hook into the OnItemClick event, but the TextView.setText() portion of the AutoCompleteTextView widget is updated after this point. The OnItemSelected() event never gets fired, and the onNothingSelected() event gets fired when the dropdown items are first displayed.
mComment.setOnItemClickListener( new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
SimpleCursorAdapter sca = (SimpleCursorAdapter) arg0.getAdapter();
String str = getSpinnerSelectedValue(sca,arg2,"comment");
TextView txt = (TextView) arg1;
txt.setText(str);
Toast.makeText(ctx, "onItemClick", Toast.LENGTH_SHORT).show();
}
});
mComment.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
Toast.makeText(ctx, "onItemSelected", Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
Toast.makeText(ctx, "onNothingSelected", Toast.LENGTH_SHORT).show();
}
});
Anyone alse have any ideas on how to override the updating of the TextView?
thanks
patrick
I don't think you should have to update the text for the AutoCompleteTextView. It should do it automatically. It does this by calling the [CursorAdapter.convertToString(...)][1] method. if you read the description of the method it points this out. So if you were writing your own CursorAdapter you would override that method to return whatever text you would want to show up in the list of suggestions. This guy does a good job of explaining how to do it:
Line 86 - http://thinkandroid.wordpress.com/2010/02/08/writing-your-own-autocompletetextview/
However, since you are using a SimpleCursorAdapter, you can't override this method. Instead you need implement/create a [SimpleCursorAdapter.CursorToStringConverter][2] and pass it into [SimpleCursorAdapter.setCursorToStringConverter(...)][3]:
SimpleCursorAdapter adapter = new SimpleCursorAdapter(context, layout, cursor, from, to);
CursorToStringConverter converter = new CursorToStringConverter() {
#Override
public CharSequence convertToString(Cursor cursor) {
int desiredColumn = 1;
return cursor.getString(desiredColumn);
}
};
adapter.setCursorToStringConverter(converter);
Or if you don't want to create a CursorToStringConverter then use the [SimpleCursorAdapter. setStringConversionColumn(...)][4] method. But I think you still have to explicitly set the CursorToStringConverter to null:
int desiredColumn = 1;
adapter.setCursorToStringConverter(null);
adapter.setStringConversionColumn(desiredColumn);
Sorry, but the spam blocker won't let me post the links to the Android Documentation that describes the links I posted above. But a quick google search will point you to the correct doc pages.
[Late answer, just for the record. EDITed to remove my suggestion that subclassing is necessary.]
To use SimpleCursorAdapter with an AutoCompleteTextView, you need to set two handlers on the adapter: The CursorToStringConverter, and the FilterQueryProvider. Pseudocode follows:
adapter.setCursorToStringConverter(new CursorToStringConverter() {
public String convertToString(android.database.Cursor cursor) {
// Assume that "someColumn" contains the strings that we want to
// use to identify rows in the result set.
final int columnIndex = cursor.getColumnIndexOrThrow("someColumn");
final String str = cursor.getString(columnIndex);
return str;
}
});
adapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
// runSomeQuery will look for all rows in the database
// that match the given constraint.
Cursor cursor = runSomeQuery(constraint);
return cursor;
}
});
When I make a selection from the list
I get a sqlite object
('android.database.sqlite.SQLiteCursor#'...
) in the textview.
You do not say what this "textview" is or how it relates to the Spinner.
I am going to take an educated guess and assume that you are simply assigning the selected item out of the Spinner into the TextView.
The selected item from a Spinner using a SimpleCursorAdapter is a Cursor, pointing at the row the user selected. The toString() implementation of Cursor will give you something akin to android.database.sqlite.SQLiteCursor# depending on where the Cursor came from.
More likely, you are going to want to call getString() on that Cursor, to retrieve some column value, and assign it to the TextView in question.
To solve the problem I just extended SimpleCursorAdapter and implemented the method convertToString(). Then I created an instance and set it as the adapter.
In order to allow filtering in AutoCompleteTextView when using CursorAdapters I also used setFilterQueryProvider(). See this question.
My extended class inside the Activity looks as:
private static class AutoCompleteCursorAdapter extends SimpleCursorAdapter {
public AutoCompleteCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
}
#Override
public CharSequence convertToString(Cursor cursor) {
// This is the method that does the trick (return the String you need)
return cursor.getString(cursor.getColumnIndex("name"));
}
}