Merge "Adding a callback to ShareActionProvider + make ActivityChooserView popup hide on action bar hide."
This commit is contained in:
committed by
Android (Google) Code Review
commit
151763d3fc
@@ -26694,11 +26694,16 @@ package android.widget {
|
||||
public class ShareActionProvider extends android.view.ActionProvider {
|
||||
ctor public ShareActionProvider(android.content.Context);
|
||||
method public android.view.View onCreateActionView();
|
||||
method public void setOnShareTargetSelectedListener(android.widget.ShareActionProvider.OnShareTargetSelectedListener);
|
||||
method public void setShareHistoryFileName(java.lang.String);
|
||||
method public void setShareIntent(android.content.Intent);
|
||||
field public static final java.lang.String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";
|
||||
}
|
||||
|
||||
public static abstract interface ShareActionProvider.OnShareTargetSelectedListener {
|
||||
method public abstract boolean onShareTargetSelected(android.widget.ShareActionProvider, android.content.Intent);
|
||||
}
|
||||
|
||||
public class SimpleAdapter extends android.widget.BaseAdapter implements android.widget.Filterable {
|
||||
ctor public SimpleAdapter(android.content.Context, java.util.List<? extends java.util.Map<java.lang.String, ?>>, int, java.lang.String[], int[]);
|
||||
method public int getCount();
|
||||
|
||||
@@ -130,6 +130,30 @@ public class ActivityChooserModel extends DataSetObservable {
|
||||
List<HistoricalRecord> historicalRecords);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for choosing an activity.
|
||||
*/
|
||||
public interface OnChooseActivityListener {
|
||||
|
||||
/**
|
||||
* Called when an activity has been chosen. The client can decide whether
|
||||
* an activity can be chosen and if so the caller of
|
||||
* {@link ActivityChooserModel#chooseActivity(int)} will receive and {@link Intent}
|
||||
* for launching it.
|
||||
* <p>
|
||||
* <strong>Note:</strong> Modifying the intent is not permitted and
|
||||
* any changes to the latter will be ignored.
|
||||
* </p>
|
||||
*
|
||||
* @param host The listener's host model.
|
||||
* @param intent The intent for launching the chosen activity.
|
||||
* @return Whether the intent is handled and should not be delivered to clients.
|
||||
*
|
||||
* @see ActivityChooserModel#chooseActivity(int)
|
||||
*/
|
||||
public boolean onChooseActivity(ActivityChooserModel host, Intent intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag for selecting debug mode.
|
||||
*/
|
||||
@@ -286,6 +310,11 @@ public class ActivityChooserModel extends DataSetObservable {
|
||||
*/
|
||||
private final Handler mHandler = new Handler();
|
||||
|
||||
/**
|
||||
* Policy for controlling how the model handles chosen activities.
|
||||
*/
|
||||
private OnChooseActivityListener mActivityChoserModelPolicy;
|
||||
|
||||
/**
|
||||
* Gets the data model backed by the contents of the provided file with historical data.
|
||||
* Note that only one data model is backed by a given file, thus multiple calls with
|
||||
@@ -426,9 +455,11 @@ public class ActivityChooserModel extends DataSetObservable {
|
||||
* the client solely to let additional customization before the start.
|
||||
* </p>
|
||||
*
|
||||
* @return Whether adding succeeded.
|
||||
* @return An {@link Intent} for launching the activity or null if the
|
||||
* policy has consumed the intent.
|
||||
*
|
||||
* @see HistoricalRecord
|
||||
* @see OnChooseActivityListener
|
||||
*/
|
||||
public Intent chooseActivity(int index) {
|
||||
ActivityResolveInfo chosenActivity = mActivites.get(index);
|
||||
@@ -436,16 +467,36 @@ public class ActivityChooserModel extends DataSetObservable {
|
||||
ComponentName chosenName = new ComponentName(
|
||||
chosenActivity.resolveInfo.activityInfo.packageName,
|
||||
chosenActivity.resolveInfo.activityInfo.name);
|
||||
HistoricalRecord historicalRecord = new HistoricalRecord(chosenName,
|
||||
System.currentTimeMillis(), DEFAULT_HISTORICAL_RECORD_WEIGHT);
|
||||
addHisoricalRecord(historicalRecord);
|
||||
|
||||
Intent choiceIntent = new Intent(mIntent);
|
||||
choiceIntent.setComponent(chosenName);
|
||||
|
||||
if (mActivityChoserModelPolicy != null) {
|
||||
// Do not allow the policy to change the intent.
|
||||
Intent choiceIntentCopy = new Intent(choiceIntent);
|
||||
final boolean handled = mActivityChoserModelPolicy.onChooseActivity(this,
|
||||
choiceIntentCopy);
|
||||
if (handled) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
HistoricalRecord historicalRecord = new HistoricalRecord(chosenName,
|
||||
System.currentTimeMillis(), DEFAULT_HISTORICAL_RECORD_WEIGHT);
|
||||
addHisoricalRecord(historicalRecord);
|
||||
|
||||
return choiceIntent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the listener for choosing an activity.
|
||||
*
|
||||
* @param listener The listener.
|
||||
*/
|
||||
public void setOnChooseActivityListener(OnChooseActivityListener listener) {
|
||||
mActivityChoserModelPolicy = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default activity, The default activity is defined as the one
|
||||
* with highest rank i.e. the first one in the list of activities that can
|
||||
|
||||
@@ -29,6 +29,8 @@ import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
|
||||
import android.widget.ActivityChooserModel.ActivityChooserModelClient;
|
||||
|
||||
import com.android.internal.R;
|
||||
@@ -115,6 +117,19 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
|
||||
}
|
||||
};
|
||||
|
||||
private final OnGlobalLayoutListener mOnGlobalLayoutListener = new OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
if (isShowingPopup()) {
|
||||
if (!isShown()) {
|
||||
getListPopupWindow().dismiss();
|
||||
} else {
|
||||
getListPopupWindow().show();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Popup window for showing the activity overflow list.
|
||||
*/
|
||||
@@ -261,6 +276,8 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
|
||||
throw new IllegalStateException("No data model. Did you call #setDataModel?");
|
||||
}
|
||||
|
||||
getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);
|
||||
|
||||
mAdapter.setMaxActivityCount(maxActivityCount);
|
||||
|
||||
final int activityCount = mAdapter.getActivityCount();
|
||||
@@ -292,6 +309,10 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
|
||||
public boolean dismissPopup() {
|
||||
if (isShowingPopup()) {
|
||||
getListPopupWindow().dismiss();
|
||||
ViewTreeObserver viewTreeObserver = getViewTreeObserver();
|
||||
if (viewTreeObserver.isAlive()) {
|
||||
viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -322,6 +343,10 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
|
||||
if (dataModel != null) {
|
||||
dataModel.unregisterObserver(mModelDataSetOberver);
|
||||
}
|
||||
ViewTreeObserver viewTreeObserver = getViewTreeObserver();
|
||||
if (viewTreeObserver.isAlive()) {
|
||||
viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
|
||||
}
|
||||
mIsAttachedToWindow = false;
|
||||
}
|
||||
|
||||
@@ -433,8 +458,10 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
|
||||
}
|
||||
} else {
|
||||
// The first item in the model is default action => adjust index
|
||||
Intent launchIntent = mAdapter.getDataModel().chooseActivity(position + 1);
|
||||
mContext.startActivity(launchIntent);
|
||||
Intent launchIntent = mAdapter.getDataModel().chooseActivity(position + 1);
|
||||
if (launchIntent != null) {
|
||||
mContext.startActivity(launchIntent);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
@@ -449,7 +476,9 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
|
||||
ResolveInfo defaultActivity = mAdapter.getDefaultActivity();
|
||||
final int index = mAdapter.getDataModel().getActivityIndex(defaultActivity);
|
||||
Intent launchIntent = mAdapter.getDataModel().chooseActivity(index);
|
||||
mContext.startActivity(launchIntent);
|
||||
if (launchIntent != null) {
|
||||
mContext.startActivity(launchIntent);
|
||||
}
|
||||
} else if (view == mExpandActivityOverflowButton) {
|
||||
mIsSelectingDefaultActivity = false;
|
||||
showPopupUnchecked(mInitialActivityCount);
|
||||
|
||||
@@ -23,11 +23,11 @@ import android.os.SystemClock;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.SparseArray;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.SoundEffectConstants;
|
||||
import android.view.View;
|
||||
import android.view.ViewDebug;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
|
||||
@@ -278,6 +278,7 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup {
|
||||
*/
|
||||
public boolean performItemClick(View view, int position, long id) {
|
||||
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
|
||||
|
||||
if (mOnItemClickListener != null) {
|
||||
playSoundEffect(SoundEffectConstants.CLICK);
|
||||
mOnItemClickListener.onItemClick(this, view, position, id);
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.view.MenuItem;
|
||||
import android.view.MenuItem.OnMenuItemClickListener;
|
||||
import android.view.SubMenu;
|
||||
import android.view.View;
|
||||
import android.widget.ActivityChooserModel.OnChooseActivityListener;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
@@ -72,6 +73,27 @@ import com.android.internal.R;
|
||||
*/
|
||||
public class ShareActionProvider extends ActionProvider {
|
||||
|
||||
/**
|
||||
* Listener for the event of selecting a share target.
|
||||
*/
|
||||
public interface OnShareTargetSelectedListener {
|
||||
|
||||
/**
|
||||
* Called when a share target has been selected. The client can
|
||||
* decide whether to handle the intent or rely on the default
|
||||
* behavior which is launching it.
|
||||
* <p>
|
||||
* <strong>Note:</strong> Modifying the intent is not permitted and
|
||||
* any changes to the latter will be ignored.
|
||||
* </p>
|
||||
*
|
||||
* @param source The source of the notification.
|
||||
* @param intent The intent for launching the chosen share target.
|
||||
* @return Whether the client has handled the intent.
|
||||
*/
|
||||
public boolean onShareTargetSelected(ShareActionProvider source, Intent intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* The default for the maximal number of activities shown in the sub-menu.
|
||||
*/
|
||||
@@ -103,6 +125,10 @@ public class ShareActionProvider extends ActionProvider {
|
||||
*/
|
||||
private String mShareHistoryFileName = DEFAULT_SHARE_HISTORY_FILE_NAME;
|
||||
|
||||
private OnShareTargetSelectedListener mOnShareTargetSelectedListener;
|
||||
|
||||
private OnChooseActivityListener mOnChooseActivityListener;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
@@ -113,6 +139,21 @@ public class ShareActionProvider extends ActionProvider {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a listener to be notified when a share target has been selected.
|
||||
* The listener can optionally decide to handle the selection and
|
||||
* not rely on the default behavior which is to launch the activity.
|
||||
* <p>
|
||||
* <strong>Note:</strong> If you choose the backing share history file
|
||||
* you will still be notified in this callback.
|
||||
* </p>
|
||||
* @param listener The listener.
|
||||
*/
|
||||
public void setOnShareTargetSelectedListener(OnShareTargetSelectedListener listener) {
|
||||
mOnShareTargetSelectedListener = listener;
|
||||
setActivityChooserPolicyIfNeeded();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@@ -192,6 +233,7 @@ public class ShareActionProvider extends ActionProvider {
|
||||
*/
|
||||
public void setShareHistoryFileName(String shareHistoryFile) {
|
||||
mShareHistoryFileName = shareHistoryFile;
|
||||
setActivityChooserPolicyIfNeeded();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,8 +271,39 @@ public class ShareActionProvider extends ActionProvider {
|
||||
mShareHistoryFileName);
|
||||
final int itemId = item.getItemId();
|
||||
Intent launchIntent = dataModel.chooseActivity(itemId);
|
||||
mContext.startActivity(launchIntent);
|
||||
if (launchIntent != null) {
|
||||
mContext.startActivity(launchIntent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the activity chooser policy of the model backed by the current
|
||||
* share history file if needed which is if there is a registered callback.
|
||||
*/
|
||||
private void setActivityChooserPolicyIfNeeded() {
|
||||
if (mOnShareTargetSelectedListener == null) {
|
||||
return;
|
||||
}
|
||||
if (mOnChooseActivityListener == null) {
|
||||
mOnChooseActivityListener = new ShareAcitivityChooserModelPolicy();
|
||||
}
|
||||
ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
|
||||
dataModel.setOnChooseActivityListener(mOnChooseActivityListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Policy that delegates to the {@link OnShareTargetSelectedListener}, if such.
|
||||
*/
|
||||
private class ShareAcitivityChooserModelPolicy implements OnChooseActivityListener {
|
||||
@Override
|
||||
public boolean onChooseActivity(ActivityChooserModel host, Intent intent) {
|
||||
if (mOnShareTargetSelectedListener != null) {
|
||||
return mOnShareTargetSelectedListener.onShareTargetSelected(
|
||||
ShareActionProvider.this, intent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user