Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 51ac0e94 authored by Svetoslav Ganov's avatar Svetoslav Ganov
Browse files

Adding a ShareView and ActionProvider for menus.

1. Adding a widget for sharing contenet with other applications.
   The widget orders the share targets based on previous shares.
   It displays the share target list as either a popup anchored to
   itslef or as a dialog.

2. Added a ShareDataModel that will back widgets or other classes
   that are interested in share targets for a given intent ordered
   according to share history. This class is backing the ShareView

3. Added ActionProvider mechanism for the MenuItems. The action
   provider of a menu creates the action view as well as performs
   a default action if the menu item is on the overflow menu and
   is triggered but none of the menu callback has handled that.

bug:4590827

Change-Id: Iaa4add2df2538b8c6c7edbeaf2880486d4fd75c5
parent b4c5fbff
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -208,6 +208,7 @@ package android {
    field public static final int actionModePasteDrawable = 16843539; // 0x1010313
    field public static final int actionModeSelectAllDrawable = 16843648; // 0x1010380
    field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
    field public static final int actionProviderClass = 16843678; // 0x101039e
    field public static final int actionViewClass = 16843516; // 0x10102fc
    field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
    field public static final int activityCloseEnterAnimation = 16842938; // 0x10100ba
@@ -20568,6 +20569,12 @@ package android.view {
    method public abstract boolean onPrepareActionMode(android.view.ActionMode, android.view.Menu);
  }
  public abstract class ActionProvider {
    ctor public ActionProvider(android.content.Context);
    method public abstract android.view.View onCreateActionView();
    method public void onPerformDefaultAction(android.view.View);
  }
  public abstract interface ContextMenu implements android.view.Menu {
    method public abstract void clearHeader();
    method public abstract android.view.ContextMenu setHeaderIcon(int);
@@ -21236,6 +21243,7 @@ package android.view {
  public abstract interface MenuItem {
    method public abstract boolean collapseActionView();
    method public abstract boolean expandActionView();
    method public abstract android.view.ActionProvider getActionProvider();
    method public abstract android.view.View getActionView();
    method public abstract char getAlphabeticShortcut();
    method public abstract int getGroupId();
@@ -21254,6 +21262,7 @@ package android.view {
    method public abstract boolean isChecked();
    method public abstract boolean isEnabled();
    method public abstract boolean isVisible();
    method public abstract android.view.MenuItem setActionProvider(android.view.ActionProvider);
    method public abstract android.view.MenuItem setActionView(android.view.View);
    method public abstract android.view.MenuItem setActionView(int);
    method public abstract android.view.MenuItem setAlphabeticShortcut(char);
@@ -25739,6 +25748,14 @@ package android.widget {
    method public abstract void onStopTrackingTouch(android.widget.SeekBar);
  }
  public class ShareActionProvider extends android.view.ActionProvider {
    ctor public ShareActionProvider(android.content.Context);
    method public android.view.View onCreateActionView();
    method public void setShareHistoryFileName(java.lang.String);
    method public void setShareIntent(android.view.View, android.content.Intent);
    field public static final java.lang.String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";
  }
  public class SimpleAdapter extends android.widget.BaseAdapter implements android.widget.Filterable {
    ctor public SimpleAdapter(android.content.Context, java.util.List<? extends java.util.Map<java.lang.String, ?>>, int, java.lang.String[], int[]);
    method public int getCount();
+114 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.view;

import android.content.Context;

/**
 * This class is a mediator for accomplishing a given task, for example sharing a file.
 * It is responsible for creating a view that performs an action that accomplishes the task.
 * This class also implements other functions such a performing a default action.
 * <p>
 * An ActionProvider can be optionally specified for a {@link MenuItem} and in such a
 * case it will be responsible for creating the action view that appears in the
 * {@link android.app.ActionBar} as a substitute for the menu item when the item is
 * displayed as an action item. Also the provider is responsible for performing a
 * default action if a menu item placed on the overflow menu of the ActionBar is
 * selected and none of the menu item callbacks has handled the selection.
 * </p>
 * <p>
 * There are two ways for using an action provider for creating and handling of action views:
 * <ul>
 * <li>
 * Setting the action provider on a {@link MenuItem} directly by calling
 * {@link MenuItem#setActionProvider(ActionProvider)}.
 * </li>
 * <li>
 * Declaring the action provider in the menu XML resource. For example:
 * <pre>
 * <code>
 *   &lt;item android:id="@+id/my_menu_item"
 *     android:title="Title"
 *     android:icon="@drawable/my_menu_item_icon"
 *     android:showAsAction="ifRoom"
 *     android:actionProviderClass="foo.bar.SomeActionProvider" /&gt;
 * </code>
 * </pre>
 * </li>
 * </ul>
 * </p>
 *
 * @see MenuItem#setActionProvider(ActionProvider)
 * @see MenuItem#getActionProvider()
 */
public abstract class ActionProvider {

    /**
     * Creates a new instance.
     *
     * @param context Context for accessing resources.
     */
    public ActionProvider(Context context) {
    }

    /**
     * Factory method for creating new action views.
     *
     * @return A new action view.
     */
    public abstract View onCreateActionView();

    /**
     * Performs an optional default action.
     * <p>
     * For the case of an action provider placed in a menu item not shown as an action this
     * method is invoked if none of the callbacks for processing menu selection has handled
     * the event.
     * </p>
     * <p>
     * A menu item selection is processed in the following order:
     * <ul>
     * <li>
     * Receiving a call to {@link MenuItem.OnMenuItemClickListener#onMenuItemClick
     *  MenuItem.OnMenuItemClickListener.onMenuItemClick}.
     * </li>
     * <li>
     * Receiving a call to {@link android.app.Activity#onOptionsItemSelected(MenuItem)
     *  Activity.onOptionsItemSelected(MenuItem)}
     * </li>
     * <li>
     * Receiving a call to {@link android.app.Fragment#onOptionsItemSelected(MenuItem)
     *  Fragment.onOptionsItemSelected(MenuItem)}
     * </li>
     * <li>
     * Launching the {@link android.content.Intent} set via
     * {@link MenuItem#setIntent(android.content.Intent) MenuItem.setIntent(android.content.Intent)}
     * </li>
     * <li>
     * Invoking this method.
     * </li>
     * </ul>
     * </p>
     * <p>
     * The default implementation does not perform any action.
     * </p>
     *
     * @param actionView A view created by {@link #onCreateActionView()}.
     */
    public void onPerformDefaultAction(View actionView) {
    }
}
+58 −18
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;

import java.io.IOException;
@@ -42,6 +43,8 @@ import java.lang.reflect.Method;
 * <em>something</em> file.)
 */
public class MenuInflater {
    private static final String LOG_TAG = "MenuInflater";

    /** Menu tag name in XML. */
    private static final String XML_MENU = "menu";
    
@@ -55,6 +58,12 @@ public class MenuInflater {
    
    private static final Class<?>[] ACTION_VIEW_CONSTRUCTOR_SIGNATURE = new Class[] {Context.class};

    private static final Class<?>[] ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE = ACTION_VIEW_CONSTRUCTOR_SIGNATURE;

    private final Object[] mActionViewConstructorArguments;

    private final Object[] mActionProviderConstructorArguments;

    private Context mContext;

    /**
@@ -64,6 +73,8 @@ public class MenuInflater {
     */
    public MenuInflater(Context context) {
        mContext = context;
        mActionViewConstructorArguments = new Object[] {context};
        mActionProviderConstructorArguments = mActionViewConstructorArguments;
    }

    /**
@@ -172,14 +183,14 @@ public class MenuInflater {
    
    private static class InflatedOnMenuItemClickListener
            implements MenuItem.OnMenuItemClickListener {
        private static final Class[] PARAM_TYPES = new Class[] { MenuItem.class };
        private static final Class<?>[] PARAM_TYPES = new Class[] { MenuItem.class };
        
        private Context mContext;
        private Method mMethod;
        
        public InflatedOnMenuItemClickListener(Context context, String methodName) {
            mContext = context;
            Class c = context.getClass();
            Class<?> c = context.getClass();
            try {
                mMethod = c.getMethod(methodName, PARAM_TYPES);
            } catch (Exception e) {
@@ -255,6 +266,7 @@ public class MenuInflater {

        private int itemActionViewLayout;
        private String itemActionViewClassName;
        private String itemActionProviderClassName;

        private String itemListenerMethodName;
        
@@ -333,6 +345,7 @@ public class MenuInflater {
            itemListenerMethodName = a.getString(com.android.internal.R.styleable.MenuItem_onClick);
            itemActionViewLayout = a.getResourceId(com.android.internal.R.styleable.MenuItem_actionLayout, 0);
            itemActionViewClassName = a.getString(com.android.internal.R.styleable.MenuItem_actionViewClass);
            itemActionProviderClassName = a.getString(com.android.internal.R.styleable.MenuItem_actionProviderClass);

            a.recycle();

@@ -377,17 +390,32 @@ public class MenuInflater {
                }
            }

            boolean actionViewSpecified = false;
            if (itemActionViewClassName != null) {
                try {
                    final Class<?> clazz = Class.forName(itemActionViewClassName, true,
                            mContext.getClassLoader());
                    Constructor<?> c = clazz.getConstructor(ACTION_VIEW_CONSTRUCTOR_SIGNATURE);
                    item.setActionView((View) c.newInstance(mContext));
                } catch (Exception e) {
                    throw new InflateException(e);
                View actionView = (View) newInstance(itemActionViewClassName,
                        ACTION_VIEW_CONSTRUCTOR_SIGNATURE, mActionViewConstructorArguments);
                item.setActionView(actionView);
                actionViewSpecified = true;
            }
            } else if (itemActionViewLayout > 0) {
            if (itemActionViewLayout > 0) {
                if (!actionViewSpecified) {
                    item.setActionView(itemActionViewLayout);
                    actionViewSpecified = true;
                } else {
                    Log.w(LOG_TAG, "Ignoring attribute 'itemActionViewLayout'."
                            + " Action view already specified.");
                }
            }
            if (itemActionProviderClassName != null) {
                if (!actionViewSpecified) {
                    ActionProvider actionProvider = newInstance(itemActionProviderClassName,
                            ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE,
                            mActionProviderConstructorArguments);
                    item.setActionProvider(actionProvider);
                } else {
                    Log.w(LOG_TAG, "Ignoring attribute 'itemActionProviderClass'."
                            + " Action view already specified.");
                }
            }
        }

@@ -406,6 +434,18 @@ public class MenuInflater {
        public boolean hasAddedItem() {
            return itemAdded;
        }
    }

        @SuppressWarnings("unchecked")
        private <T> T newInstance(String className, Class<?>[] constructorSignature,
                Object[] arguments) {
            try {
                Class<?> clazz = mContext.getClassLoader().loadClass(className);
                Constructor<?> constructor = clazz.getConstructor(constructorSignature);
                return (T) constructor.newInstance(arguments);
            } catch (Exception e) {
                Log.w(LOG_TAG, "Cannot instantiate class: " + className, e);
            }
            return null;
        }
    }
}
+34 −1
Original line number Diff line number Diff line
@@ -88,7 +88,6 @@ public interface MenuItem {
     * @see MenuItem#expandActionView()
     * @see MenuItem#collapseActionView()
     * @see MenuItem#setShowAsActionFlags(int)
     * @see MenuItem#
     */
    public interface OnActionExpandListener {
        /**
@@ -480,6 +479,10 @@ public interface MenuItem {
     * Set an action view for this menu item. An action view will be displayed in place
     * of an automatically generated menu item element in the UI when this item is shown
     * as an action within a parent.
     * <p>
     *   <strong>Note:</strong> Setting an action view overrides the action provider
     *           set via {@link #setActionProvider(ActionProvider)}.
     * </p>
     *
     * @param view View to use for presenting this item to the user.
     * @return This Item so additional setters can be called.
@@ -492,6 +495,10 @@ public interface MenuItem {
     * Set an action view for this menu item. An action view will be displayed in place
     * of an automatically generated menu item element in the UI when this item is shown
     * as an action within a parent.
     * <p>
     *   <strong>Note:</strong> Setting an action view overrides the action provider
     *           set via {@link #setActionProvider(ActionProvider)}.
     * </p>
     *
     * @param resId Layout resource to use for presenting this item to the user.
     * @return This Item so additional setters can be called.
@@ -510,6 +517,32 @@ public interface MenuItem {
     */
    public View getActionView();

    /**
     * Sets the {@link ActionProvider} responsible for creating an action view if
     * the item is placed on the action bar. The provider also provides a default
     * action invoked if the item is placed in the overflow menu.
     * <p>
     *   <strong>Note:</strong> Setting an action provider overrides the action view
     *           set via {@link #setActionView(int)} or {@link #setActionView(View)}.
     * </p>
     *
     * @param actionProvider The action provider.
     * @return This Item so additional setters can be called.
     *
     * @see ActionProvider
     */
    public MenuItem setActionProvider(ActionProvider actionProvider);

    /**
     * Gets the {@link ActionProvider}.
     *
     * @return The action provider.
     *
     * @see ActionProvider
     * @see #setActionProvider(ActionProvider)
     */
    public ActionProvider getActionProvider();

    /**
     * Expand the action view associated with this menu item.
     * The menu item must have an action view set, as well as
+1115 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading