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     public abstract View onCreateActionView();
     84 
     85     /**
     86      * Factory method called by the Android framework to create new action views.
     87      * This method returns a new action view for the given MenuItem.
     88      *
     89      * <p>If your ActionProvider implementation overrides the deprecated no-argument overload
     90      * {@link #onCreateActionView()}, overriding this method for devices running API 16 or later
     91      * is recommended but optional. The default implementation calls {@link #onCreateActionView()}
     92      * for compatibility with applications written for older platform versions.</p>
     93      *
     94      * @param forItem MenuItem to create the action view for
     95      * @return the new action view
     96      */
     97     public View onCreateActionView(MenuItem forItem) {
     98         return onCreateActionView();
     99     }
    100 
    101     /**
    102      * The result of this method determines whether or not {@link #isVisible()} will be used
    103      * by the {@link MenuItem} this ActionProvider is bound to help determine its visibility.
    104      *
    105      * @return true if this ActionProvider overrides the visibility of the MenuItem
    106      *         it is bound to, false otherwise. The default implementation returns false.
    107      * @see #isVisible()
    108      */
    109     public boolean overridesItemVisibility() {
    110         return false;
    111     }
    112 
    113     /**
    114      * If {@link #overridesItemVisibility()} returns true, the return value of this method
    115      * will help determine the visibility of the {@link MenuItem} this ActionProvider is bound to.
    116      *
    117      * <p>If the MenuItem's visibility is explicitly set to false by the application,
    118      * the MenuItem will not be shown, even if this method returns true.</p>
    119      *
    120      * @return true if the MenuItem this ActionProvider is bound to is visible, false if
    121      *         it is invisible. The default implementation returns true.
    122      */
    123     public boolean isVisible() {
    124         return true;
    125     }
    126 
    127     /**
    128      * If this ActionProvider is associated with an item in a menu,
    129      * refresh the visibility of the item based on {@link #overridesItemVisibility()} and
    130      * {@link #isVisible()}. If {@link #overridesItemVisibility()} returns false, this call
    131      * will have no effect.
    132      */
    133     public void refreshVisibility() {
    134         if (mVisibilityListener != null && overridesItemVisibility()) {
    135             mVisibilityListener.onActionProviderVisibilityChanged(isVisible());
    136         }
    137     }
    138 
    139     /**
    140      * Performs an optional default action.
    141      * <p>
    142      * For the case of an action provider placed in a menu item not shown as an action this
    143      * method is invoked if previous callbacks for processing menu selection has handled
    144      * the event.
    145      * </p>
    146      * <p>
    147      * A menu item selection is processed in the following order:
    148      * <ul>
    149      * <li>
    150      * Receiving a call to {@link MenuItem.OnMenuItemClickListener#onMenuItemClick
    151      *  MenuItem.OnMenuItemClickListener.onMenuItemClick}.
    152      * </li>
    153      * <li>
    154      * Receiving a call to {@link android.app.Activity#onOptionsItemSelected(MenuItem)
    155      *  Activity.onOptionsItemSelected(MenuItem)}
    156      * </li>
    157      * <li>
    158      * Receiving a call to {@link android.app.Fragment#onOptionsItemSelected(MenuItem)
    159      *  Fragment.onOptionsItemSelected(MenuItem)}
    160      * </li>
    161      * <li>
    162      * Launching the {@link android.content.Intent} set via
    163      * {@link MenuItem#setIntent(android.content.Intent) MenuItem.setIntent(android.content.Intent)}
    164      * </li>
    165      * <li>
    166      * Invoking this method.
    167      * </li>
    168      * </ul>
    169      * </p>
    170      * <p>
    171      * The default implementation does not perform any action and returns false.
    172      * </p>
    173      */
    174     public boolean onPerformDefaultAction() {
    175         return false;
    176     }
    177 
    178     /**
    179      * Determines if this ActionProvider has a submenu associated with it.
    180      *
    181      * <p>Associated submenus will be shown when an action view is not. This
    182      * provider instance will receive a call to {@link #onPrepareSubMenu(SubMenu)}
    183      * after the call to {@link #onPerformDefaultAction()} and before a submenu is
    184      * displayed to the user.
    185      *
    186      * @return true if the item backed by this provider should have an associated submenu
    187      */
    188     public boolean hasSubMenu() {
    189         return false;
    190     }
    191 
    192     /**
    193      * Called to prepare an associated submenu for the menu item backed by this ActionProvider.
    194      *
    195      * <p>if {@link #hasSubMenu()} returns true, this method will be called when the
    196      * menu item is selected to prepare the submenu for presentation to the user. Apps
    197      * may use this to create or alter submenu content right before display.
    198      *
    199      * @param subMenu Submenu that will be displayed
    200      */
    201     public void onPrepareSubMenu(SubMenu subMenu) {
    202     }
    203 
    204     /**
    205      * Notify the system that the visibility of an action view's sub-UI such as
    206      * an anchored popup has changed. This will affect how other system
    207      * visibility notifications occur.
    208      *
    209      * @hide Pending future API approval
    210      */
    211     public void subUiVisibilityChanged(boolean isVisible) {
    212         if (mSubUiVisibilityListener != null) {
    213             mSubUiVisibilityListener.onSubUiVisibilityChanged(isVisible);
    214         }
    215     }
    216 
    217     /**
    218      * @hide Internal use only
    219      */
    220     public void setSubUiVisibilityListener(SubUiVisibilityListener listener) {
    221         mSubUiVisibilityListener = listener;
    222     }
    223 
    224     /**
    225      * Set a listener to be notified when this ActionProvider's overridden visibility changes.
    226      * This should only be used by MenuItem implementations.
    227      *
    228      * @param listener listener to set
    229      */
    230     public void setVisibilityListener(VisibilityListener listener) {
    231         if (mVisibilityListener != null) {
    232             Log.w(TAG, "setVisibilityListener: Setting a new ActionProvider.VisibilityListener " +
    233                     "when one is already set. Are you reusing this " + getClass().getSimpleName() +
    234                     " instance while it is still in use somewhere else?");
    235         }
    236         mVisibilityListener = listener;
    237     }
    238 
    239     /**
    240      * @hide
    241      */
    242     public void reset() {
    243         mVisibilityListener = null;
    244         mSubUiVisibilityListener = null;
    245     }
    246 
    247     /**
    248      * @hide Internal use only
    249      */
    250     public interface SubUiVisibilityListener {
    251         public void onSubUiVisibilityChanged(boolean isVisible);
    252     }
    253 
    254     /**
    255      * Listens to changes in visibility as reported by {@link ActionProvider#refreshVisibility()}.
    256      *
    257      * @see ActionProvider#overridesItemVisibility()
    258      * @see ActionProvider#isVisible()
    259      */
    260     public interface VisibilityListener {
    261         public void onActionProviderVisibilityChanged(boolean isVisible);
    262     }
    263 }
    264