2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com
.actionbarsherlock
.widget
;
19 import android
.os
.Build
;
20 import com
.actionbarsherlock
.R
;
21 import com
.actionbarsherlock
.internal
.widget
.IcsLinearLayout
;
22 import com
.actionbarsherlock
.internal
.widget
.IcsListPopupWindow
;
23 import com
.actionbarsherlock
.view
.ActionProvider
;
24 import com
.actionbarsherlock
.widget
.ActivityChooserModel
.ActivityChooserModelClient
;
25 import android
.content
.Context
;
26 import android
.content
.Intent
;
27 import android
.content
.pm
.PackageManager
;
28 import android
.content
.pm
.ResolveInfo
;
29 import android
.content
.res
.Resources
;
30 import android
.content
.res
.TypedArray
;
31 import android
.database
.DataSetObserver
;
32 import android
.graphics
.drawable
.Drawable
;
33 import android
.util
.AttributeSet
;
34 import android
.view
.LayoutInflater
;
35 import android
.view
.View
;
36 import android
.view
.ViewGroup
;
37 import android
.view
.ViewTreeObserver
;
38 import android
.view
.ViewTreeObserver
.OnGlobalLayoutListener
;
39 import android
.widget
.AdapterView
;
40 import android
.widget
.BaseAdapter
;
41 import android
.widget
.FrameLayout
;
42 import android
.widget
.ImageView
;
43 import android
.widget
.PopupWindow
;
44 import android
.widget
.TextView
;
47 * This class is a view for choosing an activity for handling a given {@link Intent}.
49 * The view is composed of two adjacent buttons:
52 * The left button is an immediate action and allows one click activity choosing.
53 * Tapping this button immediately executes the intent without requiring any further
54 * user input. Long press on this button shows a popup for changing the default
58 * The right button is an overflow action and provides an optimized menu
59 * of additional activities. Tapping this button shows a popup anchored to this
60 * view, listing the most frequently used activities. This list is initially
61 * limited to a small number of items in frequency used order. The last item,
62 * "Show all..." serves as an affordance to display all available activities.
69 class ActivityChooserView
extends ViewGroup
implements ActivityChooserModelClient
{
72 * An adapter for displaying the activities in an {@link AdapterView}.
74 private final ActivityChooserViewAdapter mAdapter
;
77 * Implementation of various interfaces to avoid publishing them in the APIs.
79 private final Callbacks mCallbacks
;
82 * The content of this view.
84 private final IcsLinearLayout mActivityChooserContent
;
87 * Stores the background drawable to allow hiding and latter showing.
89 private final Drawable mActivityChooserContentBackground
;
92 * The expand activities action button;
94 private final FrameLayout mExpandActivityOverflowButton
;
97 * The image for the expand activities action button;
99 private final ImageView mExpandActivityOverflowButtonImage
;
102 * The default activities action button;
104 private final FrameLayout mDefaultActivityButton
;
107 * The image for the default activities action button;
109 private final ImageView mDefaultActivityButtonImage
;
112 * The maximal width of the list popup.
114 private final int mListPopupMaxWidth
;
117 * The ActionProvider hosting this view, if applicable.
119 ActionProvider mProvider
;
122 * Observer for the model data.
124 private final DataSetObserver mModelDataSetOberver
= new DataSetObserver() {
127 public void onChanged() {
129 mAdapter
.notifyDataSetChanged();
132 public void onInvalidated() {
133 super.onInvalidated();
134 mAdapter
.notifyDataSetInvalidated();
138 private final OnGlobalLayoutListener mOnGlobalLayoutListener
= new OnGlobalLayoutListener() {
140 public void onGlobalLayout() {
141 if (isShowingPopup()) {
143 getListPopupWindow().dismiss();
145 getListPopupWindow().show();
146 if (mProvider
!= null
) {
147 mProvider
.subUiVisibilityChanged(true
);
155 * Popup window for showing the activity overflow list.
157 private IcsListPopupWindow mListPopupWindow
;
160 * Listener for the dismissal of the popup/alert.
162 private PopupWindow
.OnDismissListener mOnDismissListener
;
165 * Flag whether a default activity currently being selected.
167 private boolean mIsSelectingDefaultActivity
;
170 * The count of activities in the popup.
172 private int mInitialActivityCount
= ActivityChooserViewAdapter
.MAX_ACTIVITY_COUNT_DEFAULT
;
175 * Flag whether this view is attached to a window.
177 private boolean mIsAttachedToWindow
;
180 * String resource for formatting content description of the default target.
182 private int mDefaultActionButtonContentDescription
;
184 private final Context mContext
;
187 * Create a new instance.
189 * @param context The application environment.
191 public ActivityChooserView(Context context
) {
196 * Create a new instance.
198 * @param context The application environment.
199 * @param attrs A collection of attributes.
201 public ActivityChooserView(Context context
, AttributeSet attrs
) {
202 this(context
, attrs
, 0);
206 * Create a new instance.
208 * @param context The application environment.
209 * @param attrs A collection of attributes.
210 * @param defStyle The default style to apply to this view.
212 public ActivityChooserView(Context context
, AttributeSet attrs
, int defStyle
) {
213 super(context
, attrs
, defStyle
);
216 TypedArray attributesArray
= context
.obtainStyledAttributes(attrs
,
217 R
.styleable
.SherlockActivityChooserView
, defStyle
, 0);
219 mInitialActivityCount
= attributesArray
.getInt(
220 R
.styleable
.SherlockActivityChooserView_initialActivityCount
,
221 ActivityChooserViewAdapter
.MAX_ACTIVITY_COUNT_DEFAULT
);
223 Drawable expandActivityOverflowButtonDrawable
= attributesArray
.getDrawable(
224 R
.styleable
.SherlockActivityChooserView_expandActivityOverflowButtonDrawable
);
226 attributesArray
.recycle();
228 LayoutInflater inflater
= LayoutInflater
.from(mContext
);
229 inflater
.inflate(R
.layout
.abs__activity_chooser_view
, this, true
);
231 mCallbacks
= new Callbacks();
233 mActivityChooserContent
= (IcsLinearLayout
) findViewById(R
.id
.abs__activity_chooser_view_content
);
234 mActivityChooserContentBackground
= mActivityChooserContent
.getBackground();
236 mDefaultActivityButton
= (FrameLayout
) findViewById(R
.id
.abs__default_activity_button
);
237 mDefaultActivityButton
.setOnClickListener(mCallbacks
);
238 mDefaultActivityButton
.setOnLongClickListener(mCallbacks
);
239 mDefaultActivityButtonImage
= (ImageView
) mDefaultActivityButton
.findViewById(R
.id
.abs__image
);
241 mExpandActivityOverflowButton
= (FrameLayout
) findViewById(R
.id
.abs__expand_activities_button
);
242 mExpandActivityOverflowButton
.setOnClickListener(mCallbacks
);
243 mExpandActivityOverflowButtonImage
=
244 (ImageView
) mExpandActivityOverflowButton
.findViewById(R
.id
.abs__image
);
245 mExpandActivityOverflowButtonImage
.setImageDrawable(expandActivityOverflowButtonDrawable
);
247 mAdapter
= new ActivityChooserViewAdapter();
248 mAdapter
.registerDataSetObserver(new DataSetObserver() {
250 public void onChanged() {
256 Resources resources
= context
.getResources();
257 mListPopupMaxWidth
= Math
.max(resources
.getDisplayMetrics().widthPixels
/ 2,
258 resources
.getDimensionPixelSize(R
.dimen
.abs__config_prefDialogWidth
));
264 public void setActivityChooserModel(ActivityChooserModel dataModel
) {
265 mAdapter
.setDataModel(dataModel
);
266 if (isShowingPopup()) {
273 * Sets the background for the button that expands the activity
276 * <strong>Note:</strong> Clients would like to set this drawable
277 * as a clue about the action the chosen activity will perform. For
278 * example, if a share activity is to be chosen the drawable should
279 * give a clue that sharing is to be performed.
281 * @param drawable The drawable.
283 public void setExpandActivityOverflowButtonDrawable(Drawable drawable
) {
284 mExpandActivityOverflowButtonImage
.setImageDrawable(drawable
);
288 * Sets the content description for the button that expands the activity
291 * description as a clue about the action performed by the button.
292 * For example, if a share activity is to be chosen the content
293 * description should be something like "Share with".
295 * @param resourceId The content description resource id.
297 public void setExpandActivityOverflowButtonContentDescription(int resourceId
) {
298 CharSequence contentDescription
= mContext
.getString(resourceId
);
299 mExpandActivityOverflowButtonImage
.setContentDescription(contentDescription
);
303 * Set the provider hosting this view, if applicable.
304 * @hide Internal use only
306 public void setProvider(ActionProvider provider
) {
307 mProvider
= provider
;
311 * Shows the popup window with activities.
313 * @return True if the popup was shown, false if already showing.
315 public boolean showPopup() {
316 if (isShowingPopup() || !mIsAttachedToWindow
) {
319 mIsSelectingDefaultActivity
= false
;
320 showPopupUnchecked(mInitialActivityCount
);
325 * Shows the popup no matter if it was already showing.
327 * @param maxActivityCount The max number of activities to display.
329 private void showPopupUnchecked(int maxActivityCount
) {
330 if (mAdapter
.getDataModel() == null
) {
331 throw new IllegalStateException("No data model. Did you call #setDataModel?");
334 getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener
);
336 final boolean defaultActivityButtonShown
=
337 mDefaultActivityButton
.getVisibility() == VISIBLE
;
339 final int activityCount
= mAdapter
.getActivityCount();
340 final int maxActivityCountOffset
= defaultActivityButtonShown ?
1 : 0;
341 if (maxActivityCount
!= ActivityChooserViewAdapter
.MAX_ACTIVITY_COUNT_UNLIMITED
342 && activityCount
> maxActivityCount
+ maxActivityCountOffset
) {
343 mAdapter
.setShowFooterView(true
);
344 mAdapter
.setMaxActivityCount(maxActivityCount
- 1);
346 mAdapter
.setShowFooterView(false
);
347 mAdapter
.setMaxActivityCount(maxActivityCount
);
350 IcsListPopupWindow popupWindow
= getListPopupWindow();
351 if (!popupWindow
.isShowing()) {
352 if (mIsSelectingDefaultActivity
|| !defaultActivityButtonShown
) {
353 mAdapter
.setShowDefaultActivity(true
, defaultActivityButtonShown
);
355 mAdapter
.setShowDefaultActivity(false
, false
);
357 final int contentWidth
= Math
.min(mAdapter
.measureContentWidth(), mListPopupMaxWidth
);
358 popupWindow
.setContentWidth(contentWidth
);
360 if (mProvider
!= null
) {
361 mProvider
.subUiVisibilityChanged(true
);
363 popupWindow
.getListView().setContentDescription(mContext
.getString(
364 R
.string
.abs__activitychooserview_choose_application
));
369 * Dismisses the popup window with activities.
371 * @return True if dismissed, false if already dismissed.
373 public boolean dismissPopup() {
374 if (isShowingPopup()) {
375 getListPopupWindow().dismiss();
376 ViewTreeObserver viewTreeObserver
= getViewTreeObserver();
377 if (viewTreeObserver
.isAlive()) {
378 viewTreeObserver
.removeGlobalOnLayoutListener(mOnGlobalLayoutListener
);
385 * Gets whether the popup window with activities is shown.
387 * @return True if the popup is shown.
389 public boolean isShowingPopup() {
390 return getListPopupWindow().isShowing();
394 protected void onAttachedToWindow() {
395 super.onAttachedToWindow();
396 ActivityChooserModel dataModel
= mAdapter
.getDataModel();
397 if (dataModel
!= null
) {
398 dataModel
.registerObserver(mModelDataSetOberver
);
400 mIsAttachedToWindow
= true
;
404 protected void onDetachedFromWindow() {
405 super.onDetachedFromWindow();
406 ActivityChooserModel dataModel
= mAdapter
.getDataModel();
407 if (dataModel
!= null
) {
409 dataModel
.unregisterObserver(mModelDataSetOberver
);
410 } catch (IllegalStateException e
) {
411 //Oh, well... fixes issue #557
414 ViewTreeObserver viewTreeObserver
= getViewTreeObserver();
415 if (viewTreeObserver
.isAlive()) {
416 viewTreeObserver
.removeGlobalOnLayoutListener(mOnGlobalLayoutListener
);
418 mIsAttachedToWindow
= false
;
422 protected void onMeasure(int widthMeasureSpec
, int heightMeasureSpec
) {
423 View child
= mActivityChooserContent
;
424 // If the default action is not visible we want to be as tall as the
425 // ActionBar so if this widget is used in the latter it will look as
426 // a normal action button.
427 if (mDefaultActivityButton
.getVisibility() != VISIBLE
) {
428 heightMeasureSpec
= MeasureSpec
.makeMeasureSpec(MeasureSpec
.getSize(heightMeasureSpec
),
429 MeasureSpec
.EXACTLY
);
431 measureChild(child
, widthMeasureSpec
, heightMeasureSpec
);
432 setMeasuredDimension(child
.getMeasuredWidth(), child
.getMeasuredHeight());
436 protected void onLayout(boolean changed
, int left
, int top
, int right
, int bottom
) {
437 mActivityChooserContent
.layout(0, 0, right
- left
, bottom
- top
);
438 if (getListPopupWindow().isShowing()) {
439 showPopupUnchecked(mAdapter
.getMaxActivityCount());
445 public ActivityChooserModel
getDataModel() {
446 return mAdapter
.getDataModel();
450 * Sets a listener to receive a callback when the popup is dismissed.
452 * @param listener The listener to be notified.
454 public void setOnDismissListener(PopupWindow
.OnDismissListener listener
) {
455 mOnDismissListener
= listener
;
459 * Sets the initial count of items shown in the activities popup
460 * i.e. the items before the popup is expanded. This is an upper
461 * bound since it is not guaranteed that such number of intent
464 * @param itemCount The initial popup item count.
466 public void setInitialActivityCount(int itemCount
) {
467 mInitialActivityCount
= itemCount
;
471 * Sets a content description of the default action button. This
472 * resource should be a string taking one formatting argument and
473 * will be used for formatting the content description of the button
474 * dynamically as the default target changes. For example, a resource
475 * pointing to the string "share with %1$s" will result in a content
476 * description "share with Bluetooth" for the Bluetooth activity.
478 * @param resourceId The resource id.
480 public void setDefaultActionButtonContentDescription(int resourceId
) {
481 mDefaultActionButtonContentDescription
= resourceId
;
485 * Gets the list popup window which is lazily initialized.
489 private IcsListPopupWindow
getListPopupWindow() {
490 if (mListPopupWindow
== null
) {
491 mListPopupWindow
= new IcsListPopupWindow(getContext());
492 mListPopupWindow
.setAdapter(mAdapter
);
493 mListPopupWindow
.setAnchorView(ActivityChooserView
.this);
494 mListPopupWindow
.setModal(true
);
495 mListPopupWindow
.setOnItemClickListener(mCallbacks
);
496 mListPopupWindow
.setOnDismissListener(mCallbacks
);
498 return mListPopupWindow
;
502 * Updates the buttons state.
504 private void updateAppearance() {
505 // Expand overflow button.
506 if (mAdapter
.getCount() > 0) {
507 mExpandActivityOverflowButton
.setEnabled(true
);
509 mExpandActivityOverflowButton
.setEnabled(false
);
511 // Default activity button.
512 final int activityCount
= mAdapter
.getActivityCount();
513 final int historySize
= mAdapter
.getHistorySize();
514 if (activityCount
> 0 && historySize
> 0) {
515 mDefaultActivityButton
.setVisibility(VISIBLE
);
516 ResolveInfo activity
= mAdapter
.getDefaultActivity();
517 PackageManager packageManager
= mContext
.getPackageManager();
518 mDefaultActivityButtonImage
.setImageDrawable(activity
.loadIcon(packageManager
));
519 if (mDefaultActionButtonContentDescription
!= 0) {
520 CharSequence label
= activity
.loadLabel(packageManager
);
521 String contentDescription
= mContext
.getString(
522 mDefaultActionButtonContentDescription
, label
);
523 mDefaultActivityButton
.setContentDescription(contentDescription
);
526 mDefaultActivityButton
.setVisibility(View
.GONE
);
528 // Activity chooser content.
529 if (mDefaultActivityButton
.getVisibility() == VISIBLE
) {
530 mActivityChooserContent
.setBackgroundDrawable(mActivityChooserContentBackground
);
532 mActivityChooserContent
.setBackgroundDrawable(null
);
533 mActivityChooserContent
.setPadding(0, 0, 0, 0);
538 * Interface implementation to avoid publishing them in the APIs.
540 private class Callbacks
implements AdapterView
.OnItemClickListener
,
541 View
.OnClickListener
, View
.OnLongClickListener
, PopupWindow
.OnDismissListener
{
543 // AdapterView#OnItemClickListener
544 public void onItemClick(AdapterView
<?
> parent
, View view
, int position
, long id
) {
545 ActivityChooserViewAdapter adapter
= (ActivityChooserViewAdapter
) parent
.getAdapter();
546 final int itemViewType
= adapter
.getItemViewType(position
);
547 switch (itemViewType
) {
548 case ActivityChooserViewAdapter
.ITEM_VIEW_TYPE_FOOTER
: {
549 showPopupUnchecked(ActivityChooserViewAdapter
.MAX_ACTIVITY_COUNT_UNLIMITED
);
551 case ActivityChooserViewAdapter
.ITEM_VIEW_TYPE_ACTIVITY
: {
553 if (mIsSelectingDefaultActivity
) {
554 // The item at position zero is the default already.
556 mAdapter
.getDataModel().setDefaultActivity(position
);
559 // If the default target is not shown in the list, the first
560 // item in the model is default action => adjust index
561 position
= mAdapter
.getShowDefaultActivity() ? position
: position
+ 1;
562 Intent launchIntent
= mAdapter
.getDataModel().chooseActivity(position
);
563 if (launchIntent
!= null
) {
564 mContext
.startActivity(launchIntent
);
569 throw new IllegalArgumentException();
573 // View.OnClickListener
574 public void onClick(View view
) {
575 if (view
== mDefaultActivityButton
) {
577 ResolveInfo defaultActivity
= mAdapter
.getDefaultActivity();
578 final int index
= mAdapter
.getDataModel().getActivityIndex(defaultActivity
);
579 Intent launchIntent
= mAdapter
.getDataModel().chooseActivity(index
);
580 if (launchIntent
!= null
) {
581 mContext
.startActivity(launchIntent
);
583 } else if (view
== mExpandActivityOverflowButton
) {
584 mIsSelectingDefaultActivity
= false
;
585 showPopupUnchecked(mInitialActivityCount
);
587 throw new IllegalArgumentException();
591 // OnLongClickListener#onLongClick
593 public boolean onLongClick(View view
) {
594 if (view
== mDefaultActivityButton
) {
595 if (mAdapter
.getCount() > 0) {
596 mIsSelectingDefaultActivity
= true
;
597 showPopupUnchecked(mInitialActivityCount
);
600 throw new IllegalArgumentException();
605 // PopUpWindow.OnDismissListener#onDismiss
606 public void onDismiss() {
607 notifyOnDismissListener();
608 if (mProvider
!= null
) {
609 mProvider
.subUiVisibilityChanged(false
);
613 private void notifyOnDismissListener() {
614 if (mOnDismissListener
!= null
) {
615 mOnDismissListener
.onDismiss();
620 private static class SetActivated
{
621 public static void invoke(View view
, boolean activated
) {
622 view
.setActivated(activated
);
626 private static final boolean IS_HONEYCOMB
= Build
.VERSION
.SDK_INT
>= Build
.VERSION_CODES
.HONEYCOMB
;
629 * Adapter for backing the list of activities shown in the popup.
631 private class ActivityChooserViewAdapter
extends BaseAdapter
{
633 public static final int MAX_ACTIVITY_COUNT_UNLIMITED
= Integer
.MAX_VALUE
;
635 public static final int MAX_ACTIVITY_COUNT_DEFAULT
= 4;
637 private static final int ITEM_VIEW_TYPE_ACTIVITY
= 0;
639 private static final int ITEM_VIEW_TYPE_FOOTER
= 1;
641 private static final int ITEM_VIEW_TYPE_COUNT
= 3;
643 private ActivityChooserModel mDataModel
;
645 private int mMaxActivityCount
= MAX_ACTIVITY_COUNT_DEFAULT
;
647 private boolean mShowDefaultActivity
;
649 private boolean mHighlightDefaultActivity
;
651 private boolean mShowFooterView
;
653 public void setDataModel(ActivityChooserModel dataModel
) {
654 ActivityChooserModel oldDataModel
= mAdapter
.getDataModel();
655 if (oldDataModel
!= null
&& isShown()) {
657 oldDataModel
.unregisterObserver(mModelDataSetOberver
);
658 } catch (IllegalStateException e
) {
659 //Oh, well... fixes issue #557
662 mDataModel
= dataModel
;
663 if (dataModel
!= null
&& isShown()) {
664 dataModel
.registerObserver(mModelDataSetOberver
);
666 notifyDataSetChanged();
670 public int getItemViewType(int position
) {
671 if (mShowFooterView
&& position
== getCount() - 1) {
672 return ITEM_VIEW_TYPE_FOOTER
;
674 return ITEM_VIEW_TYPE_ACTIVITY
;
679 public int getViewTypeCount() {
680 return ITEM_VIEW_TYPE_COUNT
;
683 public int getCount() {
685 int activityCount
= mDataModel
.getActivityCount();
686 if (!mShowDefaultActivity
&& mDataModel
.getDefaultActivity() != null
) {
689 count
= Math
.min(activityCount
, mMaxActivityCount
);
690 if (mShowFooterView
) {
696 public Object
getItem(int position
) {
697 final int itemViewType
= getItemViewType(position
);
698 switch (itemViewType
) {
699 case ITEM_VIEW_TYPE_FOOTER
:
701 case ITEM_VIEW_TYPE_ACTIVITY
:
702 if (!mShowDefaultActivity
&& mDataModel
.getDefaultActivity() != null
) {
705 return mDataModel
.getActivity(position
);
707 throw new IllegalArgumentException();
711 public long getItemId(int position
) {
715 public View
getView(int position
, View convertView
, ViewGroup parent
) {
716 final int itemViewType
= getItemViewType(position
);
717 switch (itemViewType
) {
718 case ITEM_VIEW_TYPE_FOOTER
:
719 if (convertView
== null
|| convertView
.getId() != ITEM_VIEW_TYPE_FOOTER
) {
720 convertView
= LayoutInflater
.from(getContext()).inflate(
721 R
.layout
.abs__activity_chooser_view_list_item
, parent
, false
);
722 convertView
.setId(ITEM_VIEW_TYPE_FOOTER
);
723 TextView titleView
= (TextView
) convertView
.findViewById(R
.id
.abs__title
);
724 titleView
.setText(mContext
.getString(
725 R
.string
.abs__activity_chooser_view_see_all
));
728 case ITEM_VIEW_TYPE_ACTIVITY
:
729 if (convertView
== null
|| convertView
.getId() != R
.id
.abs__list_item
) {
730 convertView
= LayoutInflater
.from(getContext()).inflate(
731 R
.layout
.abs__activity_chooser_view_list_item
, parent
, false
);
733 PackageManager packageManager
= mContext
.getPackageManager();
735 ImageView iconView
= (ImageView
) convertView
.findViewById(R
.id
.abs__icon
);
736 ResolveInfo activity
= (ResolveInfo
) getItem(position
);
737 iconView
.setImageDrawable(activity
.loadIcon(packageManager
));
739 TextView titleView
= (TextView
) convertView
.findViewById(R
.id
.abs__title
);
740 titleView
.setText(activity
.loadLabel(packageManager
));
742 // Highlight the default.
743 if (mShowDefaultActivity
&& position
== 0 && mHighlightDefaultActivity
) {
744 SetActivated
.invoke(convertView
, true
);
746 SetActivated
.invoke(convertView
, false
);
751 throw new IllegalArgumentException();
755 public int measureContentWidth() {
756 // The user may have specified some of the target not to be shown but we
757 // want to measure all of them since after expansion they should fit.
758 final int oldMaxActivityCount
= mMaxActivityCount
;
759 mMaxActivityCount
= MAX_ACTIVITY_COUNT_UNLIMITED
;
761 int contentWidth
= 0;
762 View itemView
= null
;
764 final int widthMeasureSpec
= MeasureSpec
.makeMeasureSpec(0, MeasureSpec
.UNSPECIFIED
);
765 final int heightMeasureSpec
= MeasureSpec
.makeMeasureSpec(0, MeasureSpec
.UNSPECIFIED
);
766 final int count
= getCount();
768 for (int i
= 0; i
< count
; i
++) {
769 itemView
= getView(i
, itemView
, null
);
770 itemView
.measure(widthMeasureSpec
, heightMeasureSpec
);
771 contentWidth
= Math
.max(contentWidth
, itemView
.getMeasuredWidth());
774 mMaxActivityCount
= oldMaxActivityCount
;
779 public void setMaxActivityCount(int maxActivityCount
) {
780 if (mMaxActivityCount
!= maxActivityCount
) {
781 mMaxActivityCount
= maxActivityCount
;
782 notifyDataSetChanged();
786 public ResolveInfo
getDefaultActivity() {
787 return mDataModel
.getDefaultActivity();
790 public void setShowFooterView(boolean showFooterView
) {
791 if (mShowFooterView
!= showFooterView
) {
792 mShowFooterView
= showFooterView
;
793 notifyDataSetChanged();
797 public int getActivityCount() {
798 return mDataModel
.getActivityCount();
801 public int getHistorySize() {
802 return mDataModel
.getHistorySize();
805 public int getMaxActivityCount() {
806 return mMaxActivityCount
;
809 public ActivityChooserModel
getDataModel() {
813 public void setShowDefaultActivity(boolean showDefaultActivity
,
814 boolean highlightDefaultActivity
) {
815 if (mShowDefaultActivity
!= showDefaultActivity
816 || mHighlightDefaultActivity
!= highlightDefaultActivity
) {
817 mShowDefaultActivity
= showDefaultActivity
;
818 mHighlightDefaultActivity
= highlightDefaultActivity
;
819 notifyDataSetChanged();
823 public boolean getShowDefaultActivity() {
824 return mShowDefaultActivity
;