ActivityChooserView.java revision 314419ccb9daa215c5148f59e5b60c696ef51385
151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov/* 251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Copyright (C) 2011 The Android Open Source Project 351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License"); 551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * you may not use this file except in compliance with the License. 651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * You may obtain a copy of the License at 751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * http://www.apache.org/licenses/LICENSE-2.0 951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 1051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Unless required by applicable law or agreed to in writing, software 1151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS, 1251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * See the License for the specific language governing permissions and 1451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * limitations under the License. 1551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 1651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 1751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovpackage android.widget; 1851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 19823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powellimport com.android.internal.R; 20823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell 2151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.content.Context; 2251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.content.Intent; 2351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.content.pm.PackageManager; 2451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.content.pm.ResolveInfo; 25414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganovimport android.content.res.Resources; 2651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.content.res.TypedArray; 2751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.database.DataSetObserver; 2851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.graphics.drawable.Drawable; 2951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.util.AttributeSet; 30823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powellimport android.view.ActionProvider; 3151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.view.LayoutInflater; 3251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.view.View; 3351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.view.ViewGroup; 348c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganovimport android.view.ViewTreeObserver; 358c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganovimport android.view.ViewTreeObserver.OnGlobalLayoutListener; 3670853772bd119339244a4fc8e020ad78495228beSvetoslav Ganovimport android.view.accessibility.AccessibilityEvent; 3770853772bd119339244a4fc8e020ad78495228beSvetoslav Ganovimport android.view.accessibility.AccessibilityManager; 3851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovimport android.widget.ActivityChooserModel.ActivityChooserModelClient; 3951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 4051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov/** 4151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * This class is a view for choosing an activity for handling a given {@link Intent}. 4251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * <p> 4351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * The view is composed of two adjacent buttons: 4451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * <ul> 4551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * <li> 4651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * The left button is an immediate action and allows one click activity choosing. 4751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Tapping this button immediately executes the intent without requiring any further 4851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * user input. Long press on this button shows a popup for changing the default 4951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * activity. 5051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * </li> 5151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * <li> 5251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * The right button is an overflow action and provides an optimized menu 5351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * of additional activities. Tapping this button shows a popup anchored to this 5451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * view, listing the most frequently used activities. This list is initially 5551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * limited to a small number of items in frequency used order. The last item, 5651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * "Show all..." serves as an affordance to display all available activities. 5751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * </li> 5851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * </ul> 5951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * </p> 6051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 6151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @hide 6251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 6351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganovpublic class ActivityChooserView extends ViewGroup implements ActivityChooserModelClient { 6451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 6551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 6651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * An adapter for displaying the activities in an {@link AdapterView}. 6751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 6851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private final ActivityChooserViewAdapter mAdapter; 6951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 7051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 7151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Implementation of various interfaces to avoid publishing them in the APIs. 7251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 7351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private final Callbacks mCallbacks; 7451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 7551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 7651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * The content of this view. 7751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 7851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private final LinearLayout mActivityChooserContent; 7951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 8051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 81f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov * Stores the background drawable to allow hiding and latter showing. 82f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov */ 83f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov private final Drawable mActivityChooserContentBackground; 84f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov 85f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov /** 8651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * The expand activities action button; 8751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 88bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov private final FrameLayout mExpandActivityOverflowButton; 89bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov 90bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov /** 91bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov * The image for the expand activities action button; 92bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov */ 93bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov private final ImageView mExpandActivityOverflowButtonImage; 9451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 9551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 9651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * The default activities action button; 9751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 98bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov private final FrameLayout mDefaultActivityButton; 99bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov 100bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov /** 101bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov * The image for the default activities action button; 102bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov */ 103bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov private final ImageView mDefaultActivityButtonImage; 10451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 10551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 106414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov * The maximal width of the list popup. 107414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov */ 108414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov private final int mListPopupMaxWidth; 109414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov 110414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov /** 111823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell * The ActionProvider hosting this view, if applicable. 112823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell */ 113823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell ActionProvider mProvider; 114823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell 115823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell /** 11676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov * Observer for the model data. 11751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 11876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov private final DataSetObserver mModelDataSetOberver = new DataSetObserver() { 11951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 12076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov @Override 12176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov public void onChanged() { 12276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov super.onChanged(); 12376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov mAdapter.notifyDataSetChanged(); 12476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov } 12576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov @Override 12676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov public void onInvalidated() { 12776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov super.onInvalidated(); 12876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov mAdapter.notifyDataSetInvalidated(); 12976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov } 13076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov }; 13151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 1328c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov private final OnGlobalLayoutListener mOnGlobalLayoutListener = new OnGlobalLayoutListener() { 1338c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov @Override 1348c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov public void onGlobalLayout() { 1358c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov if (isShowingPopup()) { 1368c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov if (!isShown()) { 1378c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov getListPopupWindow().dismiss(); 1388c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov } else { 1398c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov getListPopupWindow().show(); 140823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell if (mProvider != null) { 141823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell mProvider.subUiVisibilityChanged(true); 142823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell } 1438c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov } 1448c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov } 1458c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov } 1468c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov }; 1478c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov 14851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 14951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Popup window for showing the activity overflow list. 15051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 15151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private ListPopupWindow mListPopupWindow; 15251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 15351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 15451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Listener for the dismissal of the popup/alert. 15551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 15651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private PopupWindow.OnDismissListener mOnDismissListener; 15751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 15851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 15951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Flag whether a default activity currently being selected. 16051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 16151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private boolean mIsSelectingDefaultActivity; 16251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 16351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 16451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * The count of activities in the popup. 16551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 16651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private int mInitialActivityCount = ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT; 16751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 16851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 16951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Flag whether this view is attached to a window. 17051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 17151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private boolean mIsAttachedToWindow; 17251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 17351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 17470853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * String resource for formatting content description of the default target. 17570853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov */ 17670853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov private int mDefaultActionButtonContentDescription; 17770853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov 17870853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov /** 17951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Create a new instance. 18051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 18151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @param context The application environment. 18251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 18351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public ActivityChooserView(Context context) { 18451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov this(context, null); 18551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 18651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 18751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 18851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Create a new instance. 18951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 19051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @param context The application environment. 19151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @param attrs A collection of attributes. 19251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 19351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public ActivityChooserView(Context context, AttributeSet attrs) { 19423f4cc0353615107cc9c19fda9cf96ddd43266e2Adam Powell this(context, attrs, 0); 19551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 19651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 19751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 19851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Create a new instance. 19951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 20051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @param context The application environment. 20151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @param attrs A collection of attributes. 20251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @param defStyle The default style to apply to this view. 20351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 20451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public ActivityChooserView(Context context, AttributeSet attrs, int defStyle) { 20551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov super(context, attrs, defStyle); 20651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 20751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov TypedArray attributesArray = context.obtainStyledAttributes(attrs, 20851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov R.styleable.ActivityChooserView, defStyle, 0); 20951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 21051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mInitialActivityCount = attributesArray.getInt( 21151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov R.styleable.ActivityChooserView_initialActivityCount, 21251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT); 21351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 21451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov Drawable expandActivityOverflowButtonDrawable = attributesArray.getDrawable( 21551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov R.styleable.ActivityChooserView_expandActivityOverflowButtonDrawable); 21651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 217f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov attributesArray.recycle(); 218f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov 21976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov LayoutInflater inflater = LayoutInflater.from(mContext); 22051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov inflater.inflate(R.layout.activity_chooser_view, this, true); 22151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 22251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mCallbacks = new Callbacks(); 22351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 22451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mActivityChooserContent = (LinearLayout) findViewById(R.id.activity_chooser_view_content); 225f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov mActivityChooserContentBackground = mActivityChooserContent.getBackground(); 22651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 227bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov mDefaultActivityButton = (FrameLayout) findViewById(R.id.default_activity_button); 228bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov mDefaultActivityButton.setOnClickListener(mCallbacks); 229bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov mDefaultActivityButton.setOnLongClickListener(mCallbacks); 230bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.image); 23151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 232bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov mExpandActivityOverflowButton = (FrameLayout) findViewById(R.id.expand_activities_button); 23351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mExpandActivityOverflowButton.setOnClickListener(mCallbacks); 234bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov mExpandActivityOverflowButtonImage = 235bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov (ImageView) mExpandActivityOverflowButton.findViewById(R.id.image); 236bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable); 23751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 23851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mAdapter = new ActivityChooserViewAdapter(); 23951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mAdapter.registerDataSetObserver(new DataSetObserver() { 24051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov @Override 24151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public void onChanged() { 24251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov super.onChanged(); 243f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov updateAppearance(); 24451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 24551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov }); 246414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov 247414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov Resources resources = context.getResources(); 248414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov mListPopupMaxWidth = Math.max(resources.getDisplayMetrics().widthPixels / 2, 249414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov resources.getDimensionPixelSize(com.android.internal.R.dimen.config_prefDialogWidth)); 25051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 25151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 25251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 25351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * {@inheritDoc} 25451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 25551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public void setActivityChooserModel(ActivityChooserModel dataModel) { 25651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mAdapter.setDataModel(dataModel); 25751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov if (isShowingPopup()) { 25851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov dismissPopup(); 25951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov showPopup(); 26051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 26151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 26251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 26351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 26451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Sets the background for the button that expands the activity 26551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * overflow list. 26651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 26751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * <strong>Note:</strong> Clients would like to set this drawable 26851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * as a clue about the action the chosen activity will perform. For 26970853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * example, if a share activity is to be chosen the drawable should 27051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * give a clue that sharing is to be performed. 27151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 27251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @param drawable The drawable. 27351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 27451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public void setExpandActivityOverflowButtonDrawable(Drawable drawable) { 275bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov mExpandActivityOverflowButtonImage.setImageDrawable(drawable); 27651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 27751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 27851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 27970853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * Sets the content description for the button that expands the activity 28070853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * overflow list. 28170853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * 28270853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * description as a clue about the action performed by the button. 28370853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * For example, if a share activity is to be chosen the content 28470853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * description should be something like "Share with". 28570853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * 28670853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * @param resourceId The content description resource id. 28770853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov */ 28870853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov public void setExpandActivityOverflowButtonContentDescription(int resourceId) { 28970853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov CharSequence contentDescription = mContext.getString(resourceId); 29070853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov mExpandActivityOverflowButtonImage.setContentDescription(contentDescription); 29170853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov } 29270853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov 29370853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov /** 294823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell * Set the provider hosting this view, if applicable. 295823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell * @hide Internal use only 296823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell */ 297823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell public void setProvider(ActionProvider provider) { 298823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell mProvider = provider; 299823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell } 300823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell 301823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell /** 30251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Shows the popup window with activities. 30351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 30451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @return True if the popup was shown, false if already showing. 30551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 30651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public boolean showPopup() { 30776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov if (isShowingPopup() || !mIsAttachedToWindow) { 30851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return false; 30951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 31051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mIsSelectingDefaultActivity = false; 31151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov showPopupUnchecked(mInitialActivityCount); 31251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return true; 31351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 31451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 31551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 31651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Shows the popup no matter if it was already showing. 31751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 31851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @param maxActivityCount The max number of activities to display. 31951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 32051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private void showPopupUnchecked(int maxActivityCount) { 32176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov if (mAdapter.getDataModel() == null) { 32276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov throw new IllegalStateException("No data model. Did you call #setDataModel?"); 32351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 32451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 3258c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener); 3268c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov 327f632eaa9d64fb21892cc057ec7444ec157686734Svetoslav Ganov final boolean defaultActivityButtonShown = 328f632eaa9d64fb21892cc057ec7444ec157686734Svetoslav Ganov mDefaultActivityButton.getVisibility() == VISIBLE; 329f632eaa9d64fb21892cc057ec7444ec157686734Svetoslav Ganov 33076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov final int activityCount = mAdapter.getActivityCount(); 331f632eaa9d64fb21892cc057ec7444ec157686734Svetoslav Ganov final int maxActivityCountOffset = defaultActivityButtonShown ? 1 : 0; 33276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov if (maxActivityCount != ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED 333f632eaa9d64fb21892cc057ec7444ec157686734Svetoslav Ganov && activityCount > maxActivityCount + maxActivityCountOffset) { 33476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov mAdapter.setShowFooterView(true); 3351c07e22c364732779b33c72bdc0e18c4bda0f7efSvetoslav Ganov mAdapter.setMaxActivityCount(maxActivityCount - 1); 33651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } else { 33776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov mAdapter.setShowFooterView(false); 3381c07e22c364732779b33c72bdc0e18c4bda0f7efSvetoslav Ganov mAdapter.setMaxActivityCount(maxActivityCount); 33951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 34051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 34176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov ListPopupWindow popupWindow = getListPopupWindow(); 34276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov if (!popupWindow.isShowing()) { 343efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov if (mIsSelectingDefaultActivity || !defaultActivityButtonShown) { 344efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov mAdapter.setShowDefaultActivity(true, defaultActivityButtonShown); 34576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov } else { 346efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov mAdapter.setShowDefaultActivity(false, false); 34751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 348414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov final int contentWidth = Math.min(mAdapter.measureContentWidth(), mListPopupMaxWidth); 349414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov popupWindow.setContentWidth(contentWidth); 35076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov popupWindow.show(); 351823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell if (mProvider != null) { 352823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell mProvider.subUiVisibilityChanged(true); 353823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell } 35470853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov popupWindow.getListView().setContentDescription(mContext.getString( 35570853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov R.string.activitychooserview_choose_application)); 35651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 35751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 35851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 35951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 36051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Dismisses the popup window with activities. 36151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 36251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @return True if dismissed, false if already dismissed. 36351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 36451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public boolean dismissPopup() { 36576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov if (isShowingPopup()) { 36651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov getListPopupWindow().dismiss(); 3678c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov ViewTreeObserver viewTreeObserver = getViewTreeObserver(); 3688c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov if (viewTreeObserver.isAlive()) { 3698c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener); 3708c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov } 37151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 37251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return true; 37351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 37451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 37551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 37651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Gets whether the popup window with activities is shown. 37751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 37851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @return True if the popup is shown. 37951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 38051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public boolean isShowingPopup() { 38176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov return getListPopupWindow().isShowing(); 38251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 38351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 38451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov @Override 38551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov protected void onAttachedToWindow() { 38651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov super.onAttachedToWindow(); 38751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov ActivityChooserModel dataModel = mAdapter.getDataModel(); 38851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov if (dataModel != null) { 38976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov dataModel.registerObserver(mModelDataSetOberver); 39051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 39151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mIsAttachedToWindow = true; 39251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 39351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 39451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov @Override 39551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov protected void onDetachedFromWindow() { 39651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov super.onDetachedFromWindow(); 39751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov ActivityChooserModel dataModel = mAdapter.getDataModel(); 39851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov if (dataModel != null) { 39976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov dataModel.unregisterObserver(mModelDataSetOberver); 40051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 4018c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov ViewTreeObserver viewTreeObserver = getViewTreeObserver(); 4028c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov if (viewTreeObserver.isAlive()) { 4038c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener); 4048c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov } 40551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mIsAttachedToWindow = false; 40651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 40751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 40851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov @Override 40951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 410f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov View child = mActivityChooserContent; 411f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov // If the default action is not visible we want to be as tall as the 412f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov // ActionBar so if this widget is used in the latter it will look as 413f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov // a normal action button. 414f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov if (mDefaultActivityButton.getVisibility() != VISIBLE) { 415f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), 416f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov MeasureSpec.EXACTLY); 417f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov } 418f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov measureChild(child, widthMeasureSpec, heightMeasureSpec); 419f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov setMeasuredDimension(child.getMeasuredWidth(), child.getMeasuredHeight()); 42051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 42151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 42251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov @Override 42351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 42476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov mActivityChooserContent.layout(0, 0, right - left, bottom - top); 42576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov if (getListPopupWindow().isShowing()) { 42676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov showPopupUnchecked(mAdapter.getMaxActivityCount()); 42776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov } else { 42876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov dismissPopup(); 42951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 43051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 43151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 43251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public ActivityChooserModel getDataModel() { 43351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return mAdapter.getDataModel(); 43451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 43551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 43651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 43751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Sets a listener to receive a callback when the popup is dismissed. 43851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 43951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @param listener The listener to be notified. 44051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 44151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public void setOnDismissListener(PopupWindow.OnDismissListener listener) { 44251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mOnDismissListener = listener; 44351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 44451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 44551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 44651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Sets the initial count of items shown in the activities popup 44751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * i.e. the items before the popup is expanded. This is an upper 44851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * bound since it is not guaranteed that such number of intent 44951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * handlers exist. 45051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 45151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @param itemCount The initial popup item count. 45251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 45351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public void setInitialActivityCount(int itemCount) { 45451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mInitialActivityCount = itemCount; 45551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 45651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 45751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 45870853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * Sets a content description of the default action button. This 45970853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * resource should be a string taking one formatting argument and 46070853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * will be used for formatting the content description of the button 46170853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * dynamically as the default target changes. For example, a resource 46270853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * pointing to the string "share with %1$s" will result in a content 46370853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * description "share with Bluetooth" for the Bluetooth activity. 46470853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * 46570853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov * @param resourceId The resource id. 46670853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov */ 46770853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov public void setDefaultActionButtonContentDescription(int resourceId) { 46870853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov mDefaultActionButtonContentDescription = resourceId; 46970853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov } 47070853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov 47170853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov /** 47251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Gets the list popup window which is lazily initialized. 47351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * 47451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * @return The popup. 47551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 47651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private ListPopupWindow getListPopupWindow() { 47751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov if (mListPopupWindow == null) { 47851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mListPopupWindow = new ListPopupWindow(getContext()); 47951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mListPopupWindow.setAdapter(mAdapter); 48051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mListPopupWindow.setAnchorView(ActivityChooserView.this); 48151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mListPopupWindow.setModal(true); 48251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mListPopupWindow.setOnItemClickListener(mCallbacks); 48351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mListPopupWindow.setOnDismissListener(mCallbacks); 48451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 48551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return mListPopupWindow; 48651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 48751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 48851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 48951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Updates the buttons state. 49051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 491f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov private void updateAppearance() { 492f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov // Expand overflow button. 493f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov if (mAdapter.getCount() > 0) { 494f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov mExpandActivityOverflowButton.setEnabled(true); 495f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov } else { 496f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov mExpandActivityOverflowButton.setEnabled(false); 497f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov } 498f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov // Default activity button. 49951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov final int activityCount = mAdapter.getActivityCount(); 500f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov final int historySize = mAdapter.getHistorySize(); 501f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov if (activityCount > 0 && historySize > 0) { 502bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov mDefaultActivityButton.setVisibility(VISIBLE); 50351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov ResolveInfo activity = mAdapter.getDefaultActivity(); 50451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov PackageManager packageManager = mContext.getPackageManager(); 505bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov mDefaultActivityButtonImage.setImageDrawable(activity.loadIcon(packageManager)); 50670853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov if (mDefaultActionButtonContentDescription != 0) { 50770853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov CharSequence label = activity.loadLabel(packageManager); 50870853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov String contentDescription = mContext.getString( 50970853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov mDefaultActionButtonContentDescription, label); 51070853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov mDefaultActivityButton.setContentDescription(contentDescription); 51170853772bd119339244a4fc8e020ad78495228beSvetoslav Ganov } 51251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } else { 513f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov mDefaultActivityButton.setVisibility(View.GONE); 514f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov } 515f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov // Activity chooser content. 516f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov if (mDefaultActivityButton.getVisibility() == VISIBLE) { 517f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov mActivityChooserContent.setBackgroundDrawable(mActivityChooserContentBackground); 518f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov } else { 519f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov mActivityChooserContent.setBackgroundDrawable(null); 52051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 52151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 52251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 52351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 52451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Interface implementation to avoid publishing them in the APIs. 52551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 52651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private class Callbacks implements AdapterView.OnItemClickListener, 52776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov View.OnClickListener, View.OnLongClickListener, PopupWindow.OnDismissListener { 52851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 52951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov // AdapterView#OnItemClickListener 53051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 53151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov ActivityChooserViewAdapter adapter = (ActivityChooserViewAdapter) parent.getAdapter(); 53251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov final int itemViewType = adapter.getItemViewType(position); 53351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov switch (itemViewType) { 53451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_FOOTER: { 53551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov showPopupUnchecked(ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED); 53651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } break; 53751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_ACTIVITY: { 53851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov dismissPopup(); 53951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov if (mIsSelectingDefaultActivity) { 54076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov // The item at position zero is the default already. 54176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov if (position > 0) { 54276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov mAdapter.getDataModel().setDefaultActivity(position); 54376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov } 54451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } else { 545efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov // If the default target is not shown in the list, the first 546efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov // item in the model is default action => adjust index 547efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov position = mAdapter.getShowDefaultActivity() ? position : position + 1; 548efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov Intent launchIntent = mAdapter.getDataModel().chooseActivity(position); 5498c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov if (launchIntent != null) { 550314419ccb9daa215c5148f59e5b60c696ef51385Adam Powell launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 5518c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov mContext.startActivity(launchIntent); 5528c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov } 55351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 55451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } break; 55551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov default: 55651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov throw new IllegalArgumentException(); 55751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 55851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 55951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 56051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov // View.OnClickListener 56151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public void onClick(View view) { 562bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov if (view == mDefaultActivityButton) { 56351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov dismissPopup(); 56451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov ResolveInfo defaultActivity = mAdapter.getDefaultActivity(); 56551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov final int index = mAdapter.getDataModel().getActivityIndex(defaultActivity); 56651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov Intent launchIntent = mAdapter.getDataModel().chooseActivity(index); 5678c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov if (launchIntent != null) { 568314419ccb9daa215c5148f59e5b60c696ef51385Adam Powell launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 5698c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov mContext.startActivity(launchIntent); 5708c6c79f0909ceabeb8abe1013648c31c7582b7adSvetoslav Ganov } 57151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } else if (view == mExpandActivityOverflowButton) { 57251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mIsSelectingDefaultActivity = false; 57351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov showPopupUnchecked(mInitialActivityCount); 57451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } else { 57551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov throw new IllegalArgumentException(); 57651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 57751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 57851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 57951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov // OnLongClickListener#onLongClick 58051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov @Override 58151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public boolean onLongClick(View view) { 582bfbbcf5677d4a5f8c8f938e4c8a8f86d3c7d74c2Svetoslav Ganov if (view == mDefaultActivityButton) { 58351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov if (mAdapter.getCount() > 0) { 58451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mIsSelectingDefaultActivity = true; 58551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov showPopupUnchecked(mInitialActivityCount); 58651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 58751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } else { 58851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov throw new IllegalArgumentException(); 58951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 59051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return true; 59151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 59251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 59351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov // PopUpWindow.OnDismissListener#onDismiss 59451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public void onDismiss() { 59551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov notifyOnDismissListener(); 596823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell if (mProvider != null) { 597823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell mProvider.subUiVisibilityChanged(false); 598823f074a73cfc23c40a7b576c71daa096ee9ed6aAdam Powell } 59951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 60051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 60151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private void notifyOnDismissListener() { 60251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov if (mOnDismissListener != null) { 60351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mOnDismissListener.onDismiss(); 60451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 60551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 60651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 60751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 60851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov /** 60951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov * Adapter for backing the list of activities shown in the popup. 61051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov */ 61151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private class ActivityChooserViewAdapter extends BaseAdapter { 61251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 61351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public static final int MAX_ACTIVITY_COUNT_UNLIMITED = Integer.MAX_VALUE; 61451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 61551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public static final int MAX_ACTIVITY_COUNT_DEFAULT = 4; 61651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 61776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov private static final int ITEM_VIEW_TYPE_ACTIVITY = 0; 61851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 61976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov private static final int ITEM_VIEW_TYPE_FOOTER = 1; 62051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 62151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private static final int ITEM_VIEW_TYPE_COUNT = 3; 62251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 62351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private ActivityChooserModel mDataModel; 62451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 62551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov private int mMaxActivityCount = MAX_ACTIVITY_COUNT_DEFAULT; 62651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 62776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov private boolean mShowDefaultActivity; 62851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 629efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov private boolean mHighlightDefaultActivity; 630efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov 63176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov private boolean mShowFooterView; 63251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 63351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public void setDataModel(ActivityChooserModel dataModel) { 63476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov ActivityChooserModel oldDataModel = mAdapter.getDataModel(); 63576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov if (oldDataModel != null && isShown()) { 63676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov oldDataModel.unregisterObserver(mModelDataSetOberver); 63776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov } 63851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mDataModel = dataModel; 63976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov if (dataModel != null && isShown()) { 64076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov dataModel.registerObserver(mModelDataSetOberver); 64151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 64276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov notifyDataSetChanged(); 64351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 64451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 64551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov @Override 64651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public int getItemViewType(int position) { 64776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov if (mShowFooterView && position == getCount() - 1) { 64851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return ITEM_VIEW_TYPE_FOOTER; 64951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } else { 65051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return ITEM_VIEW_TYPE_ACTIVITY; 65151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 65251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 65351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 65451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov @Override 65551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public int getViewTypeCount() { 65651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return ITEM_VIEW_TYPE_COUNT; 65751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 65851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 65951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public int getCount() { 66051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov int count = 0; 66151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov int activityCount = mDataModel.getActivityCount(); 66276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) { 66351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov activityCount--; 66451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 66551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov count = Math.min(activityCount, mMaxActivityCount); 66676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov if (mShowFooterView) { 66751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov count++; 66851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 66951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return count; 67051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 67151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 67251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public Object getItem(int position) { 67351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov final int itemViewType = getItemViewType(position); 67451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov switch (itemViewType) { 67551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov case ITEM_VIEW_TYPE_FOOTER: 67676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov return null; 67751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov case ITEM_VIEW_TYPE_ACTIVITY: 67876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) { 67976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov position++; 68051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 68176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov return mDataModel.getActivity(position); 68251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov default: 68351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov throw new IllegalArgumentException(); 68451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 68551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 68651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 68751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public long getItemId(int position) { 68851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return position; 68951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 69051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 69151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public View getView(int position, View convertView, ViewGroup parent) { 69251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov final int itemViewType = getItemViewType(position); 69351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov switch (itemViewType) { 69451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov case ITEM_VIEW_TYPE_FOOTER: 69576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov if (convertView == null || convertView.getId() != ITEM_VIEW_TYPE_FOOTER) { 69676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov convertView = LayoutInflater.from(getContext()).inflate( 69776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov R.layout.activity_chooser_view_list_item, parent, false); 69876559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov convertView.setId(ITEM_VIEW_TYPE_FOOTER); 69976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov TextView titleView = (TextView) convertView.findViewById(R.id.title); 70076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov titleView.setText(mContext.getString( 70176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov R.string.activity_chooser_view_see_all)); 70276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov } 70376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov return convertView; 70451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov case ITEM_VIEW_TYPE_ACTIVITY: 70551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov if (convertView == null || convertView.getId() != R.id.list_item) { 70651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov convertView = LayoutInflater.from(getContext()).inflate( 70751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov R.layout.activity_chooser_view_list_item, parent, false); 70851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 70951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov PackageManager packageManager = mContext.getPackageManager(); 71051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov // Set the icon 71151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov ImageView iconView = (ImageView) convertView.findViewById(R.id.icon); 71251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov ResolveInfo activity = (ResolveInfo) getItem(position); 713414051b8b1e31b69ca622d68f391245f1989500bSvetoslav Ganov iconView.setImageDrawable(activity.loadIcon(packageManager)); 71451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov // Set the title. 71551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov TextView titleView = (TextView) convertView.findViewById(R.id.title); 71651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov titleView.setText(activity.loadLabel(packageManager)); 71776559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov // Highlight the default. 718efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov if (mShowDefaultActivity && position == 0 && mHighlightDefaultActivity) { 71976559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov convertView.setActivated(true); 72076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov } else { 72176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov convertView.setActivated(false); 72276559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov } 72351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return convertView; 72451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov default: 72551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov throw new IllegalArgumentException(); 72651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 72751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 72851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 72951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public int measureContentWidth() { 73076559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov // The user may have specified some of the target not to be shown but we 73151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov // want to measure all of them since after expansion they should fit. 73251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov final int oldMaxActivityCount = mMaxActivityCount; 73351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mMaxActivityCount = MAX_ACTIVITY_COUNT_UNLIMITED; 73451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 73551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov int contentWidth = 0; 73651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov View itemView = null; 73751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 73851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 73951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 74051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov final int count = getCount(); 74151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 74251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov for (int i = 0; i < count; i++) { 74351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov itemView = getView(i, itemView, null); 74451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov itemView.measure(widthMeasureSpec, heightMeasureSpec); 74551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov contentWidth = Math.max(contentWidth, itemView.getMeasuredWidth()); 74651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 74751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 74851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mMaxActivityCount = oldMaxActivityCount; 74951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 75051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return contentWidth; 75151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 75251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 75351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public void setMaxActivityCount(int maxActivityCount) { 75451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov if (mMaxActivityCount != maxActivityCount) { 75551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov mMaxActivityCount = maxActivityCount; 75651ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov notifyDataSetChanged(); 75751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 75851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 75951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 76051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public ResolveInfo getDefaultActivity() { 76176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov return mDataModel.getDefaultActivity(); 76251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 76351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 76476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov public void setShowFooterView(boolean showFooterView) { 76576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov if (mShowFooterView != showFooterView) { 76676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov mShowFooterView = showFooterView; 76751ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov notifyDataSetChanged(); 76851ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 76951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 77051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 77151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public int getActivityCount() { 77251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return mDataModel.getActivityCount(); 77351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 77451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 775f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov public int getHistorySize() { 776f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov return mDataModel.getHistorySize(); 777f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov } 778f2e754002166b8126e6faf8c494da5835432d572Svetoslav Ganov 77951ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public int getMaxActivityCount() { 78051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return mMaxActivityCount; 78151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 78251ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov 78351ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov public ActivityChooserModel getDataModel() { 78451ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov return mDataModel; 78551ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 78676559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov 787efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov public void setShowDefaultActivity(boolean showDefaultActivity, 788efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov boolean highlightDefaultActivity) { 789efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov if (mShowDefaultActivity != showDefaultActivity 790efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov || mHighlightDefaultActivity != highlightDefaultActivity) { 79176559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov mShowDefaultActivity = showDefaultActivity; 792efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov mHighlightDefaultActivity = highlightDefaultActivity; 79376559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov notifyDataSetChanged(); 79476559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov } 79576559a65ad9d644f10beacf8895ceb217fdd0aebSvetoslav Ganov } 796efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov 797efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov public boolean getShowDefaultActivity() { 798efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov return mShowDefaultActivity; 799efab4e7f59835cb2ea9fdc42cc8fd9ea3771d261Svetoslav Ganov } 80051ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov } 80151ac0e94a83cfccb5105aa14df1077729a5b4cccSvetoslav Ganov} 802