Search action item not showing edit control - android

I have a search action item associated with an AppCompatActivity. The search icon appears but when I click on it, it doesn't show the edit control allowing me to put in the search text. I've tried all the obvious issues but I just can't seem to get this to work.
This app loads a PDF a switches out the Toolbar based on user choices. The first toolbar shows a search item. Once this is selected it adds the searchNext and searchPrev buttons. All this worked until I switched to Material Design. I think the problem has something to do with replacing the menu but I'm not sure.
Here is the manifest:
<activity
android:name="com.mupdf.MuPDFActivity"
android:theme="#style/Theme.AppCompat.Light.NoActionBar"
android:configChanges="orientation|screenSize|keyboardHidden"
android:label="#string/app_name" >
</activity>
Here is the menu resources:
MAIN MENU:
<item android:id="#+id/pdf_action_search"
android:title="#string/pdf_action_search"
android:icon="#drawable/ic_pdf_action_search"
android:orderInCategory="100"
app:showAsAction="ifRoom"/>
<item android:id="#+id/pdf_action_export"
android:title="#string/pdf_action_export"
android:icon="#drawable/ic_pdf_action_export"
android:orderInCategory="100"
app:showAsAction="ifRoom">
<menu>
<item
android:id="#+id/pdf_action_share"
android:title="#string/pdf_action_share"
app:showAsAction="ifRoom"
app:actionProviderClass="android.support.v7.widget.ShareActionProvider"/>
<item
android:id="#+id/pdf_action_print"
android:title="#string/pdf_action_print"
app:showAsAction="always|withText"/>
</menu>
</item>
<item android:id="#+id/pdf_action_tools"
android:title="#string/pdf_action_tools"
android:icon="#drawable/ic_pdf_action_tools"
android:orderInCategory="100"
app:showAsAction="ifRoom">
<menu>
<item
android:id="#+id/pdf_action_highlight"
android:title="#string/pdf_action_highlight"
app:showAsAction="always|withText"/>
<item
android:id="#+id/pdf_action_underline"
android:title="#string/pdf_action_underline"
app:showAsAction="always|withText"/>
<item
android:id="#+id/pdf_action_strikeout"
android:title="#string/pdf_action_strikeout"
app:showAsAction="always|withText"/>
<item
android:id="#+id/pdf_action_pen"
android:title="#string/pdf_action_pen"
app:showAsAction="always|withText"/>
</menu>
</item>
REPLACEMENT MENU:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<group android:id="#+id/group_search_mode">
<item
android:id="#+id/pdf_menu_search_item"
android:title="#string/search"
android:icon="#drawable/ic_pdf_action_search"
app:showAsAction="always|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView"/>
<item
android:id="#+id/pdf_menu_search_prev"
android:title="#string/search_prev"
android:icon="#drawable/ic_pdf_action_search_prev"
app:showAsAction="always" />
<item
android:id="#+id/pdf_menu_search_next"
android:title="#string/search_next"
android:icon="#drawable/ic_pdf_action_search_next"
app:showAsAction="always" />
</group>
This is activity:
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.ShareActionProvider;
import android.support.v7.widget.Toolbar;
import android.text.method.PasswordTransformationMethod;
import android.view.Menu;
import android.view.MenuItem;
public class MuPDFActivity extends AppCompatActivity implements FilePicker.FilePickerSupport
{
/* The core rendering instance */
enum TopBarMode {Main, Search, Annot, Delete, More, Accept};
enum AcceptMode {Highlight, Underline, StrikeOut, Ink, CopyText};
private TopBarMode mTopBarMode = TopBarMode.Main;
private AcceptMode mAcceptMode;
private SearchTask mSearchTask;
private SearchView mSearchView;
private MenuItem mSearchMenuPrev;
private MenuItem mSearchMenuNext;
private String mSearchString;
private ActionBar mActionBar;
private Toolbar toolbar;
// ***************************************************************************************************
//
// onCreate
//
// ***************************************************************************************************
#Override
public void onCreate(Bundle savedInstanceState)
{
/** Called when the activity is first created. */
getWindow().requestFeature(Window.FEATURE_ACTION_BAR | Window.FEATURE_ACTION_BAR_OVERLAY);
super.onCreate(savedInstanceState);
createUI(savedInstanceState);
}
// ***************************************************************************************************
//
// setupToolbar
//
// ***************************************************************************************************
private void setupToolbar()
{
//toolbar = (Toolbar) findViewById(R.id.toolbar);
if(toolbar != null)
{
setSupportActionBar(toolbar);
mActionBar = getSupportActionBar();
if(mActionBar != null)
{
mActionBar.setDisplayHomeAsUpEnabled(true);
mActionBar.setHomeButtonEnabled(true);
mActionBar.setDisplayShowHomeEnabled(false);
mActionBar.setDisplayUseLogoEnabled(false);
mActionBar.setIcon(null);
mActionBar.setBackgroundDrawable(new ColorDrawable(MINAppConfiguration.getSharedInstance().getCurrentVisualElements().tbTopBackgroundColor));
mActionBar.setTitle(pdfName);
}
}
if (Build.VERSION.SDK_INT >= 21)
{
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.setStatusBarColor(MINAppConfiguration.getSharedInstance().getCurrentVisualElements().tbStatusBarBackgroundColor);
}
}
// ***************************************************************************************************
//
// onCreateOptionsMenu
//
// ***************************************************************************************************
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.pdf_menu_main, menu);
MenuItem shareMenuItem = menu.findItem(R.id.pdf_action_share);
mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(shareMenuItem);
setShareIntent();
return true;
}
// ***************************************************************************************************
//
// onOptionsItemSelected
//
// ***************************************************************************************************
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
boolean bHandledEvent = false;
int id = item.getItemId();
switch (id)
{
case R.id.pdf_action_search:
bHandledEvent = true;
mActionModeSearch = this.startSupportActionMode(mActionModeSearchCallback);
break;
}
if(!bHandledEvent)
{
return super.onOptionsItemSelected(item);
}
else
{
return bHandledEvent;
}
}
// ***************************************************************************************************
//
// mActionModeEditCallback
//
// ***************************************************************************************************
protected ActionMode mActionModeSearch;
private ActionMode.Callback mActionModeSearchCallback = new ActionMode.Callback()
{
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu)
{
actionMode.getMenuInflater().inflate(R.menu.pdf_menu_search, menu);
mSearchMenuPrev = (MenuItem) menu.findItem(R.id.pdf_menu_search_prev);
mSearchMenuPrev.setEnabled(false);
mSearchMenuNext = (MenuItem) menu.findItem(R.id.pdf_menu_search_next);
mSearchMenuNext.setEnabled(false);
//mSearchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.pdf_menu_search_item));
// TODO this search functionality still isn't working
MenuItem searchItem = menu.findItem(R.id.pdf_menu_search_item);
mSearchView=(SearchView)MenuItemCompat.getActionView(searchItem);
if(mSearchView != null)
{
mSearchView.setIconifiedByDefault(false);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
{
#Override
public boolean onQueryTextSubmit(String s)
{
return false;
}
#Override
public boolean onQueryTextChange(String s)
{
mSearchString = s;
if(s.length() > 0)
{
mSearchMenuPrev.setEnabled(true);
mSearchMenuNext.setEnabled(true);
}
// Remove any previous search results
if (SearchTaskResult.get() != null && !mSearchString.equals(SearchTaskResult.get().txt))
{
SearchTaskResult.set(null);
mDocView.resetupChildren();
}
return false;
}
});
searchModeOn();
}
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu)
{
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem)
{
switch(menuItem.getItemId())
{
case R.id.pdf_menu_search_prev:
mSearchView.clearFocus();
hideKeyboard();
search(-1);
return true;
case R.id.pdf_menu_search_next:
mSearchView.clearFocus();
hideKeyboard();
search(1);
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode actionMode)
{
searchModeOff();
bPopoverLoaded = false;
mActionModeEdit = null;
mActionModeSearch = null;
resetHideToolbarsTimer();
}
};
// ***************************************************************************************************
//
// createUI
//
// ***************************************************************************************************
public void createUI(Bundle savedInstanceState)
{
if (core == null)
return;
// Now create the UI.
// First create the document view
mDocView = new MuPDFReaderView(this) {
#Override
protected void onMoveToChild(int i) {
if (core == null)
return;
mPageNumberView.setText(String.format("%d / %d", i + 1,
core.countPages()));
mPageSlider.setMax((core.countPages() - 1) * mPageSliderRes);
mPageSlider.setProgress(i * mPageSliderRes);
super.onMoveToChild(i);
}
#Override
protected void onTapMainDocArea()
{
// Hide/Show action bar
if(isToolbarsVisible())
{
setToolbarsVisible(false);
}
else
{
setToolbarsVisible(true);
}
}
#Override
protected void onDocMotion() {
hideButtons();
}
#Override
protected void onHit(Hit item) {
switch (mTopBarMode) {
case Annot:
if (item == Hit.Annotation) {
showButtons();
mTopBarMode = TopBarMode.Delete;
//mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal());
}
break;
case Delete:
mTopBarMode = TopBarMode.Annot;
default:
// Not in annotation editing mode, but the pageview will
// still select and highlight hit annotations, so
// deselect just in case.
MuPDFView pageView = (MuPDFView) mDocView.getDisplayedView();
if (pageView != null)
pageView.deselectAnnotation();
break;
}
}
};
mDocView.setAdapter(new MuPDFPageAdapter(this, this, core));
mSearchTask = new SearchTask(this, core)
{
#Override
protected void onTextFound(SearchTaskResult result)
{
SearchTaskResult.set(result);
// Ask the ReaderView to move to the resulting page
mDocView.setDisplayedViewIndex(result.pageNumber);
// Make the ReaderView act on the change to SearchTaskResult
// via overridden onChildSetup method.
mDocView.resetupChildren();
}
};
// Make the buttons overlay, and store all its
// controls in variables
makeButtonsView();
// Set up the page slider
int smax = Math.max(core.countPages()-1,1);
mPageSliderRes = ((10 + smax - 1)/smax) * 2;
// Activate the seekbar
mPageSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
{
public void onStopTrackingTouch(SeekBar seekBar)
{
mDocView.setDisplayedViewIndex((seekBar.getProgress()+mPageSliderRes/2)/mPageSliderRes);
}
public void onStartTrackingTouch(SeekBar seekBar)
{
}
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
updatePageNumView((progress+mPageSliderRes/2)/mPageSliderRes);
}
});
if (savedInstanceState == null || !savedInstanceState.getBoolean("ButtonsHidden", false))
showButtons();
// Stick the document view and the buttons overlay into a parent view
RelativeLayout layout = new RelativeLayout(this);
layout.addView(mDocView);
layout.addView(mButtonsView);
toolbar = new Toolbar(this);
//toolbar.setMinimumWidth(android.app.ActionBar.LayoutParams.MATCH_PARENT);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
toolbar.setLayoutParams(layoutParams);
layout.addView(toolbar);
//RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) layout.getLayoutParams();
//params.width = android.app.ActionBar.LayoutParams.MATCH_PARENT;
setContentView(layout);
// Setup New Toolbar implementation
setupToolbar();
// Set up custom colors, etc...
setCustomAttributes();
}
// ***************************************************************************************************
//
// onResume
//
// ***************************************************************************************************
#Override
public void onResume()
{
super.onResume();
// Start timer to hide toolbars.
bPopoverLoaded = false;
resetHideToolbarsTimer();
}
private void showButtons()
{
if (core == null)
return;
if (!mButtonsVisible)
{
mButtonsVisible = true;
// Update page number text and slider
int index = mDocView.getDisplayedViewIndex();
updatePageNumView(index);
mPageSlider.setMax((core.countPages()-1)*mPageSliderRes);
mPageSlider.setProgress(index*mPageSliderRes);
if (mTopBarMode == TopBarMode.Search)
{
//mSearchText.requestFocus();
showKeyboard();
}
Animation anim = new TranslateAnimation(0, 0, mPageSlider.getHeight(), 0);
anim.setDuration(200);
anim.setAnimationListener(new Animation.AnimationListener()
{
public void onAnimationStart(Animation animation) {
mPageSlider.setVisibility(View.VISIBLE);
}
public void onAnimationRepeat(Animation animation) {}
public void onAnimationEnd(Animation animation) {
mPageNumberView.setVisibility(View.VISIBLE);
}
});
mPageSlider.startAnimation(anim);
}
}
private void hideButtons()
{
if (mButtonsVisible)
{
mButtonsVisible = false;
hideKeyboard();
Animation anim = new TranslateAnimation(0, 0, 0, mPageSlider.getHeight());
anim.setDuration(200);
anim.setAnimationListener(new Animation.AnimationListener()
{
public void onAnimationStart(Animation animation)
{
mPageNumberView.setVisibility(View.INVISIBLE);
}
public void onAnimationRepeat(Animation animation) {}
public void onAnimationEnd(Animation animation)
{
mPageSlider.setVisibility(View.INVISIBLE);
}
});
mPageSlider.startAnimation(anim);
}
}
private void searchModeOn()
{
if (mTopBarMode != TopBarMode.Search)
{
mTopBarMode = TopBarMode.Search;
//Focus on EditTextWidget
showKeyboard();
}
}
private void searchModeOff()
{
if (mTopBarMode == TopBarMode.Search)
{
mTopBarMode = TopBarMode.Main;
hideKeyboard();
SearchTaskResult.set(null);
// Make the ReaderView act on the change to mSearchTaskResult
// via overridden onChildSetup method.
mDocView.resetupChildren();
}
}
private void makeButtonsView()
{
mButtonsView = getLayoutInflater().inflate(R.layout.buttons,null);
mPageNumberView = (TextView)mButtonsView.findViewById(R.id.pageNumber);
mPageNumberView.setVisibility(View.INVISIBLE);
mInfoView = (TextView)mButtonsView.findViewById(R.id.info);
mInfoView.setVisibility(View.INVISIBLE);
mPageSlider = (SeekBar)mButtonsView.findViewById(R.id.pageSlider);
mPageSlider.setVisibility(View.INVISIBLE);
}
private void search(int direction)
{
hideKeyboard();
int displayPage = mDocView.getDisplayedViewIndex();
SearchTaskResult r = SearchTaskResult.get();
int searchPage = r != null ? r.pageNumber : -1;
mSearchTask.go(mSearchString, direction, displayPage, searchPage);
}
#Override
public boolean onSearchRequested()
{
if (mButtonsVisible && mTopBarMode == TopBarMode.Search)
{
hideButtons();
}
else
{
showButtons();
searchModeOn();
}
return super.onSearchRequested();
}
#Override
public boolean onPrepareOptionsMenu(Menu menu)
{
if (mButtonsVisible && mTopBarMode != TopBarMode.Search) {
hideButtons();
} else {
showButtons();
searchModeOff();
}
return super.onPrepareOptionsMenu(menu);
}
}
EDIT
One item of note: the call get getActionView on the search item is returning null. I think this might have something to do with the problem. I then try and force it but I'm not sure that's right either. Here is the code in question:
protected ActionMode mActionModeSearch;
private ActionMode.Callback mActionModeSearchCallback = new ActionMode.Callback()
{
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu)
{
actionMode.getMenuInflater().inflate(R.menu.pdf_menu_search, menu);
mSearchMenuPrev = (MenuItem) menu.findItem(R.id.pdf_menu_search_prev);
mSearchMenuPrev.setEnabled(false);
mSearchMenuNext = (MenuItem) menu.findItem(R.id.pdf_menu_search_next);
mSearchMenuNext.setEnabled(false);
mSearchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.pdf_menu_search_item));
// TODO this search functionality still isn't working
MenuItem searchItem = menu.findItem(R.id.pdf_menu_search_item);
mSearchView=(SearchView)MenuItemCompat.getActionView(searchItem); // ALWAYS COMES BACK AS NULL
if(mSearchView==null)
{
//MenuItemCompat.setShowAsAction(searchItem,MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW|MenuItem.SHOW_AS_ACTION_ALWAYS);
MenuItemCompat.setShowAsAction(searchItem, MenuItem.SHOW_AS_ACTION_ALWAYS);
mSearchView = new SearchView(MuPDFActivity.this);
MenuItemCompat.setActionView(searchItem, mSearchView);
}
if(mSearchView != null)
{
mSearchView.setIconifiedByDefault(false);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
{
#Override
public boolean onQueryTextSubmit(String s)
{
return false;
}
#Override
public boolean onQueryTextChange(String s)
{
mSearchString = s;
if(s.length() > 0)
{
mSearchMenuPrev.setEnabled(true);
mSearchMenuNext.setEnabled(true);
}
// Remove any previous search results
if (SearchTaskResult.get() != null && !mSearchString.equals(SearchTaskResult.get().txt))
{
SearchTaskResult.set(null);
mDocView.resetupChildren();
}
return false;
}
});
searchModeOn();
}
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu)
{
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem)
{
switch(menuItem.getItemId())
{
case R.id.pdf_menu_search_prev:
mSearchView.clearFocus();
hideKeyboard();
search(-1);
return true;
case R.id.pdf_menu_search_next:
mSearchView.clearFocus();
hideKeyboard();
search(1);
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode actionMode)
{
searchModeOff();
bPopoverLoaded = false;
mActionModeEdit = null;
mActionModeSearch = null;
resetHideToolbarsTimer();
}
};
EDIT 2:
I got the control to come up but now the "next" and "prev" menu items are gone. Also, the control is not left aligned. And, I still have to expand the search control.
Screenshot:
Here is the updated code that got me here:
public boolean onCreateActionMode(ActionMode actionMode, Menu menu)
{
actionMode.getMenuInflater().inflate(R.menu.pdf_menu_search, menu);
mSearchMenuPrev = menu.findItem(R.id.pdf_menu_search_prev);
mSearchMenuPrev.setEnabled(false);
mSearchMenuNext = menu.findItem(R.id.pdf_menu_search_next);
mSearchMenuNext.setEnabled(false);
MenuItem searchItem = menu.findItem(R.id.pdf_menu_search_item);
MenuItemCompat.setShowAsAction(searchItem, MenuItem.SHOW_AS_ACTION_ALWAYS);
mSearchView = new SearchView(MuPDFActivity.this);
MenuItemCompat.setActionView(searchItem, mSearchView);
//mSearchView.setIconifiedByDefault(false);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
{
#Override
public boolean onQueryTextSubmit(String s)
{
return false;
}
#Override
public boolean onQueryTextChange(String s)
{
mSearchString = s;
if(s.length() > 0)
{
mSearchMenuPrev.setEnabled(true);
mSearchMenuNext.setEnabled(true);
}
// Remove any previous search results
if (SearchTaskResult.get() != null && !mSearchString.equals(SearchTaskResult.get().txt))
{
SearchTaskResult.set(null);
mDocView.resetupChildren();
}
return false;
}
});
searchModeOn();
return true;
}
If I call mSearchView.setIconified(false), I get the following screenshots. The menu items are all there but they are in overflow. If I expand overflow, I see the search menu but when I click on it, it goes back to my original problem of no edit box to enter search string. In other words, it looks like the first screenshot below when I click on "Search":

