Challenge 1


#1

The challenge cause me to read through the Search Overview topic, because I can only get it to work for pre-API 11 (Search Dialog). It would seem the SearchView implementation is different.

PhotoGalleryActivity.onNewIntent() - gets called for both search types.

PhotoGalleryActivity.onSearchRequested() - where I call the [color=#BF0040]startSearch(query, true, null, false);[/color] method for the challenge, only gets called by the Search Dialog thing.

The android overview does not address doing both implementations well, like in how you have a item with two icons but then superimpose the SearchView into the Action Bar. I am still confused about how to best code for both methods for the two API targets. I don’t think the challenge is possible for the SearchView method.

The SearchView has its own ICON for cancel. So, I think you would want to remove the MenuItem for it when using a SearchView:

MenuItem cancelItem = menu.findItem(R.id.menu_item_clear); cancelItem.setVisible(false);

The overview also said to do this (so you can initiate the search either from the keyboard or from the SearchView):

If you add this:

the app starts with the SearchView visible and the menu_item_search not visible. Otherwise, you see the menu_item_search, and when you click it you see the SearchView. I am guessing that the menu_item_search goes away because it no longer fits in the action bar. Someone else posted something about this in this forum in May, but you ignored it.

I tried to make this only occur for API < 11:

but then got a NullPointerException for this:

So, I think this chapter is really sloppily done. It should provide at least as much info as the Android overview. I think that inflating a menu with two ICONs and then just laying the SearchView on top of it is the wrong way to go. It should be one or the other. Not both.

If you restart the app, the SearchView will start out with the hint text but the app will then continue to do a new search from the saved query. I can’t see any way to get the SearchView to display the saved query string.

Also, the SearchView’s clear button (X) just clears the text in it. It does not call onOptionsItemSelected with menu_item_clear, allowing you to also remove the query from the persisted storage.

For the Search Dialog solution of pre-API-11, the app will still go back to doing the getRecents() thing when the clear button is pressed.

The two different behaviors of the clear button don’t make sense.

Thanks.


#2

It’s not that it is not possible to implement the challenge for the SearchView method; it’s that the challenge is irrelevant when SearchView is being used. The onSearchRequested() and startSearch() methods are related to the search dialog, not the SearchView. To fill in the query in the SearchView, call SearchView.setQuery(). (Looking at the documentation, I’m not sure that it’s also possible to highlight the search query when using SearchView).

[quote]The SearchView has its own ICON for cancel. So, I think you would want to remove the MenuItem for it when using a SearchView:

MenuItem cancelItem = menu.findItem(R.id.menu_item_clear); cancelItem.setVisible(false);[/quote]

You’d need to add some additional code to detect and handle the case where the search text is cleared out by the SearchView’s cancel button. (We try to keep our examples simple, which is why we didn’t special case this code.)

[quote]The overview also said to do this (so you can initiate the search either from the keyboard or from the SearchView):

searchView.setSubmitButtonEnabled(true); [/quote]

Indeed it does. You’re right - this should be set to true in our example. Thanks for the catch!

[quote]If you add this:

the app starts with the SearchView visible and the menu_item_search not visible. Otherwise, you see the menu_item_search, and when you click it you see the SearchView. I am guessing that the menu_item_search goes away because it no longer fits in the action bar.[/quote]

The SearchView is menu_item_search. SearchView is an expandable action view that, when minimized, looks like a regular menu item. You can see this clearly if you change the android:icon value in your menu XML - SearchView ignores it, so it will still show a search icon.

Indeed I did. I’m not sure how that relates to your question, but I’d certainly prefer not to do that kind of thing, either in the past or the future.

[quote]I tried to make this only occur for API < 11:

but then got a NullPointerException for this:

It looks like you left out some code here.

See above - this is where you’d want to use SearchView.setQuery.

That’s correct - which is why the solution keeps the clear button in its menu.xml.

No problem!


#3

Yes, there’s something funny going on here. I get the same behaviour when searching: the search does a false start, i.e., it displays a few pictures and then restarts from scratch. Looking at the debug info, I see that each query is received twice (in PhotoGalleryActivity.onNewIntent()). If I add: searchView.setSubmitButtonEnabled(true), as suggested by RickDroid, a right-pointing triangle appears in the search box and when I press that, the query is only received once and I don’t get the false start. If I press enter instead of pressing the triangle. I get the false start. If I press the back button, I get the old search box without the triangle (instead of removing the search box as it should).

In PhotoGalleryFragment.onOptionsSelected(…), the call to Activity.onSearchRequested() seems superfluous because when I comment it out, I don’t see any difference in the app.


#4

In regards to the question about Honeycomb+ devices and the SearchView’s X-button (clear) behavior…

I agree with a previous poster that it obsoletes the need for our Menu clear button. Hide that button!

  1. Intuitively, you might want an experience where you hide or activate the X button, depending on whether we are displaying search results.
  2. Even better, like a previous poster said, I argue we should just allow the SearchView to dictate the behavior, because now the user see’s two different X icon’s in use.
    …There are actually up to three X buttons – one to clear the search text, but if you hit the Back button instead of the X you’ll see the X move to the right side, and then our menu Clear button. This solution is also clearer to the user; I found myself initially trying to keep hitting the Back button to get out of the searchView, and end up closing the App. Users will learn that the SearchBar’s X means to close the search and return to normal results, whereas the Back button is used for backing out of the Activity.

In going with #2, here’s what I did:

  1. In PhotoGalleryFragment::onCreateOptionsMenu(), in the code block specific to Honeycomb+ devices and our SearchView…
    I disable the Clear Search button.

MenuItem cancelItem = menu.findItem(R.id.menu_item_clear); cancelItem.setVisible(false);

  1. In the same function, I added a SearchView.OnCloseListener().
    When the SearchView is collapsed (closed), you can set your persisted query string to null and updateItems() again so that you get the regular fetch results.

[code]searchView.setOnCloseListener(new SearchView.OnCloseListener() {
@Override
public boolean onClose() {
Log.i(TAG, “onClose() called on our SearchView”);

    // update our GridView with a normal fetch result (i.e. remove search results).
    // we hvae to remove our persisted query, then updateItems() to queryThumbnails again.
    PreferenceManager.getDefaultSharedPreferences(getActivity())
        .edit()
        .putString(FlickrFetchr.PREF_SEARCH_QUERY, null)
        .commit();
    
    updateItems(1,true);  // my "1" param is to suggest the first page, as part of our book challenge, second param is other custom stuff.
    return false; 
}

});
[/code]

  1. In the same function, for clarity and as mentioned by the previous poster, I enabled the SearchView’s submit button.
  1. Extra credit: I added another Activity/fragment that loads a fullsize image from Flickr, after clicking on a GridView’s thumbnail. If you go to that length, you’d be interested in my comments below. EDIT: I see Chap 31 has a similar activity, but with a WebView. I now have the WebView on an ItemLongClickListener, lol.
    This presents some interesting behaviors. For Example:
  • Do a search in the Photo Gallery, getting an updated set of thumbnails for the specific query.
  • Explicitly run another activity.
  • Rotate to landscape while in that activity.
  • Back button to pop your activity off and to return to the Photo Gallery, still in landscape.
  • Notice the SearchView has collapsed! However, onClose() isn’t called to let us clean up!

In this case, you probably want your user to return to his search results anyway, not to clean up our search results. So I handle this, again, in the same onCreateOptionsMenu() function (at the end as my last step).
If we had a search query before showing another activity and returning, I want that SearchView expanded still, showing the previous search query text, and here’s my code…

[code]String previeousQuery = PreferenceManager
.getDefaultSharedPreferences(getActivity())
.getString(FlickrFetchr.PREF_SEARCH_QUERY, null);

if (previousQuery != null) {
searchView.setIconified(false); // expand the search box
searchView.setQueryHint(previousQuery); // set the hint to display the prior query phrase
searchView.clearFocus(); // close the soft keyboard, it may have opened and obscured our results
}
[/code]


#5

So this is what I got from this

Search view implements a search widget that goes into the bar.

It has a collapsed and normal state
In the normal state, there is a text input, a clear+collapse button and an optional send button.
The clear+collapse button has two functions (I learned this after reading the source code a bit)
The first press, not settable , clears the text input. The second, calls onClose(). The default is to just collapse and clear the text.

To get a similar functionality than on older devices, I overrode onClose, and set it so that it puts the current (last saved) query string back into the searchview and perform the rest as normal, so that when they open the search view again, the text there is the last executed search.

Then we have the other close button (which is visible only when the searchView is collapsed) whose purpose is to forget about searches and re-load the default, which is the most recent photos.


#6

[quote=“console”]In regards to the question about Honeycomb+ devices and the SearchView’s X-button (clear) behavior…

I agree with a previous poster that it obsoletes the need for our Menu clear button. Hide that button!

  1. Intuitively, you might want an experience where you hide or activate the X button, depending on whether we are displaying search results.
  2. Even better, like a previous poster said, I argue we should just allow the SearchView to dictate the behavior, because now the user see’s two different X icon’s in use.
    …There are actually up to three X buttons – one to clear the search text, but if you hit the Back button instead of the X you’ll see the X move to the right side, and then our menu Clear button. This solution is also clearer to the user; I found myself initially trying to keep hitting the Back button to get out of the searchView, and end up closing the App. Users will learn that the SearchBar’s X means to close the search and return to normal results, whereas the Back button is used for backing out of the Activity.

In going with #2, here’s what I did:

  1. In PhotoGalleryFragment::onCreateOptionsMenu(), in the code block specific to Honeycomb+ devices and our SearchView…
    I disable the Clear Search button.

MenuItem cancelItem = menu.findItem(R.id.menu_item_clear); cancelItem.setVisible(false);

  1. In the same function, I added a SearchView.OnCloseListener().
    When the SearchView is collapsed (closed), you can set your persisted query string to null and updateItems() again so that you get the regular fetch results.

[code]searchView.setOnCloseListener(new SearchView.OnCloseListener() {
@Override
public boolean onClose() {
Log.i(TAG, “onClose() called on our SearchView”);

    // update our GridView with a normal fetch result (i.e. remove search results).
    // we hvae to remove our persisted query, then updateItems() to queryThumbnails again.
    PreferenceManager.getDefaultSharedPreferences(getActivity())
        .edit()
        .putString(FlickrFetchr.PREF_SEARCH_QUERY, null)
        .commit();
    
    updateItems(1,true);  // my "1" param is to suggest the first page, as part of our book challenge, second param is other custom stuff.
    return false; 
}

});
[/code]

  1. In the same function, for clarity and as mentioned by the previous poster, I enabled the SearchView’s submit button.
  1. Extra credit: I added another Activity/fragment that loads a fullsize image from Flickr, after clicking on a GridView’s thumbnail. If you go to that length, you’d be interested in my comments below. EDIT: I see Chap 31 has a similar activity, but with a WebView. I now have the WebView on an ItemLongClickListener, lol.
    This presents some interesting behaviors. For Example:
  • Do a search in the Photo Gallery, getting an updated set of thumbnails for the specific query.
  • Explicitly run another activity.
  • Rotate to landscape while in that activity.
  • Back button to pop your activity off and to return to the Photo Gallery, still in landscape.
  • Notice the SearchView has collapsed! However, onClose() isn’t called to let us clean up!

In this case, you probably want your user to return to his search results anyway, not to clean up our search results. So I handle this, again, in the same onCreateOptionsMenu() function (at the end as my last step).
If we had a search query before showing another activity and returning, I want that SearchView expanded still, showing the previous search query text, and here’s my code…

[code]String previeousQuery = PreferenceManager
.getDefaultSharedPreferences(getActivity())
.getString(FlickrFetchr.PREF_SEARCH_QUERY, null);

if (previousQuery != null) {
searchView.setIconified(false); // expand the search box
searchView.setQueryHint(previousQuery); // set the hint to display the prior query phrase
searchView.clearFocus(); // close the soft keyboard, it may have opened and obscured our results
}
[/code][/quote]

Thanks for posting your solution console