android autocompletetextview should show only relevant options in drop down - android

I am using a AutoCompleteTextView in my code and loading the list from database using SimpleCursorAdapter.
AutoCompleteTextView cocktailIngredientView = (AutoCompleteTextView) findViewById(R.id.item);
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_spinner_item, mCursor,
new String[] { "field" },
new int[] { android.R.id.text1 });
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
cocktailIngredientView.setAdapter(adapter);
cocktailIngredientView.setThreshold(0);
It populates the list correctly but I have two issues:
I want this list to be sorted
Whatever I enter, it displays the complete list. I want it to filter based on matching patterns in the list. e.g. if the list contains values Page, Tools...then if I enter T in the box, the drop-down should show only Tools. The idea is to display options which contain the entered pattern anywhere in the string text.
How can this be done?

You have to tell the adapter what items to display. I tried implementing something similar to this by using a FilterQueryProvider that queries the database for the items that I want to display in the dropdown.
FilterQueryProvider filter = new FilterQueryProvider() {
#Override
public Cursor runQuery(CharSequence constraint) {
// Make a DB query that filters based on the constraint
return //whatever query results;
}
};
myAdapter.setFilterQueryProvider(filter);
As for the situation when you select an item on the list, you have to override the CursorToStringConverter of the SimpleCursorAdapter. Something like:
SimpleCursorAdapter.CursorToStringConverter conv = new SimpleCursorAdapter.CursorToStringConverter() {
#Override
public CharSequence convertToString(Cursor cursor) {
int numCol = cursor.getColumnIndexOrThrow("whateverFieldYouNeed");
String term = cursor.getString(numCol);
return term;
}
};
myAdapter.setCursorToStringConverter(conv);

Instead of the CursorToStringConverter you could also use
mAdapter.setStringConversionColumn(mCursor.getColumnIndexOrThrow("whateverFieldYouNeed"));

Related

AutoCompleteTextView with SimpleCursorAdapter does not filter

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.

Hidden id for selected text in Android AutoCompleteTextView

I have a very basic form in my Android App. One of the fields has to be selected from the rows in my SQLite db.
As this field offers a LOT of options, a spinner would be unconfortable for the user, so I opted for an autocomplete field, as the user usually knows the name of the item he's looking for.
So, now I have an AutoCompleteTextView against a SQLite DB table. The autocomplete functionality is working just fine:
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, null, new String[]{"nombre"}, new int[]{android.R.id.text1}, 0);
AutoCompleteTextView concepto = (AutoCompleteTextView) findViewById(R.id.editConcepto);
concepto.setAdapter(adapter);
final PorkyOpenHelper poh = new PorkyOpenHelper(getApplicationContext());
adapter.setFilterQueryProvider(new FilterQueryProvider()
{
#Override
public Cursor runQuery(CharSequence str)
{
if (str != null)
{
return poh.findConceptosByNombre(str.toString());
}
else
{
return null;
}
}
});
adapter.setCursorToStringConverter(new SimpleCursorAdapter.CursorToStringConverter()
{
#Override
public CharSequence convertToString(Cursor cursor)
{
int index = cursor.getColumnIndex(PorkyOpenHelper.CONCEPTOS_TABLE_NOMBRE);
return cursor.getString(index);
}
});
But now I have a problem: the users selects and sees the field 'nombre' from my db table, but I need to know and store the '_id' field. I could solve it with try-n-fix, but I'd like to know if there's some more elegant or 'correct' solution already proben for the Android SDK (yes, the quotes in correct are a joke).
Thanks in advance everyone!!
use OnItemClickListener, the last param of the callback is the item id

Add a "Please Select" option to a Spinner in Android

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);

Display part of a string in layout