I finally had to build it manually. I changed the menu xml file to:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<group android:id="#+id/group_search_mode">
<item
android:id="#+id/pdf_menu_search_item"
android:title="#string/search"
android:icon="#drawable/ic_pdf_action_search"
app:showAsAction="ifRoom"
app:actionViewClass="android.support.v7.widget.SearchView"/>
</group>
I then changed the code in the ActionMode.Callback to manually build the menu and force the search control open. I think it might be overkill but it works:
private static final int PREV_MENU_ITEM_ID = 1;
private static final int NEXT_MENU_ITEM_ID = 2;
protected ActionMode mActionModeSearch;
private ActionMode.Callback mActionModeSearchCallback = new ActionMode.Callback()
{
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu)
{
actionMode.getMenuInflater().inflate(R.menu.pdf_menu_search, menu);
// Load search action
MenuItem searchItem = menu.findItem(R.id.pdf_menu_search_item);
MenuItemCompat.setShowAsAction(searchItem, MenuItem.SHOW_AS_ACTION_ALWAYS);
mSearchView = new SearchView(MuPDFActivity.this);
MenuItemCompat.setActionView(searchItem, mSearchView);
MenuItemCompat.expandActionView(searchItem);
mSearchView.setIconifiedByDefault(false);
mSearchView.setIconified(false);
// Load prev and next menu items
mSearchMenuPrev = menu.add(0, PREV_MENU_ITEM_ID, 1, R.string.search_prev);
mSearchMenuPrev.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
mSearchMenuPrev.setEnabled(false);
mSearchMenuNext = menu.add(0, NEXT_MENU_ITEM_ID, 1, R.string.search_next);
mSearchMenuNext.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
mSearchMenuNext.setEnabled(false);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
{
#Override
public boolean onQueryTextSubmit(String s)
{
search(1);
return false;
}
#Override
public boolean onQueryTextChange(String s)
{
mSearchString = s;
if(s.length() > 0)
{
mSearchMenuPrev.setEnabled(true);
mSearchMenuNext.setEnabled(true);
}
// Remove any previous search results
if (SearchTaskResult.get() != null && !mSearchString.equals(SearchTaskResult.get().txt))
{
SearchTaskResult.set(null);
mDocView.resetupChildren();
}
return false;
}
});
searchModeOn();
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu)
{
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem)
{
switch(menuItem.getItemId())
{
case PREV_MENU_ITEM_ID:
mSearchView.clearFocus();
hideKeyboard();
search(-1);
return true;
case NEXT_MENU_ITEM_ID:
mSearchView.clearFocus();
hideKeyboard();
search(1);
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode actionMode)
{
searchModeOff();
bPopoverLoaded = false;
mActionModeEdit = null;
mActionModeSearch = null;
resetHideToolbarsTimer();
}
};
I hope this helps someone out there. What a pain!

