Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - AutoCompleteTextView wildcard suggestion

Good day. I have an AutoCompleteTextView in my Android Application, and it is working fine. However, I noticed that the suggestions are based on the first character(s) of the substrings of the list supplied to the AutoCompleteTextView. That is fine on its own, however, what I want is for it to also show the items which contains the user input.

For example, let's use this list:

  • Adipose
  • Bad Wolf
  • Cybermen
  • Daleks

Typing in ad will suggest Adipose, however, I also want Bad Wolf to be suggested since it contains ad in Bad. This won't happen because the AutoCompleteTextView only looks at the beginning of the substrings (substring are separated by a whitespace) in the list items and not within those substrings.

Is there any way to make AutoCompleteTextViews suggest items that contains the input text regardless of where that text falls inside the list item?

Thanks for any help.

EDIT/UPDATE

Kindly see pskink's comment below. I tried to implement the same solution as follows.

The logic from what I inferred is that a SimpleCursorAdapter is to be used, and not the common ArrayAdater. I then created a FilterQueryProvider to the SimpleCursorAdapter. Using the runQuery method of the FilterQueryProvider, I can now run a filter algorithm by searching my list of the constraint input of the user. Here is the code:

//initialize the ACTV
AutoCompleteTextView search = (AutoCompleteTextView) findViewById(R.id.actvCatalogueSearch);
search.setThreshold(1); //set threshold

//experiment time!!

//I honestly don't know what this is for
int[] to = { android.R.id.text1 };

//initializing the cursorAdapter. 
//please note that pdflist is the array I used for the ACTV value
SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(this, 
        android.R.layout.simple_dropdown_item_1line, null, pdflist, to, 0);

cursorAdapter.setStringConversionColumn(1);

//FilterQueryProvider here
FilterQueryProvider provider = new FilterQueryProvider(){
    @Override
    public Cursor runQuery(CharSequence constraint) {
        // TODO Auto-generated method stub
        Log.d("hi", "runQuery constraint: " + constraint);
        if (constraint == null) {
            return null;
        }
        String[] columnNames = { Columns._ID, "name" };
        MatrixCursor c = new MatrixCursor(columnNames);

        try {
            //loop through the array, then when an array element contains the constraint, add.
            for (int i = 0; i < pdflist.length; i++) {
                if(pdflist[i].contains(constraint)){
                    c.newRow().add(i).add(pdflist[i]);  
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return c;
    }
};

cursorAdapter.setFilterQueryProvider(provider);
search.setAdapter(cursorAdapter);

The Log statement for the runQuery constraint is shown, however, after that, the app crashes and I get this error in my logcat:

requesting column name with table name -- <first element of array here> 
.....
java.lang.IllegalArugmentException: column <first element of array here> does not exist

Clicking on the logCat error lines opens up the jar file and not any of them point to a line in the code. However, judging from some of the error lines, I think that there's something wrong with how I used the String[] columnNames and the MatrixCursor variables.

Can anyone help? I haven't used Filter Query Providers with Cursor Adapters before so I'm very clueless on how to proceed with this one.

Any help is very much appreciated. Thank you.

like image 792
Razgriz Avatar asked Oct 20 '22 21:10

Razgriz


1 Answers

Okay here's how I made it work. Major props to pskink for the lead. It's very similar to the code I have above, with some changes to make the runQuery method work.

The same logic/thought pattern is used, only that I changed the runQuery method. Read the comments for a walkthrough.

//create ACTV Here
AutoCompleteTextView search = (AutoCompleteTextView) findViewById(R.id.actvCatalogueSearch);
search.setThreshold(1);

//I don't know what these are for, honestly.
String[] from = { "name" };
int[] to = { android.R.id.text1 };

//create a simple cursorAdapter
SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(this, 
        android.R.layout.simple_dropdown_item_1line, null, from, to, 0);

//again, I don't know what this is for
cursorAdapter.setStringConversionColumn(1);

//create the filter query provider
FilterQueryProvider provider = new FilterQueryProvider(){
    @Override
    public Cursor runQuery(CharSequence constraint) {
        // TODO Auto-generated method stub
        //I need to do this because my list items are in all caps
        String constrain = (String) constraint;
        constrain = constrain.toUpperCase(); 

        if (constraint == null) {
            return null;
        }

        //I'll be honest again, no clue what these lines do. 
        String[] columnNames = { Columns._ID, "name" };
        MatrixCursor c = new MatrixCursor(columnNames);

        try {
            //here's what I do, I go though my Array (pdflist)
            //when a list item contains the user input, I add that to the Matrix Cursor
            //this matrix cursor will be returned and the contents will be displayed 
            for (int i = 0; i < pdflist.length; i++) {
                if(pdflist[i].contains(constrain)){
                    c.newRow().add(i).add(pdflist[i]);  
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return c;
    }
};

//use the filter query provider on the cursor adapter
cursorAdapter.setFilterQueryProvider(provider);

//finally, use the adapter on your ACTV
search.setAdapter(cursorAdapter);

It's a bit of a work but it gets the job done. Honestly, I'm a bit surprised that there's no "straightforward/intuitive" way of doing this. Something to the tune of just enabling/disabling something in your AutoCompleteTextView then it's done.

I guess we'll have to stick with this solution until further notice.

like image 179
Razgriz Avatar answered Oct 22 '22 11:10

Razgriz