Home | History | Annotate | Download | only in view
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.view;
     18 
     19 import android.content.Context;
     20 import android.util.Log;
     21 
     22 /**
     23  * An ActionProvider defines rich menu interaction in a single component.
     24  * ActionProvider can generate action views for use in the action bar,
     25  * dynamically populate submenus of a MenuItem, and handle default menu
     26  * item invocations.
     27  *
     28  * <p>An ActionProvider can be optionally specified for a {@link MenuItem} and will be
     29  * responsible for creating the action view that appears in the {@link android.app.ActionBar}
     30  * in place of a simple button in the bar. When the menu item is presented in a way that
     31  * does not allow custom action views, (e.g. in an overflow menu,) the ActionProvider
     32  * can perform a default action.</p>
     33  *
     34  * <p>There are two ways to use an action provider:
     35  * <ul>
     36  * <li>
     37  * Set the action provider on a {@link MenuItem} directly by calling
     38  * {@link MenuItem#setActionProvider(ActionProvider)}.
     39  * </li>
     40  * <li>
     41  * Declare the action provider in an XML menu resource. For example:
     42  * <pre>
     43  * <code>
     44  *   &lt;item android:id="@+id/my_menu_item"
     45  *     android:title="Title"
     46  *     android:icon="@drawable/my_menu_item_icon"
     47  *     android:showAsAction="ifRoom"
     48  *     android:actionProviderClass="foo.bar.SomeActionProvider" /&gt;
     49  * </code>
     50  * </pre>
     51  * </li>
     52  * </ul>
     53  * </p>
     54  *
     55  * @see MenuItem#setActionProvider(ActionProvider)
     56  * @see MenuItem#getActionProvider()
     57  */
     58 public abstract class ActionProvider {
     59     private static final String TAG = "ActionProvider";
     60     private SubUiVisibilityListener mSubUiVisibilityListener;
     61     private VisibilityListener mVisibilityListener;
     62 
     63     /**
     64      * Creates a new instance. ActionProvider classes should always implement a
     65      * constructor that takes a single Context parameter for inflating from menu XML.
     66      *
     67      * @param context Context for accessing resources.
     68      */
     69     public ActionProvider(Context context) {
     70     }
     71 
     72     /**
     73      * Factory method called by the Android framework to create new action views.
     74      *
     75      * <p>This method has been deprecated in favor of {@link #onCreateActionView(MenuItem)}.
     76      * Newer apps that wish to support platform versions prior to API 16 should also
     77      * implement this method to return a valid action view.</p>
     78      *
     79      * @return A new action view.
     80      *
     81      * @deprecated use {@link #onCreateActionView(MenuItem)}
     82      */
     83     @Deprecated
     84     public abstract View onCreateActionView();
     85 
     86     /**
     87      * Factory method called by the Android framework to create new action views.
     88      * This method returns a new action view for the given MenuItem.
     89      *
     90      * <p>If your ActionProvider implementation overrides the deprecated no-argument overload
     91      * {@link #onCreateActionView()}, overriding this method for devices running API 16 or later
     92      * is recommended but optional. The default implementation calls {@link #onCreateActionView()}
     93      * for compatibility with applications written for older platform versions.</p>
     94      *
     95      * @param forItem MenuItem to create the action view for
     96      * @return the new action view
     97      */
     98     public View onCreateActionView(MenuItem forItem) {
     99         return onCreateActionView();
    100     }
    101 
    102     /**
    103      * The result of this method determines whether or not {@link #isVisible()} will be used
    104      * by the {@link MenuItem} this ActionProvider is bound to help determine its visibility.
    105      *
    106      * @return true if this ActionProvider overrides the visibility of the MenuItem
    107      *         it is bound to, false otherwise. The default implementation returns false.
    108      * @see #isVisible()
    109      */
    110     public boolean overridesItemVisibility() {
    111         return false;
    112     }
    113 
    114     /**
    115      * If {@link #overridesItemVisibility()} returns true, the return value of this method
    116      * will help determine the visibility of the {@link MenuItem} this ActionProvider is bound to.
    117      *
    118      * <p>If the MenuItem's visibility is explicitly set to false by the application,
    119      * the MenuItem will not be shown, even if this method returns true.</p>
    120      *
    121      * @return true if the MenuItem this ActionProvider is bound to is visible, false if
    122      *         it is invisible. The default implementation returns true.
    123      */
    124     public boolean isVisible() {
    125         return true;
    126     }
    127 
    128     /**
    129      * If this ActionProvider is associated with an item in a menu,
    130      * refresh the visibility of the item based on {@link #overridesItemVisibility()} and
    131      * {@link #isVisible()}. If {@link #overridesItemVisibility()} returns false, this call
    132      * will have no effect.
    133      */
    134     public void refreshVisibility() {
    135         if (mVisibilityListener != null && overridesItemVisibility()) {
    136             mVisibilityListener.onActionProviderVisibilityChanged(isVisible());
    137         }
    138     }
    139 
    140     /**
    141      * Performs an optional default action.
    142      * <p>
    143      * For the case of an action provider placed in a menu item not shown as an action this
    144      * method is invoked if previous callbacks for processing menu selection has handled
    145      * the event.
    146      * </p>
    147      * <p>
    148      * A menu item selection is processed in the following order:
    149      * <ul>
    150      * <li>
    151      * Receiving a call to {@link MenuItem.OnMenuItemClickListener#onMenuItemClick
    152      *  MenuItem.OnMenuItemClickListener.onMenuItemClick}.
    153      * </li>
    154      * <li>
    155      * Receiving a call to {@link android.app.Activity#onOptionsItemSelected(MenuItem)
    156      *  Activity.onOptionsItemSelected(MenuItem)}
    157      * </li>
    158      * <li>
    159      * Receiving a call to {@link android.app.Fragment#onOptionsItemSelected(MenuItem)
    160      *  Fragment.onOptionsItemSelected(MenuItem)}
    161      * </li>
    162      * <li>
    163      * Launching the {@link android.content.Intent} set via
    164      * {@link MenuItem#setIntent(android.content.Intent) MenuItem.setIntent(android.content.Intent)}
    165      * </li>
    166      * <li>
    167      * Invoking this method.
    168      * </li>
    169      * </ul>
    170      * </p>
    171      * <p>
    172      * The default implementation does not perform any action and returns false.
    173      * </p>
    174      */
    175     public boolean onPerformDefaultAction() {
    176         return false;
    177     }
    178 
    179     /**
    180      * Determines if this ActionProvider has a submenu associated with it.
    181      *
    182      * <p>Associated submenus will be shown when an action view is not. This
    183      * provider instance will receive a call to {@link #onPrepareSubMenu(SubMenu)}
    184      * after the call to {@link #onPerformDefaultAction()} and before a submenu is
    185      * displayed to the user.
    186      *
    187      * @return true if the item backed by this provider should have an associated submenu
    188      */
    189     public boolean hasSubMenu() {
    190         return false;
    191     }
    192 
    193     /**
    194      * Called to prepare an associated submenu for the menu item backed by this ActionProvider.
    195      *
    196      * <p>if {@link #hasSubMenu()} returns true, this method will be called when the
    197      * menu item is selected to prepare the submenu for presentation to the user. Apps
    198      * may use this to create or alter submenu content right before display.
    199      *
    200      * @param subMenu Submenu that will be displayed
    201      */
    202     public void onPrepareSubMenu(SubMenu subMenu) {
    203     }
    204 
    205     /**
    206      * Notify the system that the visibility of an action view's sub-UI such as
    207      * an anchored popup has changed. This will affect how other system
    208      * visibility notifications occur.
    209      *
    210      * @hide Pending future API approval
    211      */
    212     public void subUiVisibilityChanged(boolean isVisible) {
    213         if (mSubUiVisibilityListener != null) {
    214             mSubUiVisibilityListener.onSubUiVisibilityChanged(isVisible);
    215         }
    216     }
    217 
    218     /**
    219      * @hide Internal use only
    220      */
    221     public void setSubUiVisibilityListener(SubUiVisibilityListener listener) {
    222         mSubUiVisibilityListener = listener;
    223     }
    224 
    225     /**
    226      * Set a listener to be notified when this ActionProvider's overridden visibility changes.
    227      * This should only be used by MenuItem implementations.
    228      *
    229      * @param listener listener to set
    230      */
    231     public void setVisibilityListener(VisibilityListener listener) {
    232         if (mVisibilityListener != null) {
    233             Log.w(TAG, "setVisibilityListener: Setting a new ActionProvider.VisibilityListener " +
    234                     "when one is already set. Are you reusing this " + getClass().getSimpleName() +
    235                     " instance while it is still in use somewhere else?");
    236         }
    237         mVisibilityListener = listener;
    238     }
    239 
    240     /**
    241      * @hide
    242      */
    243     public void reset() {
    244         mVisibilityListener = null;
    245         mSubUiVisibilityListener = null;
    246     }
    247 
    248     /**
    249      * @hide Internal use only
    250      */
    251     public interface SubUiVisibilityListener {
    252         public void onSubUiVisibilityChanged(boolean isVisible);
    253     }
    254 
    255     /**
    256      * Listens to changes in visibility as reported by {@link ActionProvider#refreshVisibility()}.
    257      *
    258      * @see ActionProvider#overridesItemVisibility()
    259      * @see ActionProvider#isVisible()
    260      */
    261     public interface VisibilityListener {
    262         public void onActionProviderVisibilityChanged(boolean isVisible);
    263     }
    264 }
    265