Related

How to hightlight the typed text in searchview in android

Hi in the MainActivity I was Implemented a Different Fragments.Now toolbar contains a searchview functionality I was added in my Activity.
Now I search for text all the fragement are also searching for same text.But I want to clear the text which one i typed for last fragement.
MainActivity:
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
setSearchtollbar();
public void setSearchtollbar()
{
searchtollbar = (Toolbar) findViewById(R.id.searchtoolbar);
if (searchtollbar != null) {
searchtollbar.inflateMenu(R.menu.menu_search);
search_menu=searchtollbar.getMenu();
searchtollbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
circleReveal(R.id.searchtoolbar,1,true,false);
else
searchtollbar.setVisibility(View.GONE);
}
});
item_search = search_menu.findItem(R.id.action_filter_search);
MenuItemCompat.setOnActionExpandListener(item_search, new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
// Do something when collapsed
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
circleReveal(R.id.searchtoolbar,1,true,false);
}
else
searchtollbar.setVisibility(View.GONE);
return true;
}
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
// Do something when expanded
return true;
}
});
initSearchView();
} else
Log.d("toolbar", "setSearchtollbar: NULL");
}
public void initSearchView()
{
final SearchView searchView = (SearchView) search_menu.findItem(R.id.action_filter_search).getActionView();
// Enable/Disable Submit button in the keyboard
searchView.setSubmitButtonEnabled(false);
// Change search close button image
ImageView closeButton = searchView.findViewById(R.id.search_close_btn);
closeButton.setImageResource(R.drawable.ic_close_black_24dp);
// closeButton.setImageResource(ContextCompat.getDrawable(getApplication(), R.drawable.ic_close_black_24dp));
// set hint and the text colors
EditText txtSearch = ((EditText) searchView.findViewById(R.id.search_src_text));
txtSearch.setHint("Search..");
txtSearch.setHintTextColor(Color.DKGRAY);
txtSearch.setTextColor(getResources().getColor(R.color.colorPrimary));
// set the cursor
AutoCompleteTextView searchTextView = (AutoCompleteTextView) searchView.findViewById(R.id.search_src_text);
try {
Field mCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
mCursorDrawableRes.setAccessible(true);
mCursorDrawableRes.set(searchTextView, R.drawable.search_cursor); //This sets the cursor resource ID to 0 or #null which will make it visible on white background
} catch (Exception e) {
e.printStackTrace();
}
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
callSearch(query);
searchView.clearFocus();
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
callSearch(newText);
return true;
}
public void callSearch(String query) {
Log.i("query", "" + query);
}
});
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void circleReveal(int viewID, int posFromRight, boolean containsOverflow, final boolean isShow)
{
final View myView = findViewById(viewID);
int width=myView.getWidth();
if(posFromRight>0)
width-=(posFromRight*getResources().getDimensionPixelSize(R.dimen.abc_action_button_min_width_material))-(getResources().getDimensionPixelSize(R.dimen.abc_action_button_min_width_material)/ 2);
if(containsOverflow)
width-=getResources().getDimensionPixelSize(R.dimen.abc_action_button_min_width_overflow_material);
int cx=width;
int cy=myView.getHeight()/2;
Animator anim;
if(isShow)
anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0,(float)width);
else
anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, (float)width, 0);
anim.setDuration((long)220);
// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
if(!isShow)
{
super.onAnimationEnd(animation);
myView.setVisibility(View.INVISIBLE);
}
}
});
// make the view visible and start the animation
if(isShow)
myView.setVisibility(View.VISIBLE);
// start the animation
anim.start();
}
Fragment:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.search:
return true;
case R.id.refresh:
fetchJSON();
return true;
}
return true;
}
Menu:
<item android:id="#+id/search"
android:orderInCategory="0"
android:title="search"
android:icon="#drawable/ic_search"
app:showAsAction="always"/>

