FileDocCategorySizeDatePackage
ActivityChooserView.javaAPI DocAndroid 5.1 API31173Thu Mar 12 22:22:56 GMT 2015android.support.v7.internal.widget

ActivityChooserView

public class ActivityChooserView extends android.view.ViewGroup implements ActivityChooserModel.ActivityChooserModelClient
This class is a view for choosing an activity for handling a given {@link Intent}.

The view is composed of two adjacent buttons:

  • The left button is an immediate action and allows one click activity choosing. Tapping this button immediately executes the intent without requiring any further user input. Long press on this button shows a popup for changing the default activity.
  • The right button is an overflow action and provides an optimized menu of additional activities. Tapping this button shows a popup anchored to this view, listing the most frequently used activities. This list is initially limited to a small number of items in frequency used order. The last item, "Show all..." serves as an affordance to display all available activities.

hide

Fields Summary
private static final String
LOG_TAG
private final ActivityChooserViewAdapter
mAdapter
An adapter for displaying the activities in an {@link android.widget.AdapterView}.
private final Callbacks
mCallbacks
Implementation of various interfaces to avoid publishing them in the APIs.
private final android.support.v7.widget.LinearLayoutCompat
mActivityChooserContent
The content of this view.
private final android.graphics.drawable.Drawable
mActivityChooserContentBackground
Stores the background drawable to allow hiding and latter showing.
private final android.widget.FrameLayout
mExpandActivityOverflowButton
The expand activities action button;
private final android.widget.ImageView
mExpandActivityOverflowButtonImage
The image for the expand activities action button;
private final android.widget.FrameLayout
mDefaultActivityButton
The default activities action button;
private final android.widget.ImageView
mDefaultActivityButtonImage
The image for the default activities action button;
private final int
mListPopupMaxWidth
The maximal width of the list popup.
android.support.v4.view.ActionProvider
mProvider
The ActionProvider hosting this view, if applicable.
private final android.database.DataSetObserver
mModelDataSetOberver
Observer for the model data.
private final android.view.ViewTreeObserver.OnGlobalLayoutListener
mOnGlobalLayoutListener
private android.support.v7.widget.ListPopupWindow
mListPopupWindow
Popup window for showing the activity overflow list.
private PopupWindow.OnDismissListener
mOnDismissListener
Listener for the dismissal of the popup/alert.
private boolean
mIsSelectingDefaultActivity
Flag whether a default activity currently being selected.
private int
mInitialActivityCount
The count of activities in the popup.
private boolean
mIsAttachedToWindow
Flag whether this view is attached to a window.
private int
mDefaultActionButtonContentDescription
String resource for formatting content description of the default target.
Constructors Summary
public ActivityChooserView(android.content.Context context)
Create a new instance.

param
context The application environment.


                  
       
        this(context, null);
    
public ActivityChooserView(android.content.Context context, android.util.AttributeSet attrs)
Create a new instance.

param
context The application environment.
param
attrs A collection of attributes.

        this(context, attrs, 0);
    
public ActivityChooserView(android.content.Context context, android.util.AttributeSet attrs, int defStyle)
Create a new instance.

param
context The application environment.
param
attrs A collection of attributes.
param
defStyle The default style to apply to this view.

        super(context, attrs, defStyle);

        TypedArray attributesArray = context.obtainStyledAttributes(attrs,
                R.styleable.ActivityChooserView, defStyle, 0);

        mInitialActivityCount = attributesArray.getInt(
                R.styleable.ActivityChooserView_initialActivityCount,
                ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT);

        Drawable expandActivityOverflowButtonDrawable = attributesArray.getDrawable(
                R.styleable.ActivityChooserView_expandActivityOverflowButtonDrawable);

        attributesArray.recycle();

        LayoutInflater inflater = LayoutInflater.from(getContext());
        inflater.inflate(R.layout.abc_activity_chooser_view, this, true);

        mCallbacks = new Callbacks();

        mActivityChooserContent = (LinearLayoutCompat) findViewById(R.id.activity_chooser_view_content);
        mActivityChooserContentBackground = mActivityChooserContent.getBackground();

        mDefaultActivityButton = (FrameLayout) findViewById(R.id.default_activity_button);
        mDefaultActivityButton.setOnClickListener(mCallbacks);
        mDefaultActivityButton.setOnLongClickListener(mCallbacks);
        mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.image);

        final FrameLayout expandButton = (FrameLayout) findViewById(R.id.expand_activities_button);
        expandButton.setOnClickListener(mCallbacks);
        expandButton.setOnTouchListener(new ListPopupWindow.ForwardingListener(expandButton) {
            @Override
            public ListPopupWindow getPopup() {
                return getListPopupWindow();
            }

            @Override
            protected boolean onForwardingStarted() {
                showPopup();
                return true;
            }

            @Override
            protected boolean onForwardingStopped() {
                dismissPopup();
                return true;
            }
        });
        mExpandActivityOverflowButton = expandButton;
        mExpandActivityOverflowButtonImage =
            (ImageView) expandButton.findViewById(R.id.image);
        mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable);

        mAdapter = new ActivityChooserViewAdapter();
        mAdapter.registerDataSetObserver(new DataSetObserver() {
            @Override
            public void onChanged() {
                super.onChanged();
                updateAppearance();
            }
        });

        Resources resources = context.getResources();
        mListPopupMaxWidth = Math.max(resources.getDisplayMetrics().widthPixels / 2,
                resources.getDimensionPixelSize(R.dimen.abc_config_prefDialogWidth));
    
