ActivityChooserView.java revision f2e754002166b8126e6faf8c494da5835432d572
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 17package android.widget; 18 19import android.content.Context; 20import android.content.Intent; 21import android.content.pm.PackageManager; 22import android.content.pm.ResolveInfo; 23import android.content.res.Resources; 24import android.content.res.TypedArray; 25import android.database.DataSetObserver; 26import android.graphics.Canvas; 27import android.graphics.drawable.Drawable; 28import android.util.AttributeSet; 29import android.view.LayoutInflater; 30import android.view.View; 31import android.view.View.MeasureSpec; 32import android.view.ViewGroup; 33import android.view.ViewTreeObserver; 34import android.view.ViewTreeObserver.OnGlobalLayoutListener; 35import android.widget.ActivityChooserModel.ActivityChooserModelClient; 36 37import com.android.internal.R; 38 39/** 40 * This class is a view for choosing an activity for handling a given {@link Intent}. 41 * <p> 42 * The view is composed of two adjacent buttons: 43 * <ul> 44 * <li> 45 * The left button is an immediate action and allows one click activity choosing. 46 * Tapping this button immediately executes the intent without requiring any further 47 * user input. Long press on this button shows a popup for changing the default 48 * activity. 49 * </li> 50 * <li> 51 * The right button is an overflow action and provides an optimized menu 52 * of additional activities. Tapping this button shows a popup anchored to this 53 * view, listing the most frequently used activities. This list is initially 54 * limited to a small number of items in frequency used order. The last item, 55 * "Show all..." serves as an affordance to display all available activities. 56 * </li> 57 * </ul> 58 * </p> 59 * 60 * @hide 61 */ 62public class ActivityChooserView extends ViewGroup implements ActivityChooserModelClient { 63 64 /** 65 * An adapter for displaying the activities in an {@link AdapterView}. 66 */ 67 private final ActivityChooserViewAdapter mAdapter; 68 69 /** 70 * Implementation of various interfaces to avoid publishing them in the APIs. 71 */ 72 private final Callbacks mCallbacks; 73 74 /** 75 * The content of this view. 76 */ 77 private final LinearLayout mActivityChooserContent; 78 79 /** 80 * Stores the background drawable to allow hiding and latter showing. 81 */ 82 private final Drawable mActivityChooserContentBackground; 83 84 /** 85 * The expand activities action button; 86 */ 87 private final FrameLayout mExpandActivityOverflowButton; 88 89 /** 90 * The image for the expand activities action button; 91 */ 92 private final ImageView mExpandActivityOverflowButtonImage; 93 94 /** 95 * The default activities action button; 96 */ 97 private final FrameLayout mDefaultActivityButton; 98 99 /** 100 * The image for the default activities action button; 101 */ 102 private final ImageView mDefaultActivityButtonImage; 103 104 /** 105 * The maximal width of the list popup. 106 */ 107 private final int mListPopupMaxWidth; 108 109 /** 110 * Observer for the model data. 111 */ 112 private final DataSetObserver mModelDataSetOberver = new DataSetObserver() { 113 114 @Override 115 public void onChanged() { 116 super.onChanged(); 117 mAdapter.notifyDataSetChanged(); 118 } 119 @Override 120 public void onInvalidated() { 121 super.onInvalidated(); 122 mAdapter.notifyDataSetInvalidated(); 123 } 124 }; 125 126 private final OnGlobalLayoutListener mOnGlobalLayoutListener = new OnGlobalLayoutListener() { 127 @Override 128 public void onGlobalLayout() { 129 if (isShowingPopup()) { 130 if (!isShown()) { 131 getListPopupWindow().dismiss(); 132 } else { 133 getListPopupWindow().show(); 134 } 135 } 136 } 137 }; 138 139 /** 140 * Popup window for showing the activity overflow list. 141 */ 142 private ListPopupWindow mListPopupWindow; 143 144 /** 145 * Listener for the dismissal of the popup/alert. 146 */ 147 private PopupWindow.OnDismissListener mOnDismissListener; 148 149 /** 150 * Flag whether a default activity currently being selected. 151 */ 152 private boolean mIsSelectingDefaultActivity; 153 154 /** 155 * The count of activities in the popup. 156 */ 157 private int mInitialActivityCount = ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT; 158 159 /** 160 * Flag whether this view is attached to a window. 161 */ 162 private boolean mIsAttachedToWindow; 163 164 /** 165 * Create a new instance. 166 * 167 * @param context The application environment. 168 */ 169 public ActivityChooserView(Context context) { 170 this(context, null); 171 } 172 173 /** 174 * Create a new instance. 175 * 176 * @param context The application environment. 177 * @param attrs A collection of attributes. 178 */ 179 public ActivityChooserView(Context context, AttributeSet attrs) { 180 this(context, attrs, 0); 181 } 182 183 /** 184 * Create a new instance. 185 * 186 * @param context The application environment. 187 * @param attrs A collection of attributes. 188 * @param defStyle The default style to apply to this view. 189 */ 190 public ActivityChooserView(Context context, AttributeSet attrs, int defStyle) { 191 super(context, attrs, defStyle); 192 193 TypedArray attributesArray = context.obtainStyledAttributes(attrs, 194 R.styleable.ActivityChooserView, defStyle, 0); 195 196 mInitialActivityCount = attributesArray.getInt( 197 R.styleable.ActivityChooserView_initialActivityCount, 198 ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT); 199 200 Drawable expandActivityOverflowButtonDrawable = attributesArray.getDrawable( 201 R.styleable.ActivityChooserView_expandActivityOverflowButtonDrawable); 202 203 attributesArray.recycle(); 204 205 LayoutInflater inflater = LayoutInflater.from(mContext); 206 inflater.inflate(R.layout.activity_chooser_view, this, true); 207 208 mCallbacks = new Callbacks(); 209 210 mActivityChooserContent = (LinearLayout) findViewById(R.id.activity_chooser_view_content); 211 mActivityChooserContentBackground = mActivityChooserContent.getBackground(); 212 213 mDefaultActivityButton = (FrameLayout) findViewById(R.id.default_activity_button); 214 mDefaultActivityButton.setOnClickListener(mCallbacks); 215 mDefaultActivityButton.setOnLongClickListener(mCallbacks); 216 mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.image); 217 218 mExpandActivityOverflowButton = (FrameLayout) findViewById(R.id.expand_activities_button); 219 mExpandActivityOverflowButton.setOnClickListener(mCallbacks); 220 mExpandActivityOverflowButtonImage = 221 (ImageView) mExpandActivityOverflowButton.findViewById(R.id.image); 222 mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable); 223 224 mAdapter = new ActivityChooserViewAdapter(); 225 mAdapter.registerDataSetObserver(new DataSetObserver() { 226 @Override 227 public void onChanged() { 228 super.onChanged(); 229 updateAppearance(); 230 } 231 }); 232 233 Resources resources = context.getResources(); 234 mListPopupMaxWidth = Math.max(resources.getDisplayMetrics().widthPixels / 2, 235 resources.getDimensionPixelSize(com.android.internal.R.dimen.config_prefDialogWidth)); 236 } 237 238 /** 239 * {@inheritDoc} 240 */ 241 public void setActivityChooserModel(ActivityChooserModel dataModel) { 242 mAdapter.setDataModel(dataModel); 243 if (isShowingPopup()) { 244 dismissPopup(); 245 showPopup(); 246 } 247 } 248 249 /** 250 * Sets the background for the button that expands the activity 251 * overflow list. 252 * 253 * <strong>Note:</strong> Clients would like to set this drawable 254 * as a clue about the action the chosen activity will perform. For 255 * example, if share activity is to be chosen the drawable should 256 * give a clue that sharing is to be performed. 257 * 258 * @param drawable The drawable. 259 */ 260 public void setExpandActivityOverflowButtonDrawable(Drawable drawable) { 261 mExpandActivityOverflowButtonImage.setImageDrawable(drawable); 262 } 263 264 /** 265 * Shows the popup window with activities. 266 * 267 * @return True if the popup was shown, false if already showing. 268 */ 269 public boolean showPopup() { 270 if (isShowingPopup() || !mIsAttachedToWindow) { 271 return false; 272 } 273 mIsSelectingDefaultActivity = false; 274 showPopupUnchecked(mInitialActivityCount); 275 return true; 276 } 277 278 /** 279 * Shows the popup no matter if it was already showing. 280 * 281 * @param maxActivityCount The max number of activities to display. 282 */ 283 private void showPopupUnchecked(int maxActivityCount) { 284 if (mAdapter.getDataModel() == null) { 285 throw new IllegalStateException("No data model. Did you call #setDataModel?"); 286 } 287 288 getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener); 289 290 mAdapter.setMaxActivityCount(maxActivityCount); 291 292 final int activityCount = mAdapter.getActivityCount(); 293 if (maxActivityCount != ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED 294 && activityCount > maxActivityCount + 1) { 295 mAdapter.setShowFooterView(true); 296 } else { 297 mAdapter.setShowFooterView(false); 298 } 299 300 ListPopupWindow popupWindow = getListPopupWindow(); 301 if (!popupWindow.isShowing()) { 302 if (mIsSelectingDefaultActivity) { 303 mAdapter.setShowDefaultActivity(true); 304 } else { 305 mAdapter.setShowDefaultActivity(false); 306 } 307 final int contentWidth = Math.min(mAdapter.measureContentWidth(), mListPopupMaxWidth); 308 popupWindow.setContentWidth(contentWidth); 309 popupWindow.show(); 310 } 311 } 312 313 /** 314 * Dismisses the popup window with activities. 315 * 316 * @return True if dismissed, false if already dismissed. 317 */ 318 public boolean dismissPopup() { 319 if (isShowingPopup()) { 320 getListPopupWindow().dismiss(); 321 ViewTreeObserver viewTreeObserver = getViewTreeObserver(); 322 if (viewTreeObserver.isAlive()) { 323 viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener); 324 } 325 } 326 return true; 327 } 328 329 /** 330 * Gets whether the popup window with activities is shown. 331 * 332 * @return True if the popup is shown. 333 */ 334 public boolean isShowingPopup() { 335 return getListPopupWindow().isShowing(); 336 } 337 338 @Override 339 protected void onAttachedToWindow() { 340 super.onAttachedToWindow(); 341 ActivityChooserModel dataModel = mAdapter.getDataModel(); 342 if (dataModel != null) { 343 dataModel.registerObserver(mModelDataSetOberver); 344 } 345 mIsAttachedToWindow = true; 346 } 347 348 @Override 349 protected void onDetachedFromWindow() { 350 super.onDetachedFromWindow(); 351 ActivityChooserModel dataModel = mAdapter.getDataModel(); 352 if (dataModel != null) { 353 dataModel.unregisterObserver(mModelDataSetOberver); 354 } 355 ViewTreeObserver viewTreeObserver = getViewTreeObserver(); 356 if (viewTreeObserver.isAlive()) { 357 viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener); 358 } 359 mIsAttachedToWindow = false; 360 } 361 362 @Override 363 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 364 View child = mActivityChooserContent; 365 // If the default action is not visible we want to be as tall as the 366 // ActionBar so if this widget is used in the latter it will look as 367 // a normal action button. 368 if (mDefaultActivityButton.getVisibility() != VISIBLE) { 369 heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), 370 MeasureSpec.EXACTLY); 371 } 372 measureChild(child, widthMeasureSpec, heightMeasureSpec); 373 setMeasuredDimension(child.getMeasuredWidth(), child.getMeasuredHeight()); 374 } 375 376 @Override 377 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 378 mActivityChooserContent.layout(0, 0, right - left, bottom - top); 379 if (getListPopupWindow().isShowing()) { 380 showPopupUnchecked(mAdapter.getMaxActivityCount()); 381 } else { 382 dismissPopup(); 383 } 384 } 385 386 public ActivityChooserModel getDataModel() { 387 return mAdapter.getDataModel(); 388 } 389 390 /** 391 * Sets a listener to receive a callback when the popup is dismissed. 392 * 393 * @param listener The listener to be notified. 394 */ 395 public void setOnDismissListener(PopupWindow.OnDismissListener listener) { 396 mOnDismissListener = listener; 397 } 398 399 /** 400 * Sets the initial count of items shown in the activities popup 401 * i.e. the items before the popup is expanded. This is an upper 402 * bound since it is not guaranteed that such number of intent 403 * handlers exist. 404 * 405 * @param itemCount The initial popup item count. 406 */ 407 public void setInitialActivityCount(int itemCount) { 408 mInitialActivityCount = itemCount; 409 } 410 411 /** 412 * Gets the list popup window which is lazily initialized. 413 * 414 * @return The popup. 415 */ 416 private ListPopupWindow getListPopupWindow() { 417 if (mListPopupWindow == null) { 418 mListPopupWindow = new ListPopupWindow(getContext()); 419 mListPopupWindow.setAdapter(mAdapter); 420 mListPopupWindow.setAnchorView(ActivityChooserView.this); 421 mListPopupWindow.setModal(true); 422 mListPopupWindow.setOnItemClickListener(mCallbacks); 423 mListPopupWindow.setOnDismissListener(mCallbacks); 424 } 425 return mListPopupWindow; 426 } 427 428 /** 429 * Updates the buttons state. 430 */ 431 private void updateAppearance() { 432 // Expand overflow button. 433 if (mAdapter.getCount() > 0) { 434 mExpandActivityOverflowButton.setEnabled(true); 435 } else { 436 mExpandActivityOverflowButton.setEnabled(false); 437 } 438 // Default activity button. 439 final int activityCount = mAdapter.getActivityCount(); 440 final int historySize = mAdapter.getHistorySize(); 441 if (activityCount > 0 && historySize > 0) { 442 mDefaultActivityButton.setVisibility(VISIBLE); 443 ResolveInfo activity = mAdapter.getDefaultActivity(); 444 PackageManager packageManager = mContext.getPackageManager(); 445 mDefaultActivityButtonImage.setImageDrawable(activity.loadIcon(packageManager)); 446 } else { 447 mDefaultActivityButton.setVisibility(View.GONE); 448 } 449 // Activity chooser content. 450 if (mDefaultActivityButton.getVisibility() == VISIBLE) { 451 mActivityChooserContent.setBackgroundDrawable(mActivityChooserContentBackground); 452 } else { 453 mActivityChooserContent.setBackgroundDrawable(null); 454 } 455 } 456 457 /** 458 * Interface implementation to avoid publishing them in the APIs. 459 */ 460 private class Callbacks implements AdapterView.OnItemClickListener, 461 View.OnClickListener, View.OnLongClickListener, PopupWindow.OnDismissListener { 462 463 // AdapterView#OnItemClickListener 464 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 465 ActivityChooserViewAdapter adapter = (ActivityChooserViewAdapter) parent.getAdapter(); 466 final int itemViewType = adapter.getItemViewType(position); 467 switch (itemViewType) { 468 case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_FOOTER: { 469 showPopupUnchecked(ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED); 470 } break; 471 case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_ACTIVITY: { 472 dismissPopup(); 473 if (mIsSelectingDefaultActivity) { 474 // The item at position zero is the default already. 475 if (position > 0) { 476 mAdapter.getDataModel().setDefaultActivity(position); 477 } 478 } else { 479 // The first item in the model is default action => adjust index 480 Intent launchIntent = mAdapter.getDataModel().chooseActivity(position + 1); 481 if (launchIntent != null) { 482 mContext.startActivity(launchIntent); 483 } 484 } 485 } break; 486 default: 487 throw new IllegalArgumentException(); 488 } 489 } 490 491 // View.OnClickListener 492 public void onClick(View view) { 493 if (view == mDefaultActivityButton) { 494 dismissPopup(); 495 ResolveInfo defaultActivity = mAdapter.getDefaultActivity(); 496 final int index = mAdapter.getDataModel().getActivityIndex(defaultActivity); 497 Intent launchIntent = mAdapter.getDataModel().chooseActivity(index); 498 if (launchIntent != null) { 499 mContext.startActivity(launchIntent); 500 } 501 } else if (view == mExpandActivityOverflowButton) { 502 mIsSelectingDefaultActivity = false; 503 showPopupUnchecked(mInitialActivityCount); 504 } else { 505 throw new IllegalArgumentException(); 506 } 507 } 508 509 // OnLongClickListener#onLongClick 510 @Override 511 public boolean onLongClick(View view) { 512 if (view == mDefaultActivityButton) { 513 if (mAdapter.getCount() > 0) { 514 mIsSelectingDefaultActivity = true; 515 showPopupUnchecked(mInitialActivityCount); 516 } 517 } else { 518 throw new IllegalArgumentException(); 519 } 520 return true; 521 } 522 523 // PopUpWindow.OnDismissListener#onDismiss 524 public void onDismiss() { 525 notifyOnDismissListener(); 526 } 527 528 private void notifyOnDismissListener() { 529 if (mOnDismissListener != null) { 530 mOnDismissListener.onDismiss(); 531 } 532 } 533 } 534 535 /** 536 * Adapter for backing the list of activities shown in the popup. 537 */ 538 private class ActivityChooserViewAdapter extends BaseAdapter { 539 540 public static final int MAX_ACTIVITY_COUNT_UNLIMITED = Integer.MAX_VALUE; 541 542 public static final int MAX_ACTIVITY_COUNT_DEFAULT = 4; 543 544 private static final int ITEM_VIEW_TYPE_ACTIVITY = 0; 545 546 private static final int ITEM_VIEW_TYPE_FOOTER = 1; 547 548 private static final int ITEM_VIEW_TYPE_COUNT = 3; 549 550 private ActivityChooserModel mDataModel; 551 552 private int mMaxActivityCount = MAX_ACTIVITY_COUNT_DEFAULT; 553 554 private boolean mShowDefaultActivity; 555 556 private boolean mShowFooterView; 557 558 public void setDataModel(ActivityChooserModel dataModel) { 559 ActivityChooserModel oldDataModel = mAdapter.getDataModel(); 560 if (oldDataModel != null && isShown()) { 561 oldDataModel.unregisterObserver(mModelDataSetOberver); 562 } 563 mDataModel = dataModel; 564 if (dataModel != null && isShown()) { 565 dataModel.registerObserver(mModelDataSetOberver); 566 } 567 notifyDataSetChanged(); 568 } 569 570 @Override 571 public int getItemViewType(int position) { 572 if (mShowFooterView && position == getCount() - 1) { 573 return ITEM_VIEW_TYPE_FOOTER; 574 } else { 575 return ITEM_VIEW_TYPE_ACTIVITY; 576 } 577 } 578 579 @Override 580 public int getViewTypeCount() { 581 return ITEM_VIEW_TYPE_COUNT; 582 } 583 584 public int getCount() { 585 int count = 0; 586 int activityCount = mDataModel.getActivityCount(); 587 if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) { 588 activityCount--; 589 } 590 count = Math.min(activityCount, mMaxActivityCount); 591 if (mShowFooterView) { 592 count++; 593 } 594 return count; 595 } 596 597 public Object getItem(int position) { 598 final int itemViewType = getItemViewType(position); 599 switch (itemViewType) { 600 case ITEM_VIEW_TYPE_FOOTER: 601 return null; 602 case ITEM_VIEW_TYPE_ACTIVITY: 603 if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) { 604 position++; 605 } 606 return mDataModel.getActivity(position); 607 default: 608 throw new IllegalArgumentException(); 609 } 610 } 611 612 public long getItemId(int position) { 613 return position; 614 } 615 616 public View getView(int position, View convertView, ViewGroup parent) { 617 final int itemViewType = getItemViewType(position); 618 switch (itemViewType) { 619 case ITEM_VIEW_TYPE_FOOTER: 620 if (convertView == null || convertView.getId() != ITEM_VIEW_TYPE_FOOTER) { 621 convertView = LayoutInflater.from(getContext()).inflate( 622 R.layout.activity_chooser_view_list_item, parent, false); 623 convertView.setId(ITEM_VIEW_TYPE_FOOTER); 624 TextView titleView = (TextView) convertView.findViewById(R.id.title); 625 titleView.setText(mContext.getString( 626 R.string.activity_chooser_view_see_all)); 627 } 628 return convertView; 629 case ITEM_VIEW_TYPE_ACTIVITY: 630 if (convertView == null || convertView.getId() != R.id.list_item) { 631 convertView = LayoutInflater.from(getContext()).inflate( 632 R.layout.activity_chooser_view_list_item, parent, false); 633 } 634 PackageManager packageManager = mContext.getPackageManager(); 635 // Set the icon 636 ImageView iconView = (ImageView) convertView.findViewById(R.id.icon); 637 ResolveInfo activity = (ResolveInfo) getItem(position); 638 iconView.setImageDrawable(activity.loadIcon(packageManager)); 639 // Set the title. 640 TextView titleView = (TextView) convertView.findViewById(R.id.title); 641 titleView.setText(activity.loadLabel(packageManager)); 642 // Highlight the default. 643 if (mShowDefaultActivity && position == 0) { 644 convertView.setActivated(true); 645 } else { 646 convertView.setActivated(false); 647 } 648 return convertView; 649 default: 650 throw new IllegalArgumentException(); 651 } 652 } 653 654 public int measureContentWidth() { 655 // The user may have specified some of the target not to be shown but we 656 // want to measure all of them since after expansion they should fit. 657 final int oldMaxActivityCount = mMaxActivityCount; 658 mMaxActivityCount = MAX_ACTIVITY_COUNT_UNLIMITED; 659 660 int contentWidth = 0; 661 View itemView = null; 662 663 final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 664 final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 665 final int count = getCount(); 666 667 for (int i = 0; i < count; i++) { 668 itemView = getView(i, itemView, null); 669 itemView.measure(widthMeasureSpec, heightMeasureSpec); 670 contentWidth = Math.max(contentWidth, itemView.getMeasuredWidth()); 671 } 672 673 mMaxActivityCount = oldMaxActivityCount; 674 675 return contentWidth; 676 } 677 678 public void setMaxActivityCount(int maxActivityCount) { 679 if (mMaxActivityCount != maxActivityCount) { 680 mMaxActivityCount = maxActivityCount; 681 notifyDataSetChanged(); 682 } 683 } 684 685 public ResolveInfo getDefaultActivity() { 686 return mDataModel.getDefaultActivity(); 687 } 688 689 public void setShowFooterView(boolean showFooterView) { 690 if (mShowFooterView != showFooterView) { 691 mShowFooterView = showFooterView; 692 notifyDataSetChanged(); 693 } 694 } 695 696 public int getActivityCount() { 697 return mDataModel.getActivityCount(); 698 } 699 700 public int getHistorySize() { 701 return mDataModel.getHistorySize(); 702 } 703 704 public int getMaxActivityCount() { 705 return mMaxActivityCount; 706 } 707 708 public ActivityChooserModel getDataModel() { 709 return mDataModel; 710 } 711 712 public void setShowDefaultActivity(boolean showDefaultActivity) { 713 if (mShowDefaultActivity != showDefaultActivity) { 714 mShowDefaultActivity = showDefaultActivity; 715 notifyDataSetChanged(); 716 } 717 } 718 } 719} 720