Filter working text is not highlighting in recyclerview in android [duplicate]

Hi in the MainActivity I was Implemented a Different Fragments.Now toolbar contains a searchview functionality I was added in my Activity.
Now I search for text all the fragement are also searching for same text.But I want to clear the text which one i typed for last fragement.
MainActivity:
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
setSearchtollbar();
public void setSearchtollbar()
{
searchtollbar = (Toolbar) findViewById(R.id.searchtoolbar);
if (searchtollbar != null) {
searchtollbar.inflateMenu(R.menu.menu_search);
search_menu=searchtollbar.getMenu();
searchtollbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
circleReveal(R.id.searchtoolbar,1,true,false);
else
searchtollbar.setVisibility(View.GONE);
}
});
item_search = search_menu.findItem(R.id.action_filter_search);
MenuItemCompat.setOnActionExpandListener(item_search, new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
// Do something when collapsed
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
circleReveal(R.id.searchtoolbar,1,true,false);
}
else
searchtollbar.setVisibility(View.GONE);
return true;
}
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
// Do something when expanded
return true;
}
});
initSearchView();
} else
Log.d("toolbar", "setSearchtollbar: NULL");
}
public void initSearchView()
{
final SearchView searchView = (SearchView) search_menu.findItem(R.id.action_filter_search).getActionView();
// Enable/Disable Submit button in the keyboard
searchView.setSubmitButtonEnabled(false);
// Change search close button image
ImageView closeButton = searchView.findViewById(R.id.search_close_btn);
closeButton.setImageResource(R.drawable.ic_close_black_24dp);
// closeButton.setImageResource(ContextCompat.getDrawable(getApplication(), R.drawable.ic_close_black_24dp));
// set hint and the text colors
EditText txtSearch = ((EditText) searchView.findViewById(R.id.search_src_text));
txtSearch.setHint("Search..");
txtSearch.setHintTextColor(Color.DKGRAY);
txtSearch.setTextColor(getResources().getColor(R.color.colorPrimary));
// set the cursor
AutoCompleteTextView searchTextView = (AutoCompleteTextView) searchView.findViewById(R.id.search_src_text);
try {
Field mCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
mCursorDrawableRes.setAccessible(true);
mCursorDrawableRes.set(searchTextView, R.drawable.search_cursor); //This sets the cursor resource ID to 0 or #null which will make it visible on white background
} catch (Exception e) {
e.printStackTrace();
}
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
callSearch(query);
searchView.clearFocus();
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
callSearch(newText);
return true;
}
public void callSearch(String query) {
Log.i("query", "" + query);
}
});
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void circleReveal(int viewID, int posFromRight, boolean containsOverflow, final boolean isShow)
{
final View myView = findViewById(viewID);
int width=myView.getWidth();
if(posFromRight>0)
width-=(posFromRight*getResources().getDimensionPixelSize(R.dimen.abc_action_button_min_width_material))-(getResources().getDimensionPixelSize(R.dimen.abc_action_button_min_width_material)/ 2);
if(containsOverflow)
width-=getResources().getDimensionPixelSize(R.dimen.abc_action_button_min_width_overflow_material);
int cx=width;
int cy=myView.getHeight()/2;
Animator anim;
if(isShow)
anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0,(float)width);
else
anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, (float)width, 0);
anim.setDuration((long)220);
// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
if(!isShow)
{
super.onAnimationEnd(animation);
myView.setVisibility(View.INVISIBLE);
}
}
});
// make the view visible and start the animation
if(isShow)
myView.setVisibility(View.VISIBLE);
// start the animation
anim.start();
}
Fragment:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.search:
return true;
case R.id.refresh:
fetchJSON();
return true;
}
return true;
}
Menu:
<item android:id="#+id/search"
android:orderInCategory="0"
android:title="search"
android:icon="#drawable/ic_search"
app:showAsAction="always"/>