Methods Summary
public booleandismissPopup()
Dismisses the popup window with activities.

return
True if dismissed, false if already dismissed.

        if (isShowingPopup()) {
            getListPopupWindow().dismiss();
            ViewTreeObserver viewTreeObserver = getViewTreeObserver();
            if (viewTreeObserver.isAlive()) {
                viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
            }
        }
        return true;
    
public ActivityChooserModelgetDataModel()

        return mAdapter.getDataModel();
    
private android.support.v7.widget.ListPopupWindowgetListPopupWindow()
Gets the list popup window which is lazily initialized.

return
The popup.

        if (mListPopupWindow == null) {
            mListPopupWindow = new ListPopupWindow(getContext());
            mListPopupWindow.setAdapter(mAdapter);
            mListPopupWindow.setAnchorView(ActivityChooserView.this);
            mListPopupWindow.setModal(true);
            mListPopupWindow.setOnItemClickListener(mCallbacks);
            mListPopupWindow.setOnDismissListener(mCallbacks);
        }
        return mListPopupWindow;
    
public booleanisShowingPopup()
Gets whether the popup window with activities is shown.

return
True if the popup is shown.

        return getListPopupWindow().isShowing();
    
protected voidonAttachedToWindow()

        super.onAttachedToWindow();
        ActivityChooserModel dataModel = mAdapter.getDataModel();
        if (dataModel != null) {
            dataModel.registerObserver(mModelDataSetOberver);
        }
        mIsAttachedToWindow = true;
    
protected voidonDetachedFromWindow()

        super.onDetachedFromWindow();
        ActivityChooserModel dataModel = mAdapter.getDataModel();
        if (dataModel != null) {
            dataModel.unregisterObserver(mModelDataSetOberver);
        }
        ViewTreeObserver viewTreeObserver = getViewTreeObserver();
        if (viewTreeObserver.isAlive()) {
            viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
        }
        if (isShowingPopup()) {
            dismissPopup();
        }
        mIsAttachedToWindow = false;
    
protected voidonLayout(boolean changed, int left, int top, int right, int bottom)

        mActivityChooserContent.layout(0, 0, right - left, bottom - top);
        if (!isShowingPopup()) {
            dismissPopup();
        }
    