I am reading data from an SQLite database using a cursor and using an adapter to display it in a listView. This works fine but I now want to reduce the amount of data that I show in the listView. At the moment it displays the following:
John Smith, 25, Moday, Consultation, Dr. Harley
Jane Doe, 41, Wednesday, Surgery, Dr. Pope
What I want it to display is:
John Smith, 25, Mo, Con, Harley
Jane Doe, 41, We, Sur, Pope
Basically I want to parse 3 of the strings. The problem is the cursor adapter takes the columns of the database as a string array in its constructor so I don't know where to perform the parsing operation on it. I've tried a number of different options and am getting unrecognised column id errors and other runtime errors. Can anyone point me in the right direction?
The method where the adapter is created:
private void fillList() {
Cursor c = db.getApts();
startManagingCursor(c);
String[] from = new String[] {ModuleDB.KEY_AptCode,
ModuleDB.KEY_AptName,
ModuleDB.KEY_AptAge,
ModuleDB.KEY_AptDay,
ModuleDB.KEY_AptType,
ModuleDB.KEY_AptDoc};
int[] to = new int[] {R.id.Aptcode_entry,
R.id.AptName_entry,
R.id.AptAge_entry,
R.id.Aptday_entry,
R.id.Apttype_entry,
R.id.Aptdoc_entry};
SimpleCursorAdapter aptAdapter =
new SimpleCursorAdapter(this, R.layout.apt_entry, c, from, to);
setListAdapter(aptAdapter);
}
1.) Let your activity implement - ViewBinder
2.) Match your column and use substring
public class YourActivity extends Activity
implements SimpleCursorAdapter.ViewBinder {
adapter.setViewBinder(this); //Put this line after your list creation and setlistAdapter
#Override
public boolean setViewValue(View view, Cursor cursor, int column) {
//Showing for day, similarly for others
int dayColumn = cursor.getColumnIndex(your day column name in quotes);
if (column == dayColumn ) {
String dayString = cursor.getString(dayColumn );
((TextView)view).setText(bodyString.subString(0, 3));
return true; // Return true to show you've handled this column
}
return false;
}
}
Also - #Simon is Right - Using a Custom Adapter that extends a Cursor Adapter is always better because you get a lot more freedom to modify it later if your requirements evolve further. Off the top of my head here is an example of how you can use custom adapter and build a nice list- http://www.androidhive.info/2012/02/android-custom-listview-with-image-and-text/
Not sure what adapter you use, but assuming all the data is shown as single row then I'd extend that one and override toString() method of it.
Don't think you can override toString() on a simple adapter but perhaps this will help?
SimpleCursorAdapter aptAdapter= new SimpleCursorAdapter(this, R.layout.apt_entry, c, from, to);
CursorToStringConverter stringConverter = new CursorToStringConverter() {
#Override
public CharSequence convertToString(Cursor cursor) {
return "Hello listview"; // whatever string you want to build using cursor.getString() etc
}
};
aptAdapter.setCursorToStringConverter(stringConverter);
[EDIT] Just checked the docs and SimpleCursorAdapter does not have a toString() method, nor do any of it's super classes.

Using buffer in sqlite select statement android

i'm making select statement and it works fine
the problem is selecting more than thousands of records ate one and this cause the program too slow.
is there a possibility to select fifty by fifty and when select the first fifty record show them then add the next fifty record to them.
how can i do that .
thanks in advance ...
Use LIMIT/OFFSET Clauses is selection statement
I haven't worked on that but can give some idea reagarding that. You can use AsynTask here. In the doingInbackground() you can get the records and then you can call publishProgress() when 50 records are fetched and update the UI.
UPDATE:
You can use the LIMIT/OFFSET clause that Kiran said to get the limit of the record fetched and can update the UI using AsyncTask.
Here is the code you need to back your AutoCompleteTextView with a cursor adapter.
#Override
protected void onResume() {
super.onResume();
text = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView1);
final AdapterHelper h = new AdapterHelper(this);
Cursor c = h.getAllResults();
startManagingCursor(c);
String[] from = new String[] { "val" };
int[] to = new int[] { android.R.id.text1 };
CursorAdapter adapter = new MyCursorAdapter(this,
android.R.layout.simple_dropdown_item_1line, c,
from, to);
adapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
if (constraint == null) {
return h.getAllResults();
}
String s = '%' + constraint.toString() + '%';
return h.getAllResults(s);
}
});
text.setAdapter(adapter);
}
class MyCursorAdapter extends SimpleCursorAdapter {
public MyCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
}
public CharSequence convertToString(Cursor cursor) {
return cursor.getString(cursor.getColumnIndex("val"));
}
}
The database that I am using has 3k rows of data in it and the Autocomplete works fine.
The things to note are that you need make sure that the your adapter puts the correct value in the text box once a user selects it. Do this with the convertToString method (at the end of the snippet above). You get to this method by extending SimpleCursorAdapter and overriding the method as shown.
Then you need to provide a FilterQueryProvider to your adapter. This allows your query to be run with the where clause of your typed text. If you have a huge dataset, then setting the threshold large enough (either programatically, or in xml) will prevent the filter query running until it will return a suitably sized resultset.
Hope this is useful.
Anthony Nolan

Categories

Resources