How to replace Android Toolbar icons programmatically?

I have a ListView and a Toolbar above of it in my Activity. I want to replace the Toolbar default icons (search and settings) with delete and edit icons when clicking an item of the ListView to perform some action.
So what I've understood from your question, you're looking for ActionMode which might serve your purpose.
So here's an implementation guideline.
Declare an ActionMode in your Activity and let your Activity to implement ActionMode.Callback.
public class YourActivity extends AppCompatActivity implements ActionMode.Callback {
// Declare ActionMode here
private ActionMode actionMode;
// Now implement the callback functions for ActionMode
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
#Override
public boolean onCreateActionMode(final ActionMode actionMode, Menu menu) {
MenuInflater inflater = actionMode.getMenuInflater();
// Inflate your menu here
inflater.inflate(R.menu.list_item_click_menu, menu);
return true;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.action_delete:
// Do something
actionMode.finish();
return true;
case R.id.action_edit:
// Do something
actionMode.finish();
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode actionMode) {
try {
this.actionMode = null;
// Do something. Reset the views maybe?
} catch (Exception e) {
e.printStackTrace();
}
}
}
Now to initiate your ActionMode you need to have this in your onClick function of the list item.
listItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (actionMode != null) {
return true;
}
// Show ActionMode
actionMode = startSupportActionMode(this);
actionMode.invalidate();
}
});
You may need to reset the ActionMode sometimes.
#Override
public void onResume() {
super.onResume();
if (actionMode != null) {
actionMode.finish();
actionMode = null;
}
}

