Search code examples
androidandroid-actionbarshareactionprovider

Auto-hideable ActionBar and ShareActionProvider


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?


Solution

  • 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();
        }
    
    };