mirror of https://github.com/tasks/tasks
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1204 lines
45 KiB
Java
1204 lines
45 KiB
Java
package com.actionbarsherlock.internal;
|
|
|
|
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
|
import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import org.xmlpull.v1.XmlPullParser;
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
import android.content.pm.ActivityInfo;
|
|
import android.content.res.AssetManager;
|
|
import android.content.res.Configuration;
|
|
import android.content.res.Resources;
|
|
import android.content.res.TypedArray;
|
|
import android.content.res.XmlResourceParser;
|
|
import android.os.Bundle;
|
|
import android.util.AndroidRuntimeException;
|
|
import android.util.Log;
|
|
import android.util.TypedValue;
|
|
import android.view.ContextThemeWrapper;
|
|
import android.view.KeyCharacterMap;
|
|
import android.view.KeyEvent;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.view.ViewStub;
|
|
import android.view.Window;
|
|
import android.view.accessibility.AccessibilityEvent;
|
|
import android.view.animation.Animation;
|
|
import android.view.animation.AnimationUtils;
|
|
import android.widget.FrameLayout;
|
|
import android.widget.TextView;
|
|
import com.actionbarsherlock.ActionBarSherlock;
|
|
import com.actionbarsherlock.R;
|
|
import com.actionbarsherlock.app.ActionBar;
|
|
import com.actionbarsherlock.internal.app.ActionBarImpl;
|
|
import com.actionbarsherlock.internal.view.StandaloneActionMode;
|
|
import com.actionbarsherlock.internal.view.menu.ActionMenuPresenter;
|
|
import com.actionbarsherlock.internal.view.menu.MenuBuilder;
|
|
import com.actionbarsherlock.internal.view.menu.MenuItemImpl;
|
|
import com.actionbarsherlock.internal.view.menu.MenuPresenter;
|
|
import com.actionbarsherlock.internal.widget.ActionBarContainer;
|
|
import com.actionbarsherlock.internal.widget.ActionBarContextView;
|
|
import com.actionbarsherlock.internal.widget.ActionBarView;
|
|
import com.actionbarsherlock.internal.widget.IcsProgressBar;
|
|
import com.actionbarsherlock.view.ActionMode;
|
|
import com.actionbarsherlock.view.Menu;
|
|
import com.actionbarsherlock.view.MenuItem;
|
|
|
|
@ActionBarSherlock.Implementation(api = 7)
|
|
public class ActionBarSherlockCompat extends ActionBarSherlock implements MenuBuilder.Callback, com.actionbarsherlock.view.Window.Callback, MenuPresenter.Callback, android.view.MenuItem.OnMenuItemClickListener {
|
|
/** Window features which are enabled by default. */
|
|
protected static final int DEFAULT_FEATURES = 0;
|
|
|
|
static private final String PANELS_TAG = "sherlock:Panels";
|
|
|
|
public ActionBarSherlockCompat(Activity activity, int flags) {
|
|
super(activity, flags);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Properties
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
/** Whether or not the device has a dedicated menu key button. */
|
|
private boolean mReserveOverflow;
|
|
/** Lazy-load indicator for {@link #mReserveOverflow}. */
|
|
private boolean mReserveOverflowSet = false;
|
|
|
|
/** Current menu instance for managing action items. */
|
|
private MenuBuilder mMenu;
|
|
/** Map between native options items and sherlock items. */
|
|
protected HashMap<android.view.MenuItem, MenuItemImpl> mNativeItemMap;
|
|
|
|
/** Parent view of the window decoration (action bar, mode, etc.). */
|
|
private ViewGroup mDecor;
|
|
/** Parent view of the activity content. */
|
|
private ViewGroup mContentParent;
|
|
|
|
/** Whether or not the title is stable and can be displayed. */
|
|
private boolean mIsTitleReady = false;
|
|
/** Whether or not the parent activity has been destroyed. */
|
|
private boolean mIsDestroyed = false;
|
|
|
|
/* Emulate PanelFeatureState */
|
|
private boolean mClosingActionMenu;
|
|
private boolean mMenuIsPrepared;
|
|
private boolean mMenuRefreshContent;
|
|
private Bundle mMenuFrozenActionViewState;
|
|
|
|
/** Implementation which backs the action bar interface API. */
|
|
private ActionBarImpl aActionBar;
|
|
/** Main action bar view which displays the core content. */
|
|
private ActionBarView wActionBar;
|
|
/** Relevant window and action bar features flags. */
|
|
private int mFeatures = DEFAULT_FEATURES;
|
|
/** Relevant user interface option flags. */
|
|
private int mUiOptions = 0;
|
|
|
|
/** Decor indeterminate progress indicator. */
|
|
private IcsProgressBar mCircularProgressBar;
|
|
/** Decor progress indicator. */
|
|
private IcsProgressBar mHorizontalProgressBar;
|
|
|
|
/** Current displayed context action bar, if any. */
|
|
private ActionMode mActionMode;
|
|
/** Parent view in which the context action bar is displayed. */
|
|
private ActionBarContextView mActionModeView;
|
|
|
|
/** Title view used with dialogs. */
|
|
private TextView mTitleView;
|
|
/** Current activity title. */
|
|
private CharSequence mTitle = null;
|
|
/** Whether or not this "activity" is floating (i.e., a dialog) */
|
|
private boolean mIsFloating;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Instance methods
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
@Override
|
|
public ActionBar getActionBar() {
|
|
if (DEBUG) Log.d(TAG, "[getActionBar]");
|
|
|
|
initActionBar();
|
|
return aActionBar;
|
|
}
|
|
|
|
private void initActionBar() {
|
|
if (DEBUG) Log.d(TAG, "[initActionBar]");
|
|
|
|
// Initializing the window decor can change window feature flags.
|
|
// Make sure that we have the correct set before performing the test below.
|
|
if (mDecor == null) {
|
|
installDecor();
|
|
}
|
|
|
|
if ((aActionBar != null) || !hasFeature(Window.FEATURE_ACTION_BAR) || hasFeature(Window.FEATURE_NO_TITLE) || mActivity.isChild()) {
|
|
return;
|
|
}
|
|
|
|
aActionBar = new ActionBarImpl(mActivity, mFeatures);
|
|
|
|
if (!mIsDelegate) {
|
|
//We may never get another chance to set the title
|
|
wActionBar.setWindowTitle(mActivity.getTitle());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected Context getThemedContext() {
|
|
return aActionBar.getThemedContext();
|
|
}
|
|
|
|
@Override
|
|
public void setTitle(CharSequence title) {
|
|
if (DEBUG) Log.d(TAG, "[setTitle] title: " + title);
|
|
|
|
dispatchTitleChanged(title, 0);
|
|
}
|
|
|
|
@Override
|
|
public ActionMode startActionMode(ActionMode.Callback callback) {
|
|
if (DEBUG) Log.d(TAG, "[startActionMode] callback: " + callback);
|
|
|
|
if (mActionMode != null) {
|
|
mActionMode.finish();
|
|
}
|
|
|
|
final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback);
|
|
ActionMode mode = null;
|
|
|
|
//Emulate Activity's onWindowStartingActionMode:
|
|
initActionBar();
|
|
if (aActionBar != null) {
|
|
mode = aActionBar.startActionMode(wrappedCallback);
|
|
}
|
|
|
|
if (mode != null) {
|
|
mActionMode = mode;
|
|
} else {
|
|
if (mActionModeView == null) {
|
|
ViewStub stub = (ViewStub)mDecor.findViewById(R.id.abs__action_mode_bar_stub);
|
|
if (stub != null) {
|
|
mActionModeView = (ActionBarContextView)stub.inflate();
|
|
}
|
|
}
|
|
if (mActionModeView != null) {
|
|
mActionModeView.killMode();
|
|
mode = new StandaloneActionMode(mActivity, mActionModeView, wrappedCallback, true);
|
|
if (callback.onCreateActionMode(mode, mode.getMenu())) {
|
|
mode.invalidate();
|
|
mActionModeView.initForMode(mode);
|
|
mActionModeView.setVisibility(View.VISIBLE);
|
|
mActionMode = mode;
|
|
mActionModeView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
|
|
} else {
|
|
mActionMode = null;
|
|
}
|
|
}
|
|
}
|
|
if (mActionMode != null && mActivity instanceof OnActionModeStartedListener) {
|
|
((OnActionModeStartedListener)mActivity).onActionModeStarted(mActionMode);
|
|
}
|
|
return mActionMode;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Lifecycle and interaction callbacks for delegation
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
@Override
|
|
public void dispatchConfigurationChanged(Configuration newConfig) {
|
|
if (DEBUG) Log.d(TAG, "[dispatchConfigurationChanged] newConfig: " + newConfig);
|
|
|
|
if (aActionBar != null) {
|
|
aActionBar.onConfigurationChanged(newConfig);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void dispatchPostResume() {
|
|
if (DEBUG) Log.d(TAG, "[dispatchPostResume]");
|
|
|
|
if (aActionBar != null) {
|
|
aActionBar.setShowHideAnimationEnabled(true);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void dispatchPause() {
|
|
if (DEBUG) Log.d(TAG, "[dispatchPause]");
|
|
|
|
if (wActionBar != null && wActionBar.isOverflowMenuShowing()) {
|
|
wActionBar.hideOverflowMenu();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void dispatchStop() {
|
|
if (DEBUG) Log.d(TAG, "[dispatchStop]");
|
|
|
|
if (aActionBar != null) {
|
|
aActionBar.setShowHideAnimationEnabled(false);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void dispatchInvalidateOptionsMenu() {
|
|
if (DEBUG) Log.d(TAG, "[dispatchInvalidateOptionsMenu]");
|
|
|
|
Bundle savedActionViewStates = null;
|
|
if (mMenu != null) {
|
|
savedActionViewStates = new Bundle();
|
|
mMenu.saveActionViewStates(savedActionViewStates);
|
|
if (savedActionViewStates.size() > 0) {
|
|
mMenuFrozenActionViewState = savedActionViewStates;
|
|
}
|
|
// This will be started again when the panel is prepared.
|
|
mMenu.stopDispatchingItemsChanged();
|
|
mMenu.clear();
|
|
}
|
|
mMenuRefreshContent = true;
|
|
|
|
// Prepare the options panel if we have an action bar
|
|
if (wActionBar != null) {
|
|
mMenuIsPrepared = false;
|
|
preparePanel();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean dispatchOpenOptionsMenu() {
|
|
if (DEBUG) Log.d(TAG, "[dispatchOpenOptionsMenu]");
|
|
|
|
if (!isReservingOverflow()) {
|
|
return false;
|
|
}
|
|
|
|
return wActionBar.showOverflowMenu();
|
|
}
|
|
|
|
@Override
|
|
public boolean dispatchCloseOptionsMenu() {
|
|
if (DEBUG) Log.d(TAG, "[dispatchCloseOptionsMenu]");
|
|
|
|
if (!isReservingOverflow()) {
|
|
return false;
|
|
}
|
|
|
|
if (wActionBar != null) {
|
|
return wActionBar.hideOverflowMenu();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void dispatchPostCreate(Bundle savedInstanceState) {
|
|
if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]");
|
|
|
|
if (mIsDelegate) {
|
|
mIsTitleReady = true;
|
|
}
|
|
|
|
if (mDecor == null) {
|
|
initActionBar();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean dispatchCreateOptionsMenu(android.view.Menu menu) {
|
|
if (DEBUG) {
|
|
Log.d(TAG, "[dispatchCreateOptionsMenu] android.view.Menu: " + menu);
|
|
Log.d(TAG, "[dispatchCreateOptionsMenu] returning true");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean dispatchPrepareOptionsMenu(android.view.Menu menu) {
|
|
if (DEBUG) Log.d(TAG, "[dispatchPrepareOptionsMenu] android.view.Menu: " + menu);
|
|
|
|
if (mActionMode != null) {
|
|
return false;
|
|
}
|
|
|
|
mMenuIsPrepared = false;
|
|
if (!preparePanel()) {
|
|
return false;
|
|
}
|
|
|
|
if (isReservingOverflow()) {
|
|
return false;
|
|
}
|
|
|
|
if (mNativeItemMap == null) {
|
|
mNativeItemMap = new HashMap<android.view.MenuItem, MenuItemImpl>();
|
|
} else {
|
|
mNativeItemMap.clear();
|
|
}
|
|
|
|
if (mMenu == null) {
|
|
return false;
|
|
}
|
|
|
|
boolean result = mMenu.bindNativeOverflow(menu, this, mNativeItemMap);
|
|
if (DEBUG) Log.d(TAG, "[dispatchPrepareOptionsMenu] returning " + result);
|
|
return result;
|
|
}
|
|
|
|
@Override
|
|
public boolean dispatchOptionsItemSelected(android.view.MenuItem item) {
|
|
throw new IllegalStateException("Native callback invoked. Create a test case and report!");
|
|
}
|
|
|
|
@Override
|
|
public boolean dispatchMenuOpened(int featureId, android.view.Menu menu) {
|
|
if (DEBUG) Log.d(TAG, "[dispatchMenuOpened] featureId: " + featureId + ", menu: " + menu);
|
|
|
|
if (featureId == Window.FEATURE_ACTION_BAR || featureId == Window.FEATURE_OPTIONS_PANEL) {
|
|
if (aActionBar != null) {
|
|
aActionBar.dispatchMenuVisibilityChanged(true);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void dispatchPanelClosed(int featureId, android.view.Menu menu){
|
|
if (DEBUG) Log.d(TAG, "[dispatchPanelClosed] featureId: " + featureId + ", menu: " + menu);
|
|
|
|
if (featureId == Window.FEATURE_ACTION_BAR || featureId == Window.FEATURE_OPTIONS_PANEL) {
|
|
if (aActionBar != null) {
|
|
aActionBar.dispatchMenuVisibilityChanged(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void dispatchTitleChanged(CharSequence title, int color) {
|
|
if (DEBUG) Log.d(TAG, "[dispatchTitleChanged] title: " + title + ", color: " + color);
|
|
|
|
if (!mIsDelegate || mIsTitleReady) {
|
|
if (mTitleView != null) {
|
|
mTitleView.setText(title);
|
|
} else if (wActionBar != null) {
|
|
wActionBar.setWindowTitle(title);
|
|
}
|
|
}
|
|
|
|
mTitle = title;
|
|
}
|
|
|
|
@Override
|
|
public boolean dispatchKeyEvent(KeyEvent event) {
|
|
if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] event: " + event);
|
|
|
|
final int keyCode = event.getKeyCode();
|
|
|
|
// Not handled by the view hierarchy, does the action bar want it
|
|
// to cancel out of something special?
|
|
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
|
final int action = event.getAction();
|
|
// Back cancels action modes first.
|
|
if (mActionMode != null) {
|
|
if (action == KeyEvent.ACTION_UP) {
|
|
mActionMode.finish();
|
|
}
|
|
if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true");
|
|
return true;
|
|
}
|
|
|
|
// Next collapse any expanded action views.
|
|
if (wActionBar != null && wActionBar.hasExpandedActionView()) {
|
|
if (action == KeyEvent.ACTION_UP) {
|
|
wActionBar.collapseActionView();
|
|
}
|
|
if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false");
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void dispatchDestroy() {
|
|
mIsDestroyed = true;
|
|
}
|
|
|
|
@Override
|
|
public void dispatchSaveInstanceState(Bundle outState) {
|
|
if (mMenu != null) {
|
|
mMenuFrozenActionViewState = new Bundle();
|
|
mMenu.saveActionViewStates(mMenuFrozenActionViewState);
|
|
}
|
|
outState.putParcelable(PANELS_TAG, mMenuFrozenActionViewState);
|
|
}
|
|
|
|
@Override
|
|
public void dispatchRestoreInstanceState(Bundle savedInstanceState) {
|
|
mMenuFrozenActionViewState = savedInstanceState.getParcelable(PANELS_TAG);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Menu callback lifecycle and creation
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
private boolean preparePanel() {
|
|
// Already prepared (isPrepared will be reset to false later)
|
|
if (mMenuIsPrepared) {
|
|
return true;
|
|
}
|
|
|
|
// Init the panel state's menu--return false if init failed
|
|
if (mMenu == null || mMenuRefreshContent) {
|
|
if (mMenu == null) {
|
|
if (!initializePanelMenu() || (mMenu == null)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (wActionBar != null) {
|
|
wActionBar.setMenu(mMenu, this);
|
|
}
|
|
|
|
// Call callback, and return if it doesn't want to display menu.
|
|
|
|
// Creating the panel menu will involve a lot of manipulation;
|
|
// don't dispatch change events to presenters until we're done.
|
|
mMenu.stopDispatchingItemsChanged();
|
|
if (!callbackCreateOptionsMenu(mMenu)) {
|
|
// Ditch the menu created above
|
|
mMenu = null;
|
|
|
|
if (wActionBar != null) {
|
|
// Don't show it in the action bar either
|
|
wActionBar.setMenu(null, this);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
mMenuRefreshContent = false;
|
|
}
|
|
|
|
// Callback and return if the callback does not want to show the menu
|
|
|
|
// Preparing the panel menu can involve a lot of manipulation;
|
|
// don't dispatch change events to presenters until we're done.
|
|
mMenu.stopDispatchingItemsChanged();
|
|
|
|
// Restore action view state before we prepare. This gives apps
|
|
// an opportunity to override frozen/restored state in onPrepare.
|
|
if (mMenuFrozenActionViewState != null) {
|
|
mMenu.restoreActionViewStates(mMenuFrozenActionViewState);
|
|
mMenuFrozenActionViewState = null;
|
|
}
|
|
|
|
if (!callbackPrepareOptionsMenu(mMenu)) {
|
|
if (wActionBar != null) {
|
|
// The app didn't want to show the menu for now but it still exists.
|
|
// Clear it out of the action bar.
|
|
wActionBar.setMenu(null, this);
|
|
}
|
|
mMenu.startDispatchingItemsChanged();
|
|
return false;
|
|
}
|
|
|
|
// Set the proper keymap
|
|
KeyCharacterMap kmap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
|
|
mMenu.setQwertyMode(kmap.getKeyboardType() != KeyCharacterMap.NUMERIC);
|
|
mMenu.startDispatchingItemsChanged();
|
|
|
|
// Set other state
|
|
mMenuIsPrepared = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
|
|
return callbackOptionsItemSelected(item);
|
|
}
|
|
|
|
public void onMenuModeChange(MenuBuilder menu) {
|
|
reopenMenu(true);
|
|
}
|
|
|
|
private void reopenMenu(boolean toggleMenuMode) {
|
|
if (wActionBar != null && wActionBar.isOverflowReserved()) {
|
|
if (!wActionBar.isOverflowMenuShowing() || !toggleMenuMode) {
|
|
if (wActionBar.getVisibility() == View.VISIBLE) {
|
|
if (callbackPrepareOptionsMenu(mMenu)) {
|
|
wActionBar.showOverflowMenu();
|
|
}
|
|
}
|
|
} else {
|
|
wActionBar.hideOverflowMenu();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
private boolean initializePanelMenu() {
|
|
Context context = mActivity;//getContext();
|
|
|
|
// If we have an action bar, initialize the menu with a context themed for it.
|
|
if (wActionBar != null) {
|
|
TypedValue outValue = new TypedValue();
|
|
Resources.Theme currentTheme = context.getTheme();
|
|
currentTheme.resolveAttribute(R.attr.actionBarWidgetTheme,
|
|
outValue, true);
|
|
final int targetThemeRes = outValue.resourceId;
|
|
|
|
if (targetThemeRes != 0 /*&& context.getThemeResId() != targetThemeRes*/) {
|
|
context = new ContextThemeWrapper(context, targetThemeRes);
|
|
}
|
|
}
|
|
|
|
mMenu = new MenuBuilder(context);
|
|
mMenu.setCallback(this);
|
|
|
|
return true;
|
|
}
|
|
|
|
void checkCloseActionMenu(Menu menu) {
|
|
if (mClosingActionMenu) {
|
|
return;
|
|
}
|
|
|
|
mClosingActionMenu = true;
|
|
wActionBar.dismissPopupMenus();
|
|
//Callback cb = getCallback();
|
|
//if (cb != null && !isDestroyed()) {
|
|
// cb.onPanelClosed(FEATURE_ACTION_BAR, menu);
|
|
//}
|
|
mClosingActionMenu = false;
|
|
}
|
|
|
|
@Override
|
|
public boolean onOpenSubMenu(MenuBuilder subMenu) {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
|
|
checkCloseActionMenu(menu);
|
|
}
|
|
|
|
@Override
|
|
public boolean onMenuItemClick(android.view.MenuItem item) {
|
|
if (DEBUG) Log.d(TAG, "[mNativeItemListener.onMenuItemClick] item: " + item);
|
|
|
|
final MenuItemImpl sherlockItem = mNativeItemMap.get(item);
|
|
if (sherlockItem != null) {
|
|
sherlockItem.invoke();
|
|
} else {
|
|
Log.e(TAG, "Options item \"" + item + "\" not found in mapping");
|
|
}
|
|
|
|
return true; //Do not allow continuation of native handling
|
|
}
|
|
|
|
@Override
|
|
public boolean onMenuItemSelected(int featureId, MenuItem item) {
|
|
return callbackOptionsItemSelected(item);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Progress bar interaction and internal handling
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
@Override
|
|
public void setProgressBarVisibility(boolean visible) {
|
|
if (DEBUG) Log.d(TAG, "[setProgressBarVisibility] visible: " + visible);
|
|
|
|
setFeatureInt(Window.FEATURE_PROGRESS, visible ? Window.PROGRESS_VISIBILITY_ON :
|
|
Window.PROGRESS_VISIBILITY_OFF);
|
|
}
|
|
|
|
@Override
|
|
public void setProgressBarIndeterminateVisibility(boolean visible) {
|
|
if (DEBUG) Log.d(TAG, "[setProgressBarIndeterminateVisibility] visible: " + visible);
|
|
|
|
setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS,
|
|
visible ? Window.PROGRESS_VISIBILITY_ON : Window.PROGRESS_VISIBILITY_OFF);
|
|
}
|
|
|
|
@Override
|
|
public void setProgressBarIndeterminate(boolean indeterminate) {
|
|
if (DEBUG) Log.d(TAG, "[setProgressBarIndeterminate] indeterminate: " + indeterminate);
|
|
|
|
setFeatureInt(Window.FEATURE_PROGRESS,
|
|
indeterminate ? Window.PROGRESS_INDETERMINATE_ON : Window.PROGRESS_INDETERMINATE_OFF);
|
|
}
|
|
|
|
@Override
|
|
public void setProgress(int progress) {
|
|
if (DEBUG) Log.d(TAG, "[setProgress] progress: " + progress);
|
|
|
|
setFeatureInt(Window.FEATURE_PROGRESS, progress + Window.PROGRESS_START);
|
|
}
|
|
|
|
@Override
|
|
public void setSecondaryProgress(int secondaryProgress) {
|
|
if (DEBUG) Log.d(TAG, "[setSecondaryProgress] secondaryProgress: " + secondaryProgress);
|
|
|
|
setFeatureInt(Window.FEATURE_PROGRESS,
|
|
secondaryProgress + Window.PROGRESS_SECONDARY_START);
|
|
}
|
|
|
|
private void setFeatureInt(int featureId, int value) {
|
|
updateInt(featureId, value, false);
|
|
}
|
|
|
|
private void updateInt(int featureId, int value, boolean fromResume) {
|
|
// Do nothing if the decor is not yet installed... an update will
|
|
// need to be forced when we eventually become active.
|
|
if (mContentParent == null) {
|
|
return;
|
|
}
|
|
|
|
final int featureMask = 1 << featureId;
|
|
|
|
if ((getFeatures() & featureMask) == 0 && !fromResume) {
|
|
return;
|
|
}
|
|
|
|
onIntChanged(featureId, value);
|
|
}
|
|
|
|
private void onIntChanged(int featureId, int value) {
|
|
if (featureId == Window.FEATURE_PROGRESS || featureId == Window.FEATURE_INDETERMINATE_PROGRESS) {
|
|
updateProgressBars(value);
|
|
}
|
|
}
|
|
|
|
private void updateProgressBars(int value) {
|
|
IcsProgressBar circularProgressBar = getCircularProgressBar(true);
|
|
IcsProgressBar horizontalProgressBar = getHorizontalProgressBar(true);
|
|
|
|
final int features = mFeatures;//getLocalFeatures();
|
|
if (value == Window.PROGRESS_VISIBILITY_ON) {
|
|
if ((features & (1 << Window.FEATURE_PROGRESS)) != 0) {
|
|
int level = horizontalProgressBar.getProgress();
|
|
int visibility = (horizontalProgressBar.isIndeterminate() || level < 10000) ?
|
|
View.VISIBLE : View.INVISIBLE;
|
|
horizontalProgressBar.setVisibility(visibility);
|
|
}
|
|
if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0) {
|
|
circularProgressBar.setVisibility(View.VISIBLE);
|
|
}
|
|
} else if (value == Window.PROGRESS_VISIBILITY_OFF) {
|
|
if ((features & (1 << Window.FEATURE_PROGRESS)) != 0) {
|
|
horizontalProgressBar.setVisibility(View.GONE);
|
|
}
|
|
if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0) {
|
|
circularProgressBar.setVisibility(View.GONE);
|
|
}
|
|
} else if (value == Window.PROGRESS_INDETERMINATE_ON) {
|
|
horizontalProgressBar.setIndeterminate(true);
|
|
} else if (value == Window.PROGRESS_INDETERMINATE_OFF) {
|
|
horizontalProgressBar.setIndeterminate(false);
|
|
} else if (Window.PROGRESS_START <= value && value <= Window.PROGRESS_END) {
|
|
// We want to set the progress value before testing for visibility
|
|
// so that when the progress bar becomes visible again, it has the
|
|
// correct level.
|
|
horizontalProgressBar.setProgress(value - Window.PROGRESS_START);
|
|
|
|
if (value < Window.PROGRESS_END) {
|
|
showProgressBars(horizontalProgressBar, circularProgressBar);
|
|
} else {
|
|
hideProgressBars(horizontalProgressBar, circularProgressBar);
|
|
}
|
|
} else if (Window.PROGRESS_SECONDARY_START <= value && value <= Window.PROGRESS_SECONDARY_END) {
|
|
horizontalProgressBar.setSecondaryProgress(value - Window.PROGRESS_SECONDARY_START);
|
|
|
|
showProgressBars(horizontalProgressBar, circularProgressBar);
|
|
}
|
|
}
|
|
|
|
private void showProgressBars(IcsProgressBar horizontalProgressBar, IcsProgressBar spinnyProgressBar) {
|
|
final int features = mFeatures;//getLocalFeatures();
|
|
if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0 &&
|
|
spinnyProgressBar.getVisibility() == View.INVISIBLE) {
|
|
spinnyProgressBar.setVisibility(View.VISIBLE);
|
|
}
|
|
// Only show the progress bars if the primary progress is not complete
|
|
if ((features & (1 << Window.FEATURE_PROGRESS)) != 0 &&
|
|
horizontalProgressBar.getProgress() < 10000) {
|
|
horizontalProgressBar.setVisibility(View.VISIBLE);
|
|
}
|
|
}
|
|
|
|
private void hideProgressBars(IcsProgressBar horizontalProgressBar, IcsProgressBar spinnyProgressBar) {
|
|
final int features = mFeatures;//getLocalFeatures();
|
|
Animation anim = AnimationUtils.loadAnimation(mActivity, android.R.anim.fade_out);
|
|
anim.setDuration(1000);
|
|
if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0 &&
|
|
spinnyProgressBar.getVisibility() == View.VISIBLE) {
|
|
spinnyProgressBar.startAnimation(anim);
|
|
spinnyProgressBar.setVisibility(View.INVISIBLE);
|
|
}
|
|
if ((features & (1 << Window.FEATURE_PROGRESS)) != 0 &&
|
|
horizontalProgressBar.getVisibility() == View.VISIBLE) {
|
|
horizontalProgressBar.startAnimation(anim);
|
|
horizontalProgressBar.setVisibility(View.INVISIBLE);
|
|
}
|
|
}
|
|
|
|
private IcsProgressBar getCircularProgressBar(boolean shouldInstallDecor) {
|
|
if (mCircularProgressBar != null) {
|
|
return mCircularProgressBar;
|
|
}
|
|
if (mContentParent == null && shouldInstallDecor) {
|
|
installDecor();
|
|
}
|
|
mCircularProgressBar = (IcsProgressBar)mDecor.findViewById(R.id.abs__progress_circular);
|
|
if (mCircularProgressBar != null) {
|
|
mCircularProgressBar.setVisibility(View.INVISIBLE);
|
|
}
|
|
return mCircularProgressBar;
|
|
}
|
|
|
|
private IcsProgressBar getHorizontalProgressBar(boolean shouldInstallDecor) {
|
|
if (mHorizontalProgressBar != null) {
|
|
return mHorizontalProgressBar;
|
|
}
|
|
if (mContentParent == null && shouldInstallDecor) {
|
|
installDecor();
|
|
}
|
|
mHorizontalProgressBar = (IcsProgressBar)mDecor.findViewById(R.id.abs__progress_horizontal);
|
|
if (mHorizontalProgressBar != null) {
|
|
mHorizontalProgressBar.setVisibility(View.INVISIBLE);
|
|
}
|
|
return mHorizontalProgressBar;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Feature management and content interaction and creation
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
private int getFeatures() {
|
|
if (DEBUG) Log.d(TAG, "[getFeatures] returning " + mFeatures);
|
|
|
|
return mFeatures;
|
|
}
|
|
|
|
@Override
|
|
public boolean hasFeature(int featureId) {
|
|
if (DEBUG) Log.d(TAG, "[hasFeature] featureId: " + featureId);
|
|
|
|
boolean result = (mFeatures & (1 << featureId)) != 0;
|
|
if (DEBUG) Log.d(TAG, "[hasFeature] returning " + result);
|
|
return result;
|
|
}
|
|
|
|
@Override
|
|
public boolean requestFeature(int featureId) {
|
|
if (DEBUG) Log.d(TAG, "[requestFeature] featureId: " + featureId);
|
|
|
|
if (mContentParent != null) {
|
|
throw new AndroidRuntimeException("requestFeature() must be called before adding content");
|
|
}
|
|
|
|
switch (featureId) {
|
|
case Window.FEATURE_ACTION_BAR:
|
|
case Window.FEATURE_ACTION_BAR_OVERLAY:
|
|
case Window.FEATURE_ACTION_MODE_OVERLAY:
|
|
case Window.FEATURE_INDETERMINATE_PROGRESS:
|
|
case Window.FEATURE_NO_TITLE:
|
|
case Window.FEATURE_PROGRESS:
|
|
mFeatures |= (1 << featureId);
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setUiOptions(int uiOptions) {
|
|
if (DEBUG) Log.d(TAG, "[setUiOptions] uiOptions: " + uiOptions);
|
|
|
|
mUiOptions = uiOptions;
|
|
}
|
|
|
|
@Override
|
|
public void setUiOptions(int uiOptions, int mask) {
|
|
if (DEBUG) Log.d(TAG, "[setUiOptions] uiOptions: " + uiOptions + ", mask: " + mask);
|
|
|
|
mUiOptions = (mUiOptions & ~mask) | (uiOptions & mask);
|
|
}
|
|
|
|
@Override
|
|
public void setContentView(int layoutResId) {
|
|
if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + layoutResId);
|
|
|
|
if (mContentParent == null) {
|
|
installDecor();
|
|
} else {
|
|
mContentParent.removeAllViews();
|
|
}
|
|
mActivity.getLayoutInflater().inflate(layoutResId, mContentParent);
|
|
|
|
android.view.Window.Callback callback = mActivity.getWindow().getCallback();
|
|
if (callback != null) {
|
|
callback.onContentChanged();
|
|
}
|
|
|
|
initActionBar();
|
|
}
|
|
|
|
@Override
|
|
public void setContentView(View view, ViewGroup.LayoutParams params) {
|
|
if (DEBUG) Log.d(TAG, "[setContentView] view: " + view + ", params: " + params);
|
|
|
|
if (mContentParent == null) {
|
|
installDecor();
|
|
} else {
|
|
mContentParent.removeAllViews();
|
|
}
|
|
mContentParent.addView(view, params);
|
|
|
|
android.view.Window.Callback callback = mActivity.getWindow().getCallback();
|
|
if (callback != null) {
|
|
callback.onContentChanged();
|
|
}
|
|
|
|
initActionBar();
|
|
}
|
|
|
|
@Override
|
|
public void addContentView(View view, ViewGroup.LayoutParams params) {
|
|
if (DEBUG) Log.d(TAG, "[addContentView] view: " + view + ", params: " + params);
|
|
|
|
if (mContentParent == null) {
|
|
installDecor();
|
|
}
|
|
mContentParent.addView(view, params);
|
|
|
|
initActionBar();
|
|
}
|
|
|
|
private void installDecor() {
|
|
if (DEBUG) Log.d(TAG, "[installDecor]");
|
|
|
|
if (mDecor == null) {
|
|
mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content);
|
|
}
|
|
if (mContentParent == null) {
|
|
//Since we are not operating at the window level we need to take
|
|
//into account the fact that the true decor may have already been
|
|
//initialized and had content attached to it. If that is the case,
|
|
//copy over its children to our new content container.
|
|
List<View> views = null;
|
|
if (mDecor.getChildCount() > 0) {
|
|
views = new ArrayList<View>(1); //Usually there's only one child
|
|
for (int i = 0, children = mDecor.getChildCount(); i < children; i++) {
|
|
View child = mDecor.getChildAt(0);
|
|
mDecor.removeView(child);
|
|
views.add(child);
|
|
}
|
|
}
|
|
|
|
mContentParent = generateLayout();
|
|
|
|
//Copy over the old children. See above for explanation.
|
|
if (views != null) {
|
|
for (View child : views) {
|
|
mContentParent.addView(child);
|
|
}
|
|
}
|
|
|
|
mTitleView = (TextView)mDecor.findViewById(android.R.id.title);
|
|
if (mTitleView != null) {
|
|
if (hasFeature(Window.FEATURE_NO_TITLE)) {
|
|
mTitleView.setVisibility(View.GONE);
|
|
if (mContentParent instanceof FrameLayout) {
|
|
((FrameLayout)mContentParent).setForeground(null);
|
|
}
|
|
} else {
|
|
mTitleView.setText(mTitle);
|
|
}
|
|
} else {
|
|
wActionBar = (ActionBarView)mDecor.findViewById(R.id.abs__action_bar);
|
|
if (wActionBar != null) {
|
|
wActionBar.setWindowCallback(this);
|
|
if (wActionBar.getTitle() == null) {
|
|
wActionBar.setWindowTitle(mActivity.getTitle());
|
|
}
|
|
if (hasFeature(Window.FEATURE_PROGRESS)) {
|
|
wActionBar.initProgress();
|
|
}
|
|
if (hasFeature(Window.FEATURE_INDETERMINATE_PROGRESS)) {
|
|
wActionBar.initIndeterminateProgress();
|
|
}
|
|
|
|
//Since we don't require onCreate dispatching, parse for uiOptions here
|
|
int uiOptions = loadUiOptionsFromManifest(mActivity);
|
|
if (uiOptions != 0) {
|
|
mUiOptions = uiOptions;
|
|
}
|
|
|
|
boolean splitActionBar = false;
|
|
final boolean splitWhenNarrow = (mUiOptions & ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW) != 0;
|
|
if (splitWhenNarrow) {
|
|
splitActionBar = getResources_getBoolean(mActivity, R.bool.abs__split_action_bar_is_narrow);
|
|
} else {
|
|
splitActionBar = mActivity.getTheme()
|
|
.obtainStyledAttributes(R.styleable.SherlockTheme)
|
|
.getBoolean(R.styleable.SherlockTheme_windowSplitActionBar, false);
|
|
}
|
|
final ActionBarContainer splitView = (ActionBarContainer)mDecor.findViewById(R.id.abs__split_action_bar);
|
|
if (splitView != null) {
|
|
wActionBar.setSplitView(splitView);
|
|
wActionBar.setSplitActionBar(splitActionBar);
|
|
wActionBar.setSplitWhenNarrow(splitWhenNarrow);
|
|
|
|
mActionModeView = (ActionBarContextView)mDecor.findViewById(R.id.abs__action_context_bar);
|
|
mActionModeView.setSplitView(splitView);
|
|
mActionModeView.setSplitActionBar(splitActionBar);
|
|
mActionModeView.setSplitWhenNarrow(splitWhenNarrow);
|
|
} else if (splitActionBar) {
|
|
Log.e(TAG, "Requested split action bar with incompatible window decor! Ignoring request.");
|
|
}
|
|
|
|
// Post the panel invalidate for later; avoid application onCreateOptionsMenu
|
|
// being called in the middle of onCreate or similar.
|
|
mDecor.post(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
//Invalidate if the panel menu hasn't been created before this.
|
|
if (!mIsDestroyed && !mActivity.isFinishing() && mMenu == null) {
|
|
dispatchInvalidateOptionsMenu();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private ViewGroup generateLayout() {
|
|
if (DEBUG) Log.d(TAG, "[generateLayout]");
|
|
|
|
// Apply data from current theme.
|
|
|
|
TypedArray a = mActivity.getTheme().obtainStyledAttributes(R.styleable.SherlockTheme);
|
|
|
|
mIsFloating = a.getBoolean(R.styleable.SherlockTheme_android_windowIsFloating, false);
|
|
|
|
if (!a.hasValue(R.styleable.SherlockTheme_windowActionBar)) {
|
|
throw new IllegalStateException("You must use Theme.Sherlock, Theme.Sherlock.Light, Theme.Sherlock.Light.DarkActionBar, or a derivative.");
|
|
}
|
|
|
|
if (a.getBoolean(R.styleable.SherlockTheme_windowNoTitle, false)) {
|
|
requestFeature(Window.FEATURE_NO_TITLE);
|
|
} else if (a.getBoolean(R.styleable.SherlockTheme_windowActionBar, false)) {
|
|
// Don't allow an action bar if there is no title.
|
|
requestFeature(Window.FEATURE_ACTION_BAR);
|
|
}
|
|
|
|
if (a.getBoolean(R.styleable.SherlockTheme_windowActionBarOverlay, false)) {
|
|
requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
|
|
}
|
|
|
|
if (a.getBoolean(R.styleable.SherlockTheme_windowActionModeOverlay, false)) {
|
|
requestFeature(Window.FEATURE_ACTION_MODE_OVERLAY);
|
|
}
|
|
|
|
a.recycle();
|
|
|
|
int layoutResource;
|
|
if (!hasFeature(Window.FEATURE_NO_TITLE)) {
|
|
if (mIsFloating) {
|
|
//Trash original dialog LinearLayout
|
|
mDecor = (ViewGroup)mDecor.getParent();
|
|
mDecor.removeAllViews();
|
|
|
|
layoutResource = R.layout.abs__dialog_title_holo;
|
|
} else {
|
|
if (hasFeature(Window.FEATURE_ACTION_BAR_OVERLAY)) {
|
|
layoutResource = R.layout.abs__screen_action_bar_overlay;
|
|
} else {
|
|
layoutResource = R.layout.abs__screen_action_bar;
|
|
}
|
|
}
|
|
} else if (hasFeature(Window.FEATURE_ACTION_MODE_OVERLAY) && !hasFeature(Window.FEATURE_NO_TITLE)) {
|
|
layoutResource = R.layout.abs__screen_simple_overlay_action_mode;
|
|
} else {
|
|
layoutResource = R.layout.abs__screen_simple;
|
|
}
|
|
|
|
if (DEBUG) Log.d(TAG, "[generateLayout] using screen XML " + mActivity.getResources().getString(layoutResource));
|
|
View in = mActivity.getLayoutInflater().inflate(layoutResource, null);
|
|
mDecor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
|
|
|
|
ViewGroup contentParent = (ViewGroup)mDecor.findViewById(R.id.abs__content);
|
|
if (contentParent == null) {
|
|
throw new RuntimeException("Couldn't find content container view");
|
|
}
|
|
|
|
//Make our new child the true content view (for fragments). VERY VOLATILE!
|
|
mDecor.setId(View.NO_ID);
|
|
contentParent.setId(android.R.id.content);
|
|
|
|
if (hasFeature(Window.FEATURE_INDETERMINATE_PROGRESS)) {
|
|
IcsProgressBar progress = getCircularProgressBar(false);
|
|
if (progress != null) {
|
|
progress.setIndeterminate(true);
|
|
}
|
|
}
|
|
|
|
return contentParent;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Miscellaneous
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Determine whether or not the device has a dedicated menu key.
|
|
*
|
|
* @return {@code true} if native menu key is present.
|
|
*/
|
|
private boolean isReservingOverflow() {
|
|
if (!mReserveOverflowSet) {
|
|
mReserveOverflow = ActionMenuPresenter.reserveOverflow(mActivity);
|
|
mReserveOverflowSet = true;
|
|
}
|
|
return mReserveOverflow;
|
|
}
|
|
|
|
private static int loadUiOptionsFromManifest(Activity activity) {
|
|
int uiOptions = 0;
|
|
try {
|
|
final String thisPackage = activity.getClass().getName();
|
|
if (DEBUG) Log.i(TAG, "Parsing AndroidManifest.xml for " + thisPackage);
|
|
|
|
final String packageName = activity.getApplicationInfo().packageName;
|
|
final AssetManager am = activity.createPackageContext(packageName, 0).getAssets();
|
|
final XmlResourceParser xml = am.openXmlResourceParser("AndroidManifest.xml");
|
|
|
|
int eventType = xml.getEventType();
|
|
while (eventType != XmlPullParser.END_DOCUMENT) {
|
|
if (eventType == XmlPullParser.START_TAG) {
|
|
String name = xml.getName();
|
|
|
|
if ("application".equals(name)) {
|
|
//Check if the <application> has the attribute
|
|
if (DEBUG) Log.d(TAG, "Got <application>");
|
|
|
|
for (int i = xml.getAttributeCount() - 1; i >= 0; i--) {
|
|
if (DEBUG) Log.d(TAG, xml.getAttributeName(i) + ": " + xml.getAttributeValue(i));
|
|
|
|
if ("uiOptions".equals(xml.getAttributeName(i))) {
|
|
uiOptions = xml.getAttributeIntValue(i, 0);
|
|
break; //out of for loop
|
|
}
|
|
}
|
|
} else if ("activity".equals(name)) {
|
|
//Check if the <activity> is us and has the attribute
|
|
if (DEBUG) Log.d(TAG, "Got <activity>");
|
|
Integer activityUiOptions = null;
|
|
String activityPackage = null;
|
|
boolean isOurActivity = false;
|
|
|
|
for (int i = xml.getAttributeCount() - 1; i >= 0; i--) {
|
|
if (DEBUG) Log.d(TAG, xml.getAttributeName(i) + ": " + xml.getAttributeValue(i));
|
|
|
|
//We need both uiOptions and name attributes
|
|
String attrName = xml.getAttributeName(i);
|
|
if ("uiOptions".equals(attrName)) {
|
|
activityUiOptions = xml.getAttributeIntValue(i, 0);
|
|
} else if ("name".equals(attrName)) {
|
|
activityPackage = cleanActivityName(packageName, xml.getAttributeValue(i));
|
|
if (!thisPackage.equals(activityPackage)) {
|
|
break; //out of for loop
|
|
}
|
|
isOurActivity = true;
|
|
}
|
|
|
|
//Make sure we have both attributes before processing
|
|
if ((activityUiOptions != null) && (activityPackage != null)) {
|
|
//Our activity, uiOptions specified, override with our value
|
|
uiOptions = activityUiOptions.intValue();
|
|
}
|
|
}
|
|
if (isOurActivity) {
|
|
//If we matched our activity but it had no logo don't
|
|
//do any more processing of the manifest
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
eventType = xml.nextToken();
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
if (DEBUG) Log.i(TAG, "Returning " + Integer.toHexString(uiOptions));
|
|
return uiOptions;
|
|
}
|
|
|
|
public static String cleanActivityName(String manifestPackage, String activityName) {
|
|
if (activityName.charAt(0) == '.') {
|
|
//Relative activity name (e.g., android:name=".ui.SomeClass")
|
|
return manifestPackage + activityName;
|
|
}
|
|
if (activityName.indexOf('.', 1) == -1) {
|
|
//Unqualified activity name (e.g., android:name="SomeClass")
|
|
return manifestPackage + "." + activityName;
|
|
}
|
|
//Fully-qualified activity name (e.g., "com.my.package.SomeClass")
|
|
return activityName;
|
|
}
|
|
|
|
/**
|
|
* Clears out internal reference when the action mode is destroyed.
|
|
*/
|
|
private class ActionModeCallbackWrapper implements ActionMode.Callback {
|
|
private final ActionMode.Callback mWrapped;
|
|
|
|
public ActionModeCallbackWrapper(ActionMode.Callback wrapped) {
|
|
mWrapped = wrapped;
|
|
}
|
|
|
|
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
|
return mWrapped.onCreateActionMode(mode, menu);
|
|
}
|
|
|
|
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
|
return mWrapped.onPrepareActionMode(mode, menu);
|
|
}
|
|
|
|
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
|
return mWrapped.onActionItemClicked(mode, item);
|
|
}
|
|
|
|
public void onDestroyActionMode(ActionMode mode) {
|
|
mWrapped.onDestroyActionMode(mode);
|
|
if (mActionModeView != null) {
|
|
mActionModeView.setVisibility(View.GONE);
|
|
mActionModeView.removeAllViews();
|
|
}
|
|
if (mActivity instanceof OnActionModeFinishedListener) {
|
|
((OnActionModeFinishedListener)mActivity).onActionModeFinished(mActionMode);
|
|
}
|
|
mActionMode = null;
|
|
}
|
|
}
|
|
}
|