3

I have an AutoSearchTextView in the actionbar. When I filter the data the dropdown hides and then shows very quickly. I really would prefer the effect on the play store, where you filter results, the dropdown is always visible but the content in the dropdown changes.

This is my filter code in my Adapter, run history query, gets the history and sets the list items.

@Override
public Filter getFilter() {
    if (filter == null) {
        filter = new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                ResortFilterResult result = new ResortFilterResult();
                String substr = constraint.toString().toLowerCase();
                if (constraint != null) {
                    if (constraint.length() > 0) {
                        result.setHistory(runHistoryQuery(substr));
                    }
                    if (constraint.length() >= 3) {
                        LCResort[] resorts = searchResortWithQuery(substr);
                        result.setQueryResults(Arrays.asList(resorts));
                    }
                }
                FilterResults filterResults = new FilterResults();
                filterResults.values = result;
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                ResortFilterResult result = (ResortFilterResult)results.values;
                history = result.getHistory();
                resorts = result.getQueryResults();
                notifyDataSetChanged();

            }
        };
    }
    return filter;
}

EDIT: I am one step closer - It turns out dismiss dropdown on the TextView is being called every time I type a new character!

serenskye
  • 3,297
  • 4
  • 30
  • 49
  • If you're going to extend the filter, do it the right way. Don't set the results from the `runHistoryQuery()` method(I'm surprised you didn't get in troubles), instead make it return the new data and assign it to the `FilterResults` object(along with the count). In the `publishResults()` callback don't just blindly call `notifyDataSetChanged()`, assign the newly received data(from the FilterResults parameter) and then call the method. – user Jun 03 '14 at 09:32
  • "don't just blindly call notifyDataSetChanged()" Not sure what you mean, the data has been changed, so thats the appropriate place. I agree that the data should be set in publish results - was doing things a bit of a weird way before. But the order should still be set data, notifyDataSetChanged surely? – serenskye Jun 03 '14 at 09:43
  • 1
    Set data, call `notifyDataSetChanged()`. If you change the data in `performFiltering()` you're changing it from a background thread and there is the possibility that the `ListView` will see those changes before you get in the `publishResults()`(which runs on the main UI thread) to call `notifyDataSetChanged()`. – user Jun 03 '14 at 09:49
  • why not to use a FilterQueryProvider? no need to play with custom Adapters, Filters etc, – pskink Jun 03 '14 at 09:49
  • @Luksprog Thank's gotcha, copied code from elsewhere and just checked the docs...thats for the heads up. This doesn't stop the flickering though. :( – serenskye Jun 03 '14 at 09:51
  • @pskink What i'm doing is more complex than the question - I don't need cursors and I need a custom adatper, it's not much more code. – serenskye Jun 03 '14 at 09:54
  • just use a SimpleCursorAdapter, really, no need for any custom Adapter and it has built in FilterQueryProvider – pskink Jun 03 '14 at 10:05
  • @pskink - You're not reading – serenskye Jun 03 '14 at 10:07
  • Are you manually showing the drop down or are you doing anything special with the widget? – user Jun 03 '14 at 10:22
  • Edited code to reflect current version - I am manually showing the dropdown when the search bar is focused, so that I can show search history instantly. In order to do this I have using a custom widget which performs filtering if the textview is focused. I had forgotten about this...could well be the issue in there somewhere. – serenskye Jun 03 '14 at 10:27
  • Commented out overriden methods in custom view so its basically just a AutoCompleteTextView but did not make a difference – serenskye Jun 03 '14 at 10:31
  • @pskink As I've said to you before, please don't use comments as a discussion forum, if you have an answer please use the section with your reasoning. As always I appreciate the help. Thanks – serenskye Jun 03 '14 at 10:50

2 Answers2

7

Okay, It turns out the answer was quite simple, sometimes the best way it to just check the source code :)

AutoSearchTextView has a method public void onFilterComplete(int count) which in turn calls private void updateDropDownForFilter(int count), if the count is zero the dropdown will be hidden.

You must set count on your FilterResults object returned from your Filter protected FilterResults performFiltering(CharSequence constraint) method.

filterResults.count = result.getHistory().size() + result.getQueryResults().size();

solved the issue.

serenskye
  • 3,297
  • 4
  • 30
  • 49
-1

please don't reinvent the wheel, use existing Filter instead of creating your own one

and the easiest is to use FilterQueryProvider together with e.g. SimpleCursorAdapter or when extending CursorAdapter just override runQueryOnBackgroundThread(), using that you will avoid errors like you have now

EDIT:

in your case if you dont need a custom Adapter use a SimpleCursorAdapter with custom FilterQueryProvider overriding runQuery() you can return all the data you need (see my answer here how i query wikipedia: How to dynamically add suggestions to autocompletetextview with preserving character status), if you REALLY need a custom Adapter extend CursorAdapter and do exactly the same in runQueryOnBackgroundThread() what you did in FilterQueryProvider.runQuery(), also when your data comes from more then one source use a MergeCursor but its perfectly ok to just use one MatrixCursor

Community
  • 1
  • 1
pskink
  • 21,078
  • 6
  • 53
  • 68
  • 1
    Hi as you can see I have found a solution. Please show code to demonstrate how your answer solves the problem. How exactly is my code re-inventing the wheel a Filter does not exist to filter data as I need – serenskye Jun 04 '14 at 10:39
  • you reinvent the wheel since you are extending the Filter dealing with FilterResults and its implementation details like values, count, also you have to integrate your custom Filter with your custom Adapter, all of it is already done in CorsorAdapter: all you need is to perform search query, that's it – pskink Jun 04 '14 at 10:55
  • AutoSearchTextView adapter must implement filterable, as I said I don't need a cursor adapter it doesn't make sense for my data type which doesn't need cursors. If you have an answer post code that shows how I can have an AutoSearchTextView which does two requests - 1 to the web and one to the search history content provider and then displays this content. If you don't explain how to achieve this, I can't make you as correct answer. – serenskye Jun 04 '14 at 11:02
  • I would argue that produces more fragile code, why should I convert my java objects into cursors just for the sake of using a cursor adapter, it feels like pushing a round peg into a square hole. Merging cursors can be prone to problems especially if the data aren't quite the same. In reality overriding a filter is exactly the same amount of code as overriding runQueryonBackgroundThread. It seems like an academic point you are trying to make and SO isn't the place, you can't tell me why my code is wrong and answer the original question, the code works, it doesn't seem to be bad practice – serenskye Jun 04 '14 at 11:37