How to check that the action overflow PopupMenu is now showing?
It is need for me when I trying to auto-hide ActionBar, and don't need to hide when ActionBar's overflow popup is showing.
You can override Activity.onMenuOpened and Activity.onPanelClosed to determine when the overflow menu or other sub-menus are showing, such as the ShareActionProvider. Here's an example:
/** True if an options menu has been opened, false otherwise */
private boolean mMenuOpened;
#Override
public boolean onMenuOpened(int featureId, Menu menu) {
mMenuOpened = true;
return super.onMenuOpened(featureId, menu);
}
#Override
public void onPanelClosed(int featureId, Menu menu) {
super.onPanelClosed(featureId, menu);
mMenuOpened = false;
}
Alternatively
ActionBarView subclasses AbsActionBarView which contains AbsActionBarView.isOverflowMenuShowing. Since these class are internal and hidden, you'll need to access it via reflection.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final int actionBarViewId = getResources().getIdentifier("action_bar", "id", "android");
final View actionBarView = findViewById(actionBarViewId);
actionBarView.postDelayed(new Runnable() {
#Override
public void run() {
System.out.println(isOverflowMenuShowing(actionBarView));
}
}, 2500);
}
private static boolean isOverflowMenuShowing(View actionBarView) {
try {
final Class<?> abv = Class.forName("com.android.internal.widget.ActionBarView");
final Method isOverflowShowing = abv.getMethod("isOverflowMenuShowing", new Class[] {});
return (boolean) isOverflowShowing.invoke(actionBarView, new Object[] {});
} catch (final Exception ignored) {
// Nothing to do
}
return false;
}
Related
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!
I'm using native ActionBar and ShareActionProvider.
There is a code in my activity that hides ActionBar in four seconds:
Handler hideUIHandler = new Handler();
hideUIHandler.postDelayed(new Runnable() {
public void run() {
getActionBar().hide();
}
}, 4000);
Unfortunately hideUIHandler hides ActionBar even when I clicked the "Share" item to see menu providing by ShareActionProvider.
I don't want to hide ActionBar in that case. What should I do?
You can override Activity.onMenuOpened and Activity.onPanelClosed to determine when the overflow menu or other sub-menus are showing, such as the ShareActionProvider. Here's an example:
/** True if an options menu has been opened, false otherwise */
private boolean mMenuOpened;
#Override
public boolean onMenuOpened(int featureId, Menu menu) {
mMenuOpened = true;
return super.onMenuOpened(featureId, menu);
}
#Override
public void onPanelClosed(int featureId, Menu menu) {
super.onPanelClosed(featureId, menu);
mMenuOpened = false;
}
Alternatively
ActivityChooserView has a way to check ActivityChooserView.isShowingPopup, but you'll have to subclass ShareActionProvider and invoke it via reflection because the ActivityChooserView class is hidden.
Here's an example:
AccessibleShareActionProvider
/**
* A subclass of {#link ShareActionProvider} that uses reflection to invoke
* <p>
* <code>android.widget.ActivityChooserView.isShowingPopup</code>
* <p>
*/
public class AccessibleShareActionProvider extends ShareActionProvider {
/** The action view created for {#link ShareActionProvider} */
private View mActivityChooserView;
/**
* Constructor for <code>AccessibleShareActionProvider</code>
*
* #param context The {#link Context} to use
*/
public AccessibleShareActionProvider(Context context) {
super(context);
}
/**
* {#inheritDoc}
*/
#Override
public View onCreateActionView(MenuItem forItem) {
mActivityChooserView = super.onCreateActionView(forItem);
return mActivityChooserView;
}
/**
* #return True if showing, false if already dismissed
*/
public boolean isShowingPopup() {
try {
final Class<?> acv = Class.forName("android.widget.ActivityChooserView");
final Method isShowingPopup = acv.getMethod("isShowingPopup", new Class[] {});
return (boolean) isShowingPopup.invoke(mActivityChooserView, new Object[] {});
} catch (final Exception ignored) {
// Nothing to do
}
return false;
}
}
Your MenuItem
<item
android:id="#+id/menu_item_share"
android:actionProviderClass="your_path_to.AccessibleShareActionProvider"
android:showAsAction="ifRoom"
android:title="#string/share"/>
In your Activity
private Handler mHandler = new Handler();
private AccessibleShareActionProvider mShareProvider;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
...
final MenuItem item = menu.findItem(R.id.menu_item_share);
mShareProvider = (AccessibleShareActionProvider) item.getActionProvider();
...
return super.onCreateOptionsMenu(menu);
}
private final Runnable mHideActionBar = new Runnable() {
#Override
public void run() {
// If the ShareActionProvider is showing, delay for 4 seconds
if (mShareProvider.isShowingPopup()) {
mHandler.removeCallbacksAndMessages(null);
mHandler.postDelayed(mHideActionBar, 4000);
return;
}
getActionBar().hide();
}
};
i implemented a contextual action mode bar in a nested fragement. This fragment is part of a view pager and the view pager is also a fragment and part of a navigation drawer.
My Problem: I want to close the contextual action mode bar if the fragment is no more focused. So, if I swipe through the view pager the action mode bar should close. But if I use the onPause() method of the nested fragment, the method is not called directly. Often it waits until i swiped two or three times forward... Here are some pictures:
In the second picture you can see that the action mode bar is still there. So my question is:
In which method should I call my actionModeBar.finish() method, to close directly the action mode bar if i leave the fragment?
Maybe the code of the fragment helps you:
public class EditorFragment extends Fragment {
private static final String KEY_POSITION="position";
ListView listView;
private boolean isMultipleList = false;
private ActionMode acMode;
private int counterChecked = 0;
private ActionMode.Callback modeCallBack = new ActionMode.Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu){
return false;
}
public void onDestroyActionMode(ActionMode mode) {
listView.clearChoices();
for (int i = 0; i < listView.getChildCount(); i++)
listView.setItemChecked(i, false);
listView.post(new Runnable() {
#Override
public void run() {
listView.setChoiceMode(ListView.CHOICE_MODE_NONE);
}
});
isMultipleList = false;
counterChecked = 0;
mode = null;
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.setTitle("1 Aufgabe");
mode.getMenuInflater().inflate(R.menu.actionmode, menu);
return true;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.actionmode_delete:
int choiceCount = listView.getCount();
SparseBooleanArray spBoolArray = listView.getCheckedItemPositions();
DBAufgaben db = new DBAufgaben(MainActivity.getMContext());
db.open();
for (int i = 0; i < choiceCount; i++) {
if(spBoolArray.get(i)){
db.deletContact(listView.getItemIdAtPosition(i));
}
}
Cursor cursor = db.getAllRecords();
AdapterEingang adapterE = new AdapterEingang(MainActivity.getMContext(), cursor, 0);
listView.setAdapter(adapterE);
db.close();
mode.finish();
break;
case R.id.actionmode_cancel:
mode.finish();
break;
}
return false;
}
};
//......//
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = null;
int position = getArguments().getInt(KEY_POSITION, -1);
switch(position){
case 0:
rootView = inflater.inflate(R.layout.pager_list, null);
listView = (ListView) rootView.findViewById(R.id.pager_list);
Context context = MainActivity.getMContext();
DBAufgaben db = new DBAufgaben(context);
db.open();
Cursor cursor = db.getAllRecords();
AdapterEingang adapterE = new AdapterEingang(context, cursor, 0);
listView.setAdapter(adapterE);
db.close();
listView.setOnItemLongClickListener(new OnItemLongClickListener(){
#Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view,
int position, long id) {
if(!isMultipleList){
acMode = MainActivity.getInstance().startActionMode(modeCallBack);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
listView.setItemChecked(position, true);
isMultipleList = true;
counterChecked++;
setNewTitle();
} else {
listView.setItemChecked(position, true);
counterChecked++;
setNewTitle();
}
return true;
}
});
listView.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position,
long id) {
Log.d(getTag(), "Datensatz: "+String.valueOf(id));
if(isMultipleList){
if(listView.isItemChecked(position)){
listView.setItemChecked(position, true);
counterChecked++;
setNewTitle();
} else {
listView.setItemChecked(position, false);
counterChecked--;
setNewTitle();
}
}
}
});
break;
default:
rootView = inflater.inflate(R.layout.frag_dummy, null);
TextView txt = (TextView) rootView.findViewById(R.id.dummy_txt);
txt.setText(String.valueOf(position));
break;
}
return(rootView);
}
public void setNewTitle(){
if(counterChecked == 1){
acMode.setTitle(counterChecked+" Aufgabe");
} else {
acMode.setTitle(counterChecked+" Aufgaben");
}
}
#Override
public void onPause(){
super.onPause();
if(isMultipleList){
acMode.finish();
}
}
}
ViewPagers keep multiple pages active at any one time (by default, the page before and page after the currently shown page), hence why onPause() is not called until you swipe two pages away.
Your best bet would be to use a ViewPager.OnPageChangeListener, and show and hide the ActionMode in onPageSelected(..) (i.e. if the page selected isn't the one with the ActionMode, hide the ActionMode). You'll likely have to implement this in the Activity which hosts your ViewPager.
Here's what worked for me --
Hold a static reference to the action mode in MyFragment:
public static ActionMode mActionMode;
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mActionMode = mode;
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
Set ViewPager.OnPageChangeListener in MyViewPagerActivity.
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
....
#Override
public void onPageScrollStateChanged(int state) {
if(MyFragment.mActionMode != null) MyFragment.mActionMode.finish();
}
});
This worked for me:
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
if (!isVisibleToUser && this.listView != null) {
//HACK this is done in order to finish the contextual action bar
int choiceMode = this.listView.getChoiceMode();
this.listView.setChoiceMode(choiceMode);
}
}
I combined code from the OP with the override suggested by user pomber:
I save the ActionMode to a class field when the action mode is created.
I set the field back to null when the action mode is destroyed.
I override setUserVisibleHint in my fragment and call ActionMode#finish() if the fragment isn't visible in the view pager.
I also call ActionMode#finish() in the onPause() method of the fragment to close the fragment if the user navigates elsewhere.
Code:
#Nullable
ActionMode mActionMode = null;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Start out with a progress indicator.
setListShownNoAnimation(false);
setEmptyText(getText(R.string.no_forms_in_progress));
getListView().setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE_MODAL);
getListView().setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
// Here you can do something when items are selected/de-selected,
// such as update the title in the CAB
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context_saved_item, menu);
inflater.inflate(R.menu.context_instance_list, menu);
mActionMode = mode;
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.action_delete:
confirmDelete(getListView().getCheckedItemIds());
return true;
case R.id.action_print:
print(getListView().getCheckedItemIds());
return true;
}
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
});
}
#Override
public void onPause() {
super.onPause();
if (mActionMode != null) {
mActionMode.finish();
}
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (mActionMode != null && !isVisibleToUser) {
mActionMode.finish();
}
}
You can use the onDestroyOptionsMenu() method inside your Fragment:
public void onDestroyOptionsMenu() {
super.onDestroyOptionsMenu();
if (mActionMode != null) {
mActionMode.finish();
mActionMode = null;
}
}
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;
}
I want use a Contextual Action Bar (CAB) in my app but is not compatible with old versions of Android so I'm using this tutorial: http://www.miximum.fr/tutos/849-porting-the-contextual-anction-mode-for-pre-honeycomb-android-apps
My code is:
public class SongsFragment extends SherlockListFragment implements
LoaderManager.LoaderCallbacks<Cursor>, OnLongClickListener{
...
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
activity = this.getActivity();
...
mMode = null;
mListView = getListView();
mListView.setItemsCanFocus(false);
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
mListView.setOnLongClickListener(this);
}
#Override
public boolean onLongClick(View v) {
SparseBooleanArray checked = mListView.getCheckedItemPositions();
boolean hasCheckedElement = false;
for (int i = 0; i < checked.size() && !hasCheckedElement; i++) {
hasCheckedElement = checked.valueAt(i);
}
if (hasCheckedElement) {
if (mMode == null) {
mMode = activity.startActionMode(mActionModeCallback);
}
} else {
if (mMode != null) {
mMode.finish();
}
}
return false;
}
private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Create the menu from the xml file
activity.getSupportMenuInflater().inflate(R.menu.cab_songs, menu);
return true;
}
...
I have errors in:
-"activity.startActionMode(mActionModeCallback);": The method startActionMode(ActionMode.Callback) in the type Activity is not
applicable for the arguments (ActionMode.Callback)
-activity.getSupportMenuInflater().inflate(R.menu.cab_songs, menu);": The method getSupportMenuInflater() is undefined for the
type FragmentActivity
Any idea? is there another solution for CAB using sherlock?
Change your imports for ActionMode and MenuInflater to their ActionBarSherlock equivalents (com.actionbarsherlock.view.ActionMode and com.actionbarsherlock.view.MenuInflater).
I solved using:
getSherlockActivity().startActionMode(mActionModeCallback);
...
mode.getMenuInflater().inflate(R.menu.cab_songs, menu);
Now, I want do an action when the user does a "click" and another action when the user does a "long click". I've "onItemLongClick" and "onListItemClick" but sometimes longClick is not called and when it is called if I release the "onListItemClick" is called. How can I do this actions?