MenuItemCompat.setOnActionExpandListener doesn't do anything

Background
I have a searchView being initialized using a special class I've made, that's being used across all of the activities and fragments.
The problem
Recently, probably due to updates to the support library (or because I didn't use it so far, I don't remember), I can't catch events of expand/collapse of the searchView.
As I've found, this happens even if I use setSupportActionBar with a Toolbar instance.
What I've tried
I've tried using each of the next methods, but none worked:
MenuItemCompat.setOnActionExpandListener.
MenuItemCompat.setOnActionExpandListener together with iconifying the SearchView, as suggested on some websites.
setOnActionExpandListener on the search menu item itself, but then it crashes since it can't be used when extending the ActionBarActivity.
SearchView.setOnCloseListener , but this works only if I close it, and only using the UI (doesn't get called when calling collapseActionView ).
I've also tried to mess around with the XML file of the search menu item.
The code
Here's the helper class I've made:
SearchHolderCompat
public class SearchHolderCompat {
public MenuItem mSearchMenuItem;
public SearchView mSearchView;
private final Activity _context;
public SearchHolderCompat(final Activity context) {
_context = context;
}
public boolean isCurrentyExpanded() {
return mSearchMenuItem != null && MenuItemCompat.isActionViewExpanded(mSearchMenuItem);
}
public boolean hasQuery() {
return mSearchMenuItem != null && mSearchView != null && MenuItemCompat.isActionViewExpanded(mSearchMenuItem)
&& !TextUtils.isEmpty(mSearchView.getQuery());
}
public void addSearchItemAndInit(final Menu menu, final OnQueryTextListener onQueryTextListener,
final OnActionExpandListener onActionExpandListener) {
final MenuInflater menuInflater = _context.getMenuInflater();
menuInflater.inflate(R.menu.search_menu_item, menu);
init(menu.findItem(R.id.menuItem_search), onQueryTextListener, onActionExpandListener);
}
public void init(final MenuItem searchMenuItem, final OnQueryTextListener onQueryTextListener,
final OnActionExpandListener onActionExpandListener) {
this.mSearchMenuItem = searchMenuItem;
mSearchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem);
if (mSearchView == null) {
MenuItemCompat.setShowAsAction(searchMenuItem, MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW
| MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
MenuItemCompat.setActionView(searchMenuItem, mSearchView = new SearchView(_context));
}
mSearchView.setQueryHint(_context.getString(R.string.search));
mSearchView.setOnQueryTextListener(onQueryTextListener);
MenuItemCompat.setOnActionExpandListener(searchMenuItem, onActionExpandListener);
}
}
MainActivity.java
public class MainActivity extends ActionBarActivity {
SearchHolderCompat mSearchHolder = new SearchHolderCompat(this);
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
mSearchHolder.addSearchItemAndInit(menu, new OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(final String arg0) {
android.util.Log.d("AppLog", "onQueryTextSubmit");
return false;
}
#Override
public boolean onQueryTextChange(final String queryText) {
android.util.Log.d("AppLog", "onQueryTextChange");
return true;
}
}, new OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(final MenuItem arg0) {
android.util.Log.d("AppLog", "onMenuItemActionExpand");
return false;
}
#Override
public boolean onMenuItemActionCollapse(final MenuItem arg0) {
android.util.Log.d("AppLog", "onMenuItemActionCollapse");
return false;
}
});
return true;
}
}
search_menu_item.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<!-- search items -->
<item
android:id="#+id/menuItem_search"
android:icon="#drawable/ic_action_search"
android:title="#string/search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"
tools:ignore="AlwaysShowAction"/>
</menu>
The question
What's the correct way to handle the SearchView and the search menu item (using the support library) ?
How come "MenuItemCompat.setOnActionExpandListener" doesn't work?
After looking for a solution for couple of hours I've implement something like this. and worked for me. (I wanted Expand and Collapse events anyhow)
.
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.menu_main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
if(searchItem != null)
{
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
// use this method for search process
searchView.setOnSearchClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//Search view is expanded
showSearchPage();
}
});
searchView.setOnCloseListener(new SearchView.OnCloseListener()
{
#Override
public boolean onClose()
{
//Search View is collapsed
hideSearchPage();
return false;
}
});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
{
#Override
public boolean onQueryTextSubmit(String query)
{
// use this method when query submitted
Toast.makeText(MainActivity.this, query, Toast.LENGTH_SHORT).show();
return false;
}
#Override
public boolean onQueryTextChange(String newText)
{
// use this method for auto complete search process
Log.e("SearchValueIs",":"+newText);
return false;
}
});
}
return super.onCreateOptionsMenu(menu);
}
Hope It will help Someone...
Android training
app:showAsAction="ifRoom|collapseActionView"
You can add ViewTreeObserver to track the visibility state of android.support.v7.appcompat.R.id.search_edit_frame. You can check my answer here: https://stackoverflow.com/a/28762632/1633609
You can see below how to handle Expand and Collapsed states!
To answer why MenuItemCompat.setOnActionExpandListener(...) is not working, this listener is only called if the showAsAction of the SearchView is set to MenuItemCompat.SHOW_AS_ACTION_ALWAYS (you can also add more options).
This is the copy of my answer form the other question:
I found that MenuItemCompat.setOnActionExpandListener(...) is not working if you don't pass:
searchItem
.setShowAsAction(MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW
| MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
But this is changing the SearchView and is replacing the DrawerToggle with back arrow.
I wanted to keep the original views and still track the Expanded/Collapsed state and use supported Search View.
Solution:
When android.support.v7.widget.SearchView is changing the view state the LinearLayout view's, with id android.support.v7.appcompat.R.id.search_edit_frame, visibility value is being changed from View.VISIBLE to View.GONE and opposite. So I add ViewTreeObserver to track the visibility change of the search edit frame.
menu_search.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<item
android:id="#+id/action_search"
android:icon="#android:drawable/ic_menu_search"
android:title="#string/search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"/>
</menu>
In the activity:
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.SearchView;
import android.view.Menu;
import android.view.MenuItem;
..........
private View mSearchEditFrame;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_search, menu);
MenuItem searchItem = (MenuItem) menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat
.getActionView(searchItem);
searchView.setSubmitButtonEnabled(false);
mSearchEditFrame = searchView
.findViewById(android.support.v7.appcompat.R.id.search_edit_frame);
ViewTreeObserver vto = mSearchEditFrame.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
int oldVisibility = -1;
#Override
public void onGlobalLayout() {
int currentVisibility = mSearchEditFrame.getVisibility();
if (currentVisibility != oldVisibility) {
if (currentVisibility == View.VISIBLE) {
Log.v(TAG, "EXPANDED");
} else {
Log.v(TAG, "COLLAPSED");
}
oldVisibility = currentVisibility;
}
}
});
return super.onCreateOptionsMenu(menu);
}
I know I'm very late to post this answer but hope it helps someone else. I recently came across the issue and I just made the Override methods return true and it worked like a charm.
#Override
public boolean onMenuItemActionExpand(final MenuItem arg0) {
android.util.Log.d("AppLog", "onMenuItemActionExpand");
return true;
}
#Override
public boolean onMenuItemActionCollapse(final MenuItem arg0) {
android.util.Log.d("AppLog", "onMenuItemActionCollapse");
return true;
}
In more recent versions
menuSearch.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
//SearchView appers
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
//SearchView disappears
return true;
}
});

SearchView in ActionBar -- problems with the *Up* button

I am using the the SearchView in the ActionBar of the ListView. The magnifying glass can be touched, the SearchView shows its edit box, and the user can enter the text for filtering the content of the list. It almost works. However, when the user presses the Up button, the SearchView collapses back to the icon, the text inside the widget is cleared, and the filtering is reset. The effect (in my case) is that the list can be filtered only when the SearchView is not iconified. The wanted behaviour is to keep the filter text also after the SearchView was collapsed.
Attention: The behaviour probably changed in Android 4.3. With 4.2.2 it worked as wanted. See the observations below.
Details: To be more specific, the menu contains the following item:
<item android:id="#+id/menu_search_customers"
android:title="#string/menu_search_text"
android:icon="#android:drawable/ic_menu_search"
android:showAsAction="ifRoom|collapseActionView"
android:actionViewClass="android.widget.SearchView" />
Notice the icon and the android:showAsAction. I belive the Up button appears by default when the SearchView is expanded (by Up I mean the < plus the icon -- see the right image with the blue book from the official Navigation with Back and Up). It seems that the default handler implementation just collapses the expanded SearchView (returns back to the icon state).
When debugging, I have found that the onQueryTextChange() is fired with the empty text when the Up is used. (I believe this was not the case with Android 4.2.2, because it worked as wanted before the OS update.) This is the reason why the filtering of the list items is also reset -- see my onQueryTextChange() below. I want the SearchView collapsed, and the filter text displayed as subtitle in the action bar.
So far, my code related to the SearchView looks like this:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// MenuInflater adds the magnifying glass icon for the SearchView
// to the ActionBar as the always visible menu item.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.customers_menu, menu);
// Get the related SearchView widget.
SearchView sv = (SearchView) menu.findItem(R.id.menu_search_customers)
.getActionView();
// Get the changes immediately.
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
// I am not sure whether the onQueryTextSubmit() is important
// for the purpose.
#Override
public boolean onQueryTextSubmit(String query) {
getActionBar().setSubtitle(mCurFilter);
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
// The newText is stored into a member variable that
// is used when the new CursorLoader is created.
mCurFilter = newText;
getActionBar().setSubtitle(mCurFilter);
getLoaderManager().restartLoader(0, null,
CustomersOverviewActivity.this);
return true;
}
});
return true;
}
The restarted loader calls the onCreateLoader. Notice the mCurFilter is used for building the SQL query:
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = { CustomerTable._ID,
CustomerTable.CODE,
CustomerTable.NAME,
CustomerTable.STREET,
CustomerTable.TOWN };
String selection = null; // init
String[] selectionArgs = null; // init
if ( ! mCurFilter.isEmpty()) {
selection = CustomerTable.NAME + " like ?";
selectionArgs = new String[]{ "%" + mCurFilter +"%" };
}
CursorLoader cursorLoader = new CursorLoader(this,
DemoContentProvider.CUSTOMERS_CONTENT_URI, projection,
selection, selectionArgs,
orderInfo);
return cursorLoader;
}
I would like to detect the situation when the Up is pressed before the onQueryTextChange() is called. This way (say) I could set a flag and block the mCurFilter assignment by the emptied SearchView content. Also, when the search icon is expanded again, I would like to initialize the text in the expanded SearchView from the mCurFilter before it is shown (i.e. the expanded view is preset with the filter text). How that can be done?
Update: The earlier implementation of the SearchView had...
#Override
public void onActionViewCollapsed() {
clearFocus();
updateViewsVisibility(true);
mQueryTextView.setImeOptions(mCollapsedImeOptions);
mExpandedInActionView = false;
}
Now, it contains...
#Override
public void onActionViewCollapsed() {
setQuery("", false);
clearFocus();
updateViewsVisibility(true);
mQueryTextView.setImeOptions(mCollapsedImeOptions);
mExpandedInActionView = false;
}
Do you know what could be the reason for setting the query to the empty string? Should I override the new implementation by the old code? Or is there a better way?
I have written a StatefulSearchView which retains the text:
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
import android.widget.TextView;
public class StatefulSearchView extends SearchView implements android.view.View.OnLayoutChangeListener, OnQueryTextListener,android.widget.SearchView.OnCloseListener{
private boolean mSaveText=true;
private OnQueryTextListener mQueryListener;
private String mQuery;
private OnCloseListener mCloseListener;
private boolean fromIconify = true;
public StatefulSearchView(Context context, AttributeSet attrs) {
super(context, attrs);
addOnLayoutChangeListener(this);
super.setOnCloseListener(this);
}
public StatefulSearchView(Context context) {
super(context);
// TODO Auto-generated constructor stub
addOnLayoutChangeListener(this);
super.setOnCloseListener(this);
}
public void setSaveSearchTextState(boolean save){
this.mSaveText = save;
this.setSaveEnabled(mSaveText);
}
public void setOnStatefulQueryTextListener(OnQueryTextListener listener) {
mQueryListener = listener;
super.setOnQueryTextListener(this);
}
#Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if(super.isIconfiedByDefault() || !super.isIconified() && !TextUtils.isEmpty(mQuery) && mSaveText){
setSavedText(mQuery);
}
Log.i("onLayoutChanged()",""+mQuery);
}
#Override
public void setIconified(boolean iconify) {
mQuery = getQuery().toString();
Log.i("setIconified()",""+mQuery);
super.setOnCloseListener(null);
super.setIconified(iconify);
super.setIconified(iconify);
super.setOnCloseListener(this);
fromIconify = true;
}
#Override
public void setOnCloseListener(OnCloseListener listener) {
mCloseListener = listener;
super.setOnCloseListener(this);
}
#Override
protected Parcelable onSaveInstanceState() {
Parcelable state = super.onSaveInstanceState();
return new SearchQueryState(state, mQuery, mSaveText);
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
SearchQueryState sqs = (SearchQueryState)state;
super.onRestoreInstanceState(sqs.getSuperState());
mQuery = sqs.getSavedQuery();
mSaveText = sqs.getSaveText();
}
#Override
public boolean onQueryTextChange(String arg0) {
mQuery = arg0;
return mQueryListener.onQueryTextChange(mQuery);
}
#Override
public boolean onQueryTextSubmit(String arg0) {
// TODO Auto-generated method stub
return mQueryListener.onQueryTextSubmit(arg0);
}
private TextView getTextView(){
int searchTextViewId = getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
return (TextView) this.findViewById(searchTextViewId);
}
private void setSavedText(String s){
super.setOnQueryTextListener(null);
Log.i("setSavedText()",""+s);
TextView t = getTextView();
t.setText(s);
if(!TextUtils.isEmpty(s))
((EditText)t).setSelection(s.length());
super.setOnQueryTextListener(mQueryListener);
}
private class SearchQueryState extends BaseSavedState{
private boolean mSaveText;
private String mQueryText;
public SearchQueryState(Parcel arg0) {
super(arg0);
this.mQueryText = arg0.readString();
this.mSaveText = arg0.readInt() == 1;
}
public SearchQueryState(Parcelable superState, String queryText, boolean saveText) {
super(superState);
this.mQueryText = queryText;
this.mSaveText = saveText;
}
public boolean getSaveText(){
return this.mSaveText;
}
public String getSavedQuery(){
return mQueryText;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
super.writeToParcel(dest, flags);
dest.writeString(mQueryText);
dest.writeInt(mSaveText? 1: 0);
}
}
#Override
public boolean onClose() {
Log.i("onClose()", "Is from setIconified(): "+fromIconify);
if(!fromIconify){
mQuery = null;
fromIconify = false;
}
return mCloseListener == null ? false : mCloseListener.onClose();
}
}
In demonstration activity:
public class MainActivity extends Activity{
private StatefulSearchView mSearchView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getActionBar().setHomeButtonEnabled(true);
}
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
if(item.getItemId()==android.R.id.home) {
mSearchView.setIconified(true);
return true;
}
return super.onMenuItemSelected(featureId, item);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
MenuItem item = menu.findItem(R.id.action_search);
mSearchView =(StatefulSearchView)item.getActionView();
mSearchView.setSaveSearchTextState(true);
mSearchView.setOnStatefulQueryTextListener(new OnQueryTextListener(){
#Override
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
return false;
}});
return true;
}
In menu xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/action_search"
android:orderInCategory="100"
android:showAsAction="always"
android:actionViewClass="com.nikola.despotoski.saveablesearchview.StatefulSearchView"
android:title="#string/action_settings"/>
</menu>
In the source of the SearchView, it clearly says that they change the text to "":
#Override
public void onActionViewCollapsed() {
setQuery("", false);
clearFocus();
updateViewsVisibility(true);
mQueryTextView.setImeOptions(mCollapsedImeOptions);
mExpandedInActionView = false;
}
/**
* {#inheritDoc}
*/
#Override
public void onActionViewExpanded() {
if (mExpandedInActionView) return;
mExpandedInActionView = true;
mCollapsedImeOptions = mQueryTextView.getImeOptions();
mQueryTextView.setImeOptions(mCollapsedImeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN);
mQueryTextView.setText("");
setIconified(false);
}
Let me know if you have issues.
I'm not sure I understand your problem but you can just detect when up is clicked like this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
doSOmething();
return true;
}
return super.onOptionsItemSelected(item);
}
If you intercept the up click, you can presumably do anything you want here. Returning true will consume the event and that should prevent any default action from taking place. This way you can do whatever you want the up button to do while at the same time consuming the up event to prevent clearing of your filters.
I struggle with this a little until I found the solution.
Declare your menuItem like this, check the showAsAction attribute, type only ifRoom, if you set collapseActionView the widget will collapse and show the back button on the actionbar
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/search"
android:actionViewClass="android.widget.SearchView"
android:icon="#drawable/ic_2_action_search"
android:showAsAction="ifRoom"
android:title="#null"/>
</menu>
Set up your SearchView as usual, remember to Add setIconifiedByDefault this will make the icon to start up as an icon
SearchManager searchManager = (SearchManager)getSystemService(Context.SEARCH_SERVICE);
searchView = (SearchView) menu.findItem(R.id.search).getActionView();
searchView.setIconifiedByDefault(true);
searchView.setOnQueryTextListener(new SearchViewOnQueryListener());
searchView.setOnCloseListener(new SearchViewOnCloseListener());
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
On your QueryListener is where you handle the end of your search like so, here is where you use onActionViewCollapse() which collapse back the ViewSearch
#Override
public boolean onQueryTextSubmit(String query) {
makeSearchRequest(SEARCH_TYPE_KEYWORD, query);
searchView.setQuery("", false);
searchView.clearFocus();
searchView.onActionViewCollapsed();
buttonClearSearchResults.setVisibility(View.VISIBLE);
return false;
}

Categories

Resources