protected voidonMeasure(int widthMeasureSpec, int heightMeasureSpec)

        View child = mActivityChooserContent;
        // If the default action is not visible we want to be as tall as the
        // ActionBar so if this widget is used in the latter it will look as
        // a normal action button.
        if (mDefaultActivityButton.getVisibility() != VISIBLE) {
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
                    MeasureSpec.EXACTLY);
        }
        measureChild(child, widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(child.getMeasuredWidth(), child.getMeasuredHeight());
    
public voidsetActivityChooserModel(ActivityChooserModel dataModel)
{@inheritDoc}

        mAdapter.setDataModel(dataModel);
        if (isShowingPopup()) {
            dismissPopup();
            showPopup();
        }
    
public voidsetDefaultActionButtonContentDescription(int resourceId)
Sets a content description of the default action button. This resource should be a string taking one formatting argument and will be used for formatting the content description of the button dynamically as the default target changes. For example, a resource pointing to the string "share with %1$s" will result in a content description "share with Bluetooth" for the Bluetooth activity.

param
resourceId The resource id.

        mDefaultActionButtonContentDescription = resourceId;
    
public voidsetExpandActivityOverflowButtonContentDescription(int resourceId)
Sets the content description for the button that expands the activity overflow list. description as a clue about the action performed by the button. For example, if a share activity is to be chosen the content description should be something like "Share with".

param
resourceId The content description resource id.

        CharSequence contentDescription = getContext().getString(resourceId);
        mExpandActivityOverflowButtonImage.setContentDescription(contentDescription);
    
public voidsetExpandActivityOverflowButtonDrawable(android.graphics.drawable.Drawable drawable)
Sets the background for the button that expands the activity overflow list. Note: Clients would like to set this drawable as a clue about the action the chosen activity will perform. For example, if a share activity is to be chosen the drawable should give a clue that sharing is to be performed.

param
drawable The drawable.

        mExpandActivityOverflowButtonImage.setImageDrawable(drawable);
    
public voidsetInitialActivityCount(int itemCount)
Sets the initial count of items shown in the activities popup i.e. the items before the popup is expanded. This is an upper bound since it is not guaranteed that such number of intent handlers exist.

param
itemCount The initial popup item count.

        mInitialActivityCount = itemCount;
    
public voidsetOnDismissListener(PopupWindow.OnDismissListener listener)
Sets a listener to receive a callback when the popup is dismissed.

param
listener The listener to be notified.

        mOnDismissListener = listener;
    
public voidsetProvider(android.support.v4.view.ActionProvider provider)
Set the provider hosting this view, if applicable.

hide
Internal use only

        mProvider = provider;
    
public booleanshowPopup()
Shows the popup window with activities.

return
True if the popup was shown, false if already showing.

        if (isShowingPopup() || !mIsAttachedToWindow) {
            return false;
        }
        mIsSelectingDefaultActivity = false;
        showPopupUnchecked(mInitialActivityCount);
        return true;
    
private voidshowPopupUnchecked(int maxActivityCount)
Shows the popup no matter if it was already showing.

param
maxActivityCount The max number of activities to display.

        if (mAdapter.getDataModel() == null) {
            throw new IllegalStateException("No data model. Did you call #setDataModel?");
        }

        getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);

        final boolean defaultActivityButtonShown =
                mDefaultActivityButton.getVisibility() == VISIBLE;

        final int activityCount = mAdapter.getActivityCount();
        final int maxActivityCountOffset = defaultActivityButtonShown ? 1 : 0;
        if (maxActivityCount != ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED
                && activityCount > maxActivityCount + maxActivityCountOffset) {
            mAdapter.setShowFooterView(true);
            mAdapter.setMaxActivityCount(maxActivityCount - 1);
        } else {
            mAdapter.setShowFooterView(false);
            mAdapter.setMaxActivityCount(maxActivityCount);
        }

        ListPopupWindow popupWindow = getListPopupWindow();
        if (!popupWindow.isShowing()) {
            if (mIsSelectingDefaultActivity || !defaultActivityButtonShown) {
                mAdapter.setShowDefaultActivity(true, defaultActivityButtonShown);
            } else {
                mAdapter.setShowDefaultActivity(false, false);
            }
            final int contentWidth = Math.min(mAdapter.measureContentWidth(), mListPopupMaxWidth);
            popupWindow.setContentWidth(contentWidth);
            popupWindow.show();
            if (mProvider != null) {
                mProvider.subUiVisibilityChanged(true);
            }
            popupWindow.getListView().setContentDescription(getContext().getString(
                    R.string.abc_activitychooserview_choose_application));
        }
    
private voidupdateAppearance()
Updates the buttons state.

        // Expand overflow button.
        if (mAdapter.getCount() > 0) {
            mExpandActivityOverflowButton.setEnabled(true);
        } else {
            mExpandActivityOverflowButton.setEnabled(false);
        }
        // Default activity button.
        final int activityCount = mAdapter.getActivityCount();
        final int historySize = mAdapter.getHistorySize();
        if (activityCount==1 || activityCount > 1 && historySize > 0) {
            mDefaultActivityButton.setVisibility(VISIBLE);
            ResolveInfo activity = mAdapter.getDefaultActivity();
            PackageManager packageManager = getContext().getPackageManager();
            mDefaultActivityButtonImage.setImageDrawable(activity.loadIcon(packageManager));
            if (mDefaultActionButtonContentDescription != 0) {
                CharSequence label = activity.loadLabel(packageManager);
                String contentDescription = getContext().getString(
                        mDefaultActionButtonContentDescription, label);
                mDefaultActivityButton.setContentDescription(contentDescription);
            }
        } else {
            mDefaultActivityButton.setVisibility(View.GONE);
        }
        // Activity chooser content.
        if (mDefaultActivityButton.getVisibility() == VISIBLE) {
            mActivityChooserContent.setBackgroundDrawable(mActivityChooserContentBackground);
        } else {
            mActivityChooserContent.setBackgroundDrawable(null);
        }