-
-
Save XinyueZ/0e9fe2119b901921b160 to your computer and use it in GitHub Desktop.
package android.support.v7.app; | |
import android.support.v7.appcompat.R; | |
import android.content.Context; | |
import android.content.pm.ActivityInfo; | |
import android.content.pm.PackageManager; | |
import android.content.res.Configuration; | |
import android.content.res.TypedArray; | |
import android.os.Build; | |
import android.os.Bundle; | |
import android.support.v4.app.ActionBarDrawerToggle; | |
import android.support.v7.internal.view.SupportMenuInflater; | |
import android.support.v7.view.ActionMode; | |
import android.util.Log; | |
import android.view.Menu; | |
import android.view.MenuInflater; | |
import android.view.MenuItem; | |
import android.view.View; | |
import android.view.ViewGroup; | |
public abstract class ActionBarActivityDelegateCompat { | |
static final String METADATA_UI_OPTIONS = "android.support.UI_OPTIONS"; | |
static final String UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW = "splitActionBarWhenNarrow"; | |
private static final String TAG = "ActionBarActivityDelegate"; | |
static ActionBarActivityDelegateCompat createDelegate(ActionBarPreferenceActivity activity) { | |
final int version = Build.VERSION.SDK_INT; | |
if (version >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { | |
return new ActionBarActivityDelegateCompatICS(activity); | |
} else if (version >= Build.VERSION_CODES.HONEYCOMB) { | |
return new ActionBarActivityDelegateCompatHC(activity); | |
} else { | |
return new ActionBarActivityDelegateCompatBase(activity); | |
} | |
} | |
final ActionBarPreferenceActivity mActivity; | |
private ActionBar mActionBar; | |
private MenuInflater mMenuInflater; | |
// true if this activity has an action bar. | |
boolean mHasActionBar; | |
// true if this activity's action bar overlays other activity content. | |
boolean mOverlayActionBar; | |
ActionBarActivityDelegateCompat(ActionBarPreferenceActivity activity) { | |
mActivity = activity; | |
} | |
abstract ActionBar createSupportActionBar(); | |
final ActionBar getSupportActionBar() { | |
// The Action Bar should be lazily created as mHasActionBar or mOverlayActionBar | |
// could change after onCreate | |
if (mHasActionBar || mOverlayActionBar) { | |
if (mActionBar == null) { | |
mActionBar = createSupportActionBar(); | |
} | |
} else { | |
// If we're not set to have a Action Bar, null it just in case it's been set | |
mActionBar = null; | |
} | |
return mActionBar; | |
} | |
MenuInflater getMenuInflater() { | |
if (mMenuInflater == null) { | |
ActionBar ab = getSupportActionBar(); | |
if (ab != null) { | |
mMenuInflater = new SupportMenuInflater(ab.getThemedContext()); | |
} else { | |
mMenuInflater = new SupportMenuInflater(mActivity); | |
} | |
} | |
return mMenuInflater; | |
} | |
void onCreate(Bundle savedInstanceState) { | |
TypedArray a = mActivity.obtainStyledAttributes(R.styleable.ActionBarWindow); | |
if (!a.hasValue(R.styleable.ActionBarWindow_windowActionBar)) { | |
a.recycle(); | |
throw new IllegalStateException( | |
"You need to use a Theme.AppCompat theme (or descendant) with this activity."); | |
} | |
mHasActionBar = a.getBoolean(R.styleable.ActionBarWindow_windowActionBar, false); | |
mOverlayActionBar = a.getBoolean(R.styleable.ActionBarWindow_windowActionBarOverlay, false); | |
a.recycle(); | |
} | |
abstract void onConfigurationChanged(Configuration newConfig); | |
abstract void onStop(); | |
abstract void onPostResume(); | |
abstract void setContentView(View v); | |
abstract void setContentView(int resId); | |
abstract void setContentView(View v, ViewGroup.LayoutParams lp); | |
abstract void addContentView(View v, ViewGroup.LayoutParams lp); | |
abstract void setTitle(CharSequence title); | |
abstract void supportInvalidateOptionsMenu(); | |
abstract boolean supportRequestWindowFeature(int featureId); | |
// Methods used to create and respond to options menu | |
abstract View onCreatePanelView(int featureId); | |
abstract boolean onPreparePanel(int featureId, View view, Menu menu); | |
abstract boolean onCreatePanelMenu(int featureId, Menu menu); | |
abstract boolean onMenuItemSelected(int featureId, MenuItem item); | |
abstract boolean onBackPressed(); | |
abstract ActionMode startSupportActionMode(ActionMode.Callback callback); | |
abstract void setSupportProgressBarVisibility(boolean visible); | |
abstract void setSupportProgressBarIndeterminateVisibility(boolean visible); | |
abstract void setSupportProgressBarIndeterminate(boolean indeterminate); | |
abstract void setSupportProgress(int progress); | |
abstract ActionBarDrawerToggle.Delegate getDrawerToggleDelegate(); | |
protected final String getUiOptionsFromMetadata() { | |
try { | |
PackageManager pm = mActivity.getPackageManager(); | |
ActivityInfo info = pm.getActivityInfo(mActivity.getComponentName(), | |
PackageManager.GET_META_DATA); | |
String uiOptions = null; | |
if (info.metaData != null) { | |
uiOptions = info.metaData.getString(METADATA_UI_OPTIONS); | |
} | |
return uiOptions; | |
} catch (PackageManager.NameNotFoundException e) { | |
Log.e(TAG, "getUiOptionsFromMetadata: Activity '" + mActivity.getClass() | |
.getSimpleName() + "' not in manifest"); | |
return null; | |
} | |
} | |
protected final Context getActionBarThemedContext() { | |
Context context = mActivity; | |
// If we have an action bar, initialize the menu with a context themed from it. | |
ActionBar ab = getSupportActionBar(); | |
if (ab != null) { | |
context = ab.getThemedContext(); | |
} | |
return context; | |
} | |
} |
package android.support.v7.app; | |
import android.content.Context; | |
import android.content.res.Configuration; | |
import android.content.res.TypedArray; | |
import android.graphics.drawable.Drawable; | |
import android.support.v4.app.ActionBarDrawerToggle; | |
import android.support.v4.view.WindowCompat; | |
import android.support.v7.appcompat.R; | |
import android.support.v7.internal.view.menu.ListMenuPresenter; | |
import android.support.v7.internal.view.menu.MenuBuilder; | |
import android.support.v7.internal.view.menu.MenuPresenter; | |
import android.support.v7.internal.view.menu.MenuView; | |
import android.support.v7.internal.view.menu.MenuWrapperFactory; | |
import android.support.v7.internal.widget.ActionBarContainer; | |
import android.support.v7.internal.widget.ActionBarContextView; | |
import android.support.v7.internal.widget.ActionBarView; | |
import android.support.v7.internal.widget.ProgressBarICS; | |
import android.support.v7.view.ActionMode; | |
import android.view.LayoutInflater; | |
import android.view.Menu; | |
import android.view.MenuItem; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.view.Window; | |
import android.widget.FrameLayout; | |
import android.widget.ListView; | |
public class ActionBarActivityDelegateCompatBase extends ActionBarActivityDelegateCompat implements | |
MenuPresenter.Callback, MenuBuilder.Callback { | |
@SuppressWarnings("unused") | |
private static final String TAG = "ActionBarActivityDelegateBase"; | |
private static final int[] ACTION_BAR_DRAWABLE_TOGGLE_ATTRS = new int[] { | |
R.attr.homeAsUpIndicator | |
}; | |
private ActionBarView mActionBarView; | |
private ListMenuPresenter mListMenuPresenter; | |
private MenuBuilder mMenu; | |
private ActionMode mActionMode; | |
// true if we have installed a window sub-decor layout. | |
private boolean mSubDecorInstalled; | |
// Used to keep track of Progress Bar Window features | |
private boolean mFeatureProgress, mFeatureIndeterminateProgress; | |
private boolean mInvalidateMenuPosted; | |
private final Runnable mInvalidateMenuRunnable = new Runnable() { | |
@Override | |
public void run() { | |
final MenuBuilder menu = createMenu(); | |
if (mActivity.superOnCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, menu) && | |
mActivity.superOnPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, menu)) { | |
setMenu(menu); | |
} else { | |
setMenu(null); | |
} | |
mInvalidateMenuPosted = false; | |
} | |
}; | |
ActionBarActivityDelegateCompatBase(ActionBarPreferenceActivity activity) { | |
super(activity); | |
} | |
@Override | |
public ActionBar createSupportActionBar() { | |
ensureSubDecor(); | |
return new ActionBarImplCompatBase(mActivity, mActivity); | |
} | |
@Override | |
public void onConfigurationChanged(Configuration newConfig) { | |
// If this is called before sub-decor is installed, ActionBar will not | |
// be properly initialized. | |
if (mHasActionBar && mSubDecorInstalled) { | |
// Note: The action bar will need to access | |
// view changes from superclass. | |
ActionBarImplCompatBase actionBar = (ActionBarImplCompatBase) getSupportActionBar(); | |
actionBar.onConfigurationChanged(newConfig); | |
} | |
} | |
@Override | |
public void onStop() { | |
ActionBarImplCompatBase ab = (ActionBarImplCompatBase) getSupportActionBar(); | |
if (ab != null) { | |
ab.setShowHideAnimationEnabled(false); | |
} | |
} | |
@Override | |
public void onPostResume() { | |
ActionBarImplCompatBase ab = (ActionBarImplCompatBase) getSupportActionBar(); | |
if (ab != null) { | |
ab.setShowHideAnimationEnabled(true); | |
} | |
} | |
@Override | |
public void setContentView(View v) { | |
ensureSubDecor(); | |
if (mHasActionBar) { | |
final ViewGroup contentParent = | |
(ViewGroup) mActivity.findViewById(R.id.action_bar_activity_content); | |
contentParent.removeAllViews(); | |
contentParent.addView(v); | |
} else { | |
mActivity.superSetContentView(v); | |
} | |
} | |
@Override | |
public void setContentView(int resId) { | |
ensureSubDecor(); | |
if (mHasActionBar) { | |
final ViewGroup contentParent = | |
(ViewGroup) mActivity.findViewById(R.id.action_bar_activity_content); | |
contentParent.removeAllViews(); | |
final LayoutInflater inflater = mActivity.getLayoutInflater(); | |
inflater.inflate(resId, contentParent); | |
} else { | |
mActivity.superSetContentView(resId); | |
} | |
} | |
@Override | |
public void setContentView(View v, ViewGroup.LayoutParams lp) { | |
ensureSubDecor(); | |
if (mHasActionBar) { | |
final ViewGroup contentParent = | |
(ViewGroup) mActivity.findViewById(R.id.action_bar_activity_content); | |
contentParent.removeAllViews(); | |
contentParent.addView(v, lp); | |
} else { | |
mActivity.superSetContentView(v, lp); | |
} | |
} | |
@Override | |
public void addContentView(View v, ViewGroup.LayoutParams lp) { | |
ensureSubDecor(); | |
if (mHasActionBar) { | |
final ViewGroup contentParent = | |
(ViewGroup) mActivity.findViewById(R.id.action_bar_activity_content); | |
contentParent.addView(v, lp); | |
} else { | |
mActivity.superSetContentView(v, lp); | |
} | |
} | |
final void ensureSubDecor() { | |
if (mHasActionBar && !mSubDecorInstalled) { | |
ListView listView = new ListView(mActivity); | |
listView.setId(android.R.id.list); | |
listView.setLayoutParams( | |
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); | |
if (mOverlayActionBar) { | |
ViewGroup decor = (ViewGroup) mActivity.getLayoutInflater().inflate( | |
R.layout.abc_action_bar_decor_overlay, null); | |
decor.addView(listView); | |
mActivity.superSetContentView(decor); | |
} else { | |
ViewGroup decor = (ViewGroup) mActivity.getLayoutInflater().inflate(R.layout.abc_action_bar_decor, | |
null); | |
decor.addView(listView); | |
mActivity.superSetContentView(decor); | |
} | |
mActionBarView = (ActionBarView) mActivity.findViewById(R.id.action_bar); | |
mActionBarView.setWindowCallback(mActivity); | |
/** | |
* Progress Bars | |
*/ | |
if (mFeatureProgress) { | |
mActionBarView.initProgress(); | |
} | |
if (mFeatureIndeterminateProgress) { | |
mActionBarView.initIndeterminateProgress(); | |
} | |
/** | |
* Split Action Bar | |
*/ | |
boolean splitWhenNarrow = UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW | |
.equals(getUiOptionsFromMetadata()); | |
boolean splitActionBar; | |
if (splitWhenNarrow) { | |
splitActionBar = mActivity.getResources() | |
.getBoolean(R.bool.abc_split_action_bar_is_narrow); | |
} else { | |
TypedArray a = mActivity.obtainStyledAttributes(R.styleable.ActionBarWindow); | |
splitActionBar = a | |
.getBoolean(R.styleable.ActionBarWindow_windowSplitActionBar, false); | |
a.recycle(); | |
} | |
final ActionBarContainer splitView = (ActionBarContainer) mActivity.findViewById( | |
R.id.split_action_bar); | |
if (splitView != null) { | |
mActionBarView.setSplitView(splitView); | |
mActionBarView.setSplitActionBar(splitActionBar); | |
mActionBarView.setSplitWhenNarrow(splitWhenNarrow); | |
final ActionBarContextView cab = (ActionBarContextView) mActivity.findViewById( | |
R.id.action_context_bar); | |
cab.setSplitView(splitView); | |
cab.setSplitActionBar(splitActionBar); | |
cab.setSplitWhenNarrow(splitWhenNarrow); | |
} | |
mSubDecorInstalled = true; | |
supportInvalidateOptionsMenu(); | |
} | |
} | |
@Override | |
public boolean supportRequestWindowFeature(int featureId) { | |
switch (featureId) { | |
case WindowCompat.FEATURE_ACTION_BAR: | |
mHasActionBar = true; | |
return true; | |
case WindowCompat.FEATURE_ACTION_BAR_OVERLAY: | |
mOverlayActionBar = true; | |
return true; | |
case Window.FEATURE_PROGRESS: | |
mFeatureProgress = true; | |
return true; | |
case Window.FEATURE_INDETERMINATE_PROGRESS: | |
mFeatureIndeterminateProgress = true; | |
return true; | |
default: | |
return mActivity.requestWindowFeature(featureId); | |
} | |
} | |
@Override | |
public void setTitle(CharSequence title) { | |
ActionBar ab = getSupportActionBar(); | |
if (ab != null) { | |
ab.setTitle(title); | |
} | |
} | |
@Override | |
public View onCreatePanelView(int featureId) { | |
View createdPanelView = null; | |
if (featureId == Window.FEATURE_OPTIONS_PANEL) { | |
boolean show = true; | |
MenuBuilder menu = mMenu; | |
if (mActionMode == null) { | |
// We only want to dispatch Activity/Fragment menu calls if there isn't | |
// currently an action mode | |
if (menu == null) { | |
// We don't have a menu created, so create one | |
menu = createMenu(); | |
setMenu(menu); | |
// Make sure we're not dispatching item changes to presenters | |
menu.stopDispatchingItemsChanged(); | |
// Dispatch onCreateSupportOptionsMenu | |
show = mActivity.superOnCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, menu); | |
} | |
if (show) { | |
// Make sure we're not dispatching item changes to presenters | |
menu.stopDispatchingItemsChanged(); | |
// Dispatch onPrepareSupportOptionsMenu | |
show = mActivity.superOnPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, menu); | |
} | |
} | |
if (show) { | |
createdPanelView = (View) getListMenuView(mActivity, this); | |
// Allow menu to start dispatching changes to presenters | |
menu.startDispatchingItemsChanged(); | |
} else { | |
// If the menu isn't being shown, we no longer need it | |
setMenu(null); | |
} | |
} | |
return createdPanelView; | |
} | |
@Override | |
public boolean onCreatePanelMenu(int featureId, Menu menu) { | |
if (featureId != Window.FEATURE_OPTIONS_PANEL) { | |
return mActivity.superOnCreatePanelMenu(featureId, menu); | |
} | |
return false; | |
} | |
@Override | |
public boolean onPreparePanel(int featureId, View view, Menu menu) { | |
if (featureId != Window.FEATURE_OPTIONS_PANEL) { | |
return mActivity.superOnPreparePanel(featureId, view, menu); | |
} | |
return false; | |
} | |
@Override | |
public boolean onMenuItemSelected(int featureId, MenuItem item) { | |
if (featureId == Window.FEATURE_OPTIONS_PANEL) { | |
item = MenuWrapperFactory.createMenuItemWrapper(item); | |
} | |
return mActivity.superOnMenuItemSelected(featureId, item); | |
} | |
@Override | |
public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { | |
return mActivity.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, item); | |
} | |
@Override | |
public void onMenuModeChange(MenuBuilder menu) { | |
reopenMenu(menu, true); | |
} | |
@Override | |
public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { | |
mActivity.closeOptionsMenu(); | |
} | |
@Override | |
public boolean onOpenSubMenu(MenuBuilder subMenu) { | |
return false; | |
} | |
@Override | |
public ActionMode startSupportActionMode(ActionMode.Callback callback) { | |
if (callback == null) { | |
throw new IllegalArgumentException("ActionMode callback can not be null."); | |
} | |
if (mActionMode != null) { | |
mActionMode.finish(); | |
} | |
final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback); | |
ActionBarImplCompatBase ab = (ActionBarImplCompatBase) getSupportActionBar(); | |
if (ab != null) { | |
mActionMode = ab.startActionMode(wrappedCallback); | |
} | |
if (mActionMode != null) { | |
mActivity.onSupportActionModeStarted(mActionMode); | |
} | |
return mActionMode; | |
} | |
@Override | |
public void supportInvalidateOptionsMenu() { | |
if (!mInvalidateMenuPosted) { | |
mInvalidateMenuPosted = true; | |
mActivity.getWindow().getDecorView().post(mInvalidateMenuRunnable); | |
} | |
} | |
private MenuBuilder createMenu() { | |
MenuBuilder menu = new MenuBuilder(getActionBarThemedContext()); | |
menu.setCallback(this); | |
return menu; | |
} | |
private void reopenMenu(MenuBuilder menu, boolean toggleMenuMode) { | |
if (mActionBarView != null && mActionBarView.isOverflowReserved()) { | |
if (!mActionBarView.isOverflowMenuShowing() || !toggleMenuMode) { | |
if (mActionBarView.getVisibility() == View.VISIBLE) { | |
mActionBarView.showOverflowMenu(); | |
} | |
} else { | |
mActionBarView.hideOverflowMenu(); | |
} | |
return; | |
} | |
menu.close(); | |
} | |
private MenuView getListMenuView(Context context, MenuPresenter.Callback cb) { | |
if (mMenu == null) { | |
return null; | |
} | |
if (mListMenuPresenter == null) { | |
TypedArray a = context.obtainStyledAttributes(R.styleable.Theme); | |
final int listPresenterTheme = a.getResourceId( | |
R.styleable.Theme_panelMenuListTheme, | |
R.style.Theme_AppCompat_CompactMenu); | |
a.recycle(); | |
mListMenuPresenter = new ListMenuPresenter( | |
R.layout.abc_list_menu_item_layout, listPresenterTheme); | |
mListMenuPresenter.setCallback(cb); | |
mMenu.addMenuPresenter(mListMenuPresenter); | |
} else { | |
// Make sure we update the ListView | |
mListMenuPresenter.updateMenuView(false); | |
} | |
return mListMenuPresenter.getMenuView(new FrameLayout(context)); | |
} | |
private void setMenu(MenuBuilder menu) { | |
if (menu == mMenu) { | |
return; | |
} | |
if (mMenu != null) { | |
mMenu.removeMenuPresenter(mListMenuPresenter); | |
} | |
mMenu = menu; | |
if (menu != null && mListMenuPresenter != null) { | |
// Only update list menu if there isn't an action mode menu | |
menu.addMenuPresenter(mListMenuPresenter); | |
} | |
if (mActionBarView != null) { | |
mActionBarView.setMenu(menu, this); | |
} | |
} | |
@Override | |
public boolean onBackPressed() { | |
// Back cancels action modes first. | |
if (mActionMode != null) { | |
mActionMode.finish(); | |
return true; | |
} | |
// Next collapse any expanded action views. | |
if (mActionBarView != null && mActionBarView.hasExpandedActionView()) { | |
mActionBarView.collapseActionView(); | |
return true; | |
} | |
return false; | |
} | |
@Override | |
void setSupportProgressBarVisibility(boolean visible) { | |
updateProgressBars(visible ? Window.PROGRESS_VISIBILITY_ON : | |
Window.PROGRESS_VISIBILITY_OFF); | |
} | |
@Override | |
void setSupportProgressBarIndeterminateVisibility(boolean visible) { | |
updateProgressBars(visible ? Window.PROGRESS_VISIBILITY_ON : | |
Window.PROGRESS_VISIBILITY_OFF); | |
} | |
@Override | |
void setSupportProgressBarIndeterminate(boolean indeterminate) { | |
updateProgressBars(indeterminate ? Window.PROGRESS_INDETERMINATE_ON | |
: Window.PROGRESS_INDETERMINATE_OFF); | |
} | |
@Override | |
void setSupportProgress(int progress) { | |
updateProgressBars(Window.PROGRESS_START + progress); | |
} | |
@Override | |
ActionBarDrawerToggle.Delegate getDrawerToggleDelegate() { | |
return new ActionBarDrawableToggleImpl(); | |
} | |
/** | |
* Progress Bar function. Mostly extracted from PhoneWindow.java | |
*/ | |
private void updateProgressBars(int value) { | |
ProgressBarICS circularProgressBar = getCircularProgressBar(); | |
ProgressBarICS horizontalProgressBar = getHorizontalProgressBar(); | |
if (value == Window.PROGRESS_VISIBILITY_ON) { | |
if (mFeatureProgress) { | |
int level = horizontalProgressBar.getProgress(); | |
int visibility = (horizontalProgressBar.isIndeterminate() || level < 10000) ? | |
View.VISIBLE : View.INVISIBLE; | |
horizontalProgressBar.setVisibility(visibility); | |
} | |
if (mFeatureIndeterminateProgress) { | |
circularProgressBar.setVisibility(View.VISIBLE); | |
} | |
} else if (value == Window.PROGRESS_VISIBILITY_OFF) { | |
if (mFeatureProgress) { | |
horizontalProgressBar.setVisibility(View.GONE); | |
} | |
if (mFeatureIndeterminateProgress) { | |
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); | |
} | |
} | |
} | |
private void showProgressBars(ProgressBarICS horizontalProgressBar, | |
ProgressBarICS spinnyProgressBar) { | |
if (mFeatureIndeterminateProgress && spinnyProgressBar.getVisibility() == View.INVISIBLE) { | |
spinnyProgressBar.setVisibility(View.VISIBLE); | |
} | |
// Only show the progress bars if the primary progress is not complete | |
if (mFeatureProgress && horizontalProgressBar.getProgress() < 10000) { | |
horizontalProgressBar.setVisibility(View.VISIBLE); | |
} | |
} | |
private void hideProgressBars(ProgressBarICS horizontalProgressBar, | |
ProgressBarICS spinnyProgressBar) { | |
if (mFeatureIndeterminateProgress && spinnyProgressBar.getVisibility() == View.VISIBLE) { | |
spinnyProgressBar.setVisibility(View.INVISIBLE); | |
} | |
if (mFeatureProgress && horizontalProgressBar.getVisibility() == View.VISIBLE) { | |
horizontalProgressBar.setVisibility(View.INVISIBLE); | |
} | |
} | |
private ProgressBarICS getCircularProgressBar() { | |
ProgressBarICS pb = (ProgressBarICS) mActionBarView.findViewById(R.id.progress_circular); | |
if (pb != null) { | |
pb.setVisibility(View.INVISIBLE); | |
} | |
return pb; | |
} | |
private ProgressBarICS getHorizontalProgressBar() { | |
ProgressBarICS pb = (ProgressBarICS) mActionBarView.findViewById(R.id.progress_horizontal); | |
if (pb != null) { | |
pb.setVisibility(View.INVISIBLE); | |
} | |
return pb; | |
} | |
/** | |
* Clears out internal reference when the action mode is destroyed. | |
*/ | |
private class ActionModeCallbackWrapper implements ActionMode.Callback { | |
private 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); | |
mActivity.onSupportActionModeFinished(mode); | |
mActionMode = null; | |
} | |
} | |
private class ActionBarDrawableToggleImpl | |
implements ActionBarDrawerToggle.Delegate { | |
@Override | |
public Drawable getThemeUpIndicator() { | |
final TypedArray a = mActivity.obtainStyledAttributes(ACTION_BAR_DRAWABLE_TOGGLE_ATTRS); | |
final Drawable result = a.getDrawable(0); | |
a.recycle(); | |
return result; | |
} | |
@Override | |
public void setActionBarUpIndicator(Drawable upDrawable, int contentDescRes) { | |
if (mActionBarView != null) { | |
mActionBarView.setHomeAsUpIndicator(upDrawable); | |
} | |
} | |
@Override | |
public void setActionBarDescription(int contentDescRes) { | |
// No support for setting Action Bar content description | |
} | |
} | |
} |
package android.support.v7.app; | |
import android.os.Bundle; | |
import android.view.Window; | |
class ActionBarActivityDelegateCompatHC extends ActionBarActivityDelegateCompatBase { | |
ActionBarActivityDelegateCompatHC(ActionBarPreferenceActivity activity) { | |
super(activity); | |
} | |
@Override | |
void onCreate(Bundle savedInstanceState) { | |
/** | |
* A native Action Mode could be displayed (text selection, etc) so we need to make sure it | |
* is positioned correctly. Here we request the ACTION_MODE_OVERLAY feature so that it | |
* displays over the compat Action Bar. | |
* {@link android.support.v7.internal.widget.NativeActionModeAwareLayout} is responsible for | |
* making sure that the compat Action Bar is visible when an Action Mode is started | |
* (for positioning). | |
*/ | |
mActivity.getWindow().requestFeature(Window.FEATURE_ACTION_MODE_OVERLAY); | |
super.onCreate(savedInstanceState); | |
} | |
@Override | |
public ActionBar createSupportActionBar() { | |
ensureSubDecor(); | |
return new ActionBarImplCompatHC(mActivity, mActivity); | |
} | |
} |
package android.support.v7.app; | |
import android.annotation.TargetApi; | |
import android.content.Context; | |
import android.content.pm.ActivityInfo; | |
import android.content.res.Configuration; | |
import android.os.Build; | |
import android.os.Bundle; | |
import android.support.v4.app.ActionBarDrawerToggle; | |
import android.support.v4.view.WindowCompat; | |
import android.support.v7.internal.view.ActionModeWrapper; | |
import android.support.v7.internal.view.menu.MenuWrapperFactory; | |
import android.support.v7.view.ActionMode; | |
import android.view.KeyEvent; | |
import android.view.Menu; | |
import android.view.MenuItem; | |
import android.view.MotionEvent; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.view.Window; | |
import android.view.WindowManager; | |
import android.view.accessibility.AccessibilityEvent; | |
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) | |
class ActionBarActivityDelegateCompatICS extends ActionBarActivityDelegateCompat { | |
Menu mMenu; | |
ActionBarActivityDelegateCompatICS(ActionBarPreferenceActivity activity) { | |
super(activity); | |
} | |
@Override | |
public ActionBar createSupportActionBar() { | |
return new ActionBarImplCompatICS(mActivity, mActivity); | |
} | |
@Override | |
public void onCreate(Bundle savedInstanceState) { | |
// Set framework uiOptions from the support metadata value | |
if (UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW.equals(getUiOptionsFromMetadata())) { | |
mActivity.getWindow().setUiOptions(ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW, | |
ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW); | |
} | |
if (mHasActionBar) { | |
// If action bar is requested by inheriting from the appcompat theme, | |
// the system will not know about that. So explicitly request for an action bar. | |
mActivity.requestWindowFeature(WindowCompat.FEATURE_ACTION_BAR); | |
} | |
if (mOverlayActionBar) { | |
mActivity.requestWindowFeature(WindowCompat.FEATURE_ACTION_BAR_OVERLAY); | |
} | |
super.onCreate(savedInstanceState); | |
/* | |
* This goofy move needs some explanation. | |
* | |
* The verifier on older platform versions has some interesting side effects if | |
* a class defines a method that takes a parameter of a type that doesn't exist. | |
* In this case, that type is android.view.ActionMode. Therefore, ActionBarActivity | |
* cannot override the onActionModeStarted/Finished methods without causing nastiness | |
* when it is loaded on older platform versions. | |
* | |
* Since these methods are actually part of the window callback and not intrinsic to | |
* Activity itself, we can install a little shim with the window instead that knows | |
* about the ActionMode class. Note that this means that any new methods added to | |
* Window.Callback in the future won't get proxied without updating the support lib, | |
* but we shouldn't be adding new methods to public interfaces that way anyway...right? ;) | |
*/ | |
final Window w = mActivity.getWindow(); | |
w.setCallback(createWindowCallbackWrapper(w.getCallback())); | |
} | |
Window.Callback createWindowCallbackWrapper(Window.Callback cb) { | |
return new WindowCallbackWrapper(cb); | |
} | |
@Override | |
public void onConfigurationChanged(Configuration newConfig) { | |
} | |
@Override | |
public void onStop() { | |
} | |
@Override | |
public void onPostResume() { | |
} | |
@Override | |
public void setContentView(View v) { | |
mActivity.superSetContentView(v); | |
} | |
@Override | |
public void setContentView(int resId) { | |
mActivity.superSetContentView(resId); | |
} | |
@Override | |
public void setContentView(View v, ViewGroup.LayoutParams lp) { | |
mActivity.superSetContentView(v, lp); | |
} | |
@Override | |
public void addContentView(View v, ViewGroup.LayoutParams lp) { | |
mActivity.superAddContentView(v, lp); | |
} | |
@Override | |
public boolean supportRequestWindowFeature(int featureId) { | |
return mActivity.requestWindowFeature(featureId); | |
} | |
@Override | |
public View onCreatePanelView(int featureId) { | |
// Do not create custom options menu on HC+ | |
return null; | |
} | |
@Override | |
public boolean onCreatePanelMenu(int featureId, Menu menu) { | |
if (featureId == Window.FEATURE_OPTIONS_PANEL || featureId == Window.FEATURE_ACTION_BAR) { | |
if (mMenu == null) { | |
mMenu = MenuWrapperFactory.createMenuWrapper(menu); | |
} | |
return mActivity.superOnCreatePanelMenu(featureId, mMenu); | |
} | |
return mActivity.superOnCreatePanelMenu(featureId, menu); | |
} | |
@Override | |
public boolean onPreparePanel(int featureId, View view, Menu menu) { | |
if (featureId == Window.FEATURE_OPTIONS_PANEL || featureId == Window.FEATURE_ACTION_BAR) { | |
return mActivity.superOnPreparePanel(featureId, view, mMenu); | |
} | |
return mActivity.superOnPreparePanel(featureId, view, menu); | |
} | |
@Override | |
public boolean onMenuItemSelected(int featureId, MenuItem item) { | |
if (featureId == Window.FEATURE_OPTIONS_PANEL) { | |
item = MenuWrapperFactory.createMenuItemWrapper(item); | |
} | |
return mActivity.superOnMenuItemSelected(featureId, item); | |
} | |
@Override | |
public void setTitle(CharSequence title) { | |
// Handled by framework | |
} | |
@Override | |
public ActionMode startSupportActionMode(ActionMode.Callback callback) { | |
if (callback == null) { | |
throw new IllegalArgumentException("ActionMode callback can not be null."); | |
} | |
Context context = getActionBarThemedContext(); | |
ActionModeWrapper.CallbackWrapper wrappedCallback = new ActionModeWrapper.CallbackWrapper( | |
context, callback); | |
ActionModeWrapper wrappedMode = null; | |
android.view.ActionMode frameworkMode = mActivity.startActionMode(wrappedCallback); | |
if (frameworkMode != null) { | |
wrappedMode = new ActionModeWrapper(context, | |
mActivity.startActionMode(wrappedCallback)); | |
wrappedCallback.setLastStartedActionMode(wrappedMode); | |
} | |
return wrappedMode; | |
} | |
public void onActionModeStarted(android.view.ActionMode mode) { | |
mActivity.onSupportActionModeStarted( | |
new ActionModeWrapper(getActionBarThemedContext(), mode)); | |
} | |
@Override | |
void setSupportProgressBarVisibility(boolean visible) { | |
mActivity.setProgressBarVisibility(visible); | |
} | |
@Override | |
void setSupportProgressBarIndeterminateVisibility(boolean visible) { | |
mActivity.setProgressBarIndeterminateVisibility(visible); | |
} | |
@Override | |
void setSupportProgressBarIndeterminate(boolean indeterminate) { | |
mActivity.setProgressBarIndeterminate(indeterminate); | |
} | |
@Override | |
void setSupportProgress(int progress) { | |
mActivity.setProgress(progress); | |
} | |
public void onActionModeFinished(android.view.ActionMode mode) { | |
mActivity.onSupportActionModeFinished( | |
new ActionModeWrapper(getActionBarThemedContext(), mode)); | |
} | |
@Override | |
public void supportInvalidateOptionsMenu() { | |
mMenu = null; | |
} | |
@Override | |
public boolean onBackPressed() { | |
return false; | |
} | |
@Override | |
public ActionBarDrawerToggle.Delegate getDrawerToggleDelegate() { | |
// Return null so that ActionBarDrawableToggle uses it's standard impl | |
return null; | |
} | |
class WindowCallbackWrapper implements Window.Callback { | |
final Window.Callback mWrapped; | |
public WindowCallbackWrapper(Window.Callback wrapped) { | |
mWrapped = wrapped; | |
} | |
@Override | |
public boolean dispatchKeyEvent(KeyEvent event) { | |
return mWrapped.dispatchKeyEvent(event); | |
} | |
@Override | |
public boolean dispatchKeyShortcutEvent(KeyEvent event) { | |
return mWrapped.dispatchKeyShortcutEvent(event); | |
} | |
@Override | |
public boolean dispatchTouchEvent(MotionEvent event) { | |
return mWrapped.dispatchTouchEvent(event); | |
} | |
@Override | |
public boolean dispatchTrackballEvent(MotionEvent event) { | |
return mWrapped.dispatchTrackballEvent(event); | |
} | |
@Override | |
public boolean dispatchGenericMotionEvent(MotionEvent event) { | |
return mWrapped.dispatchGenericMotionEvent(event); | |
} | |
@Override | |
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { | |
return mWrapped.dispatchPopulateAccessibilityEvent(event); | |
} | |
@Override | |
public View onCreatePanelView(int featureId) { | |
return mWrapped.onCreatePanelView(featureId); | |
} | |
@Override | |
public boolean onCreatePanelMenu(int featureId, Menu menu) { | |
return mWrapped.onCreatePanelMenu(featureId, menu); | |
} | |
@Override | |
public boolean onPreparePanel(int featureId, View view, Menu menu) { | |
return mWrapped.onPreparePanel(featureId, view, menu); | |
} | |
@Override | |
public boolean onMenuOpened(int featureId, Menu menu) { | |
return mWrapped.onMenuOpened(featureId, menu); | |
} | |
@Override | |
public boolean onMenuItemSelected(int featureId, MenuItem item) { | |
return mWrapped.onMenuItemSelected(featureId, item); | |
} | |
@Override | |
public void onWindowAttributesChanged(WindowManager.LayoutParams attrs) { | |
mWrapped.onWindowAttributesChanged(attrs); | |
} | |
@Override | |
public void onContentChanged() { | |
mWrapped.onContentChanged(); | |
} | |
@Override | |
public void onWindowFocusChanged(boolean hasFocus) { | |
mWrapped.onWindowFocusChanged(hasFocus); | |
} | |
@Override | |
public void onAttachedToWindow() { | |
mWrapped.onAttachedToWindow(); | |
} | |
@Override | |
public void onDetachedFromWindow() { | |
mWrapped.onDetachedFromWindow(); | |
} | |
@Override | |
public void onPanelClosed(int featureId, Menu menu) { | |
mWrapped.onPanelClosed(featureId, menu); | |
} | |
@Override | |
public boolean onSearchRequested() { | |
return mWrapped.onSearchRequested(); | |
} | |
@Override | |
public android.view.ActionMode onWindowStartingActionMode( | |
android.view.ActionMode.Callback callback) { | |
return mWrapped.onWindowStartingActionMode(callback); | |
} | |
/* | |
* And here are the money methods, the reason why this wrapper exists: | |
*/ | |
@Override | |
public void onActionModeStarted(android.view.ActionMode mode) { | |
mWrapped.onActionModeStarted(mode); | |
ActionBarActivityDelegateCompatICS.this.onActionModeStarted(mode); | |
} | |
@Override | |
public void onActionModeFinished(android.view.ActionMode mode) { | |
mWrapped.onActionModeFinished(mode); | |
ActionBarActivityDelegateCompatICS.this.onActionModeFinished(mode); | |
} | |
} | |
} |
/* | |
* Copyright (C) 2012 The Android Open Source Project | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package android.support.v7.app; | |
import java.lang.ref.WeakReference; | |
import java.util.ArrayList; | |
import android.app.Dialog; | |
import android.content.Context; | |
import android.content.res.Configuration; | |
import android.content.res.Resources; | |
import android.graphics.drawable.Drawable; | |
import android.os.Handler; | |
import android.support.v4.app.FragmentTransaction; | |
import android.support.v4.internal.view.SupportMenuItem; | |
import android.support.v7.appcompat.R; | |
import android.support.v7.internal.view.ActionBarPolicy; | |
import android.support.v7.internal.view.SupportMenuInflater; | |
import android.support.v7.internal.view.menu.MenuBuilder; | |
import android.support.v7.internal.view.menu.SubMenuBuilder; | |
import android.support.v7.internal.widget.ActionBarContainer; | |
import android.support.v7.internal.widget.ActionBarContextView; | |
import android.support.v7.internal.widget.ActionBarOverlayLayout; | |
import android.support.v7.internal.widget.ActionBarView; | |
import android.support.v7.internal.widget.ScrollingTabContainerView; | |
import android.support.v7.view.ActionMode; | |
import android.util.TypedValue; | |
import android.view.ContextThemeWrapper; | |
import android.view.LayoutInflater; | |
import android.view.Menu; | |
import android.view.MenuInflater; | |
import android.view.MenuItem; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.view.accessibility.AccessibilityEvent; | |
import android.view.animation.Animation; | |
import android.view.animation.AnimationUtils; | |
import android.widget.SpinnerAdapter; | |
@SuppressWarnings("unused") | |
class ActionBarImplCompatBase extends ActionBar { | |
private Context mContext; | |
private Context mThemedContext; | |
private ActionBarPreferenceActivity mActivity; | |
private Dialog mDialog; | |
private ActionBarOverlayLayout mOverlayLayout; | |
private ActionBarContainer mContainerView; | |
private ViewGroup mTopVisibilityView; | |
private ActionBarView mActionView; | |
private ActionBarContextView mContextView; | |
private ActionBarContainer mSplitView; | |
private View mContentView; | |
private ScrollingTabContainerView mTabScrollView; | |
private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>(); | |
private TabImpl mSelectedTab; | |
private int mSavedTabPosition = INVALID_POSITION; | |
private boolean mDisplayHomeAsUpSet; | |
ActionModeImpl mActionMode; | |
ActionMode mDeferredDestroyActionMode; | |
ActionMode.Callback mDeferredModeDestroyCallback; | |
private boolean mLastMenuVisibility; | |
private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners = | |
new ArrayList<OnMenuVisibilityListener>(); | |
private static final int CONTEXT_DISPLAY_NORMAL = 0; | |
private static final int CONTEXT_DISPLAY_SPLIT = 1; | |
private static final int INVALID_POSITION = -1; | |
private int mContextDisplayMode; | |
private boolean mHasEmbeddedTabs; | |
final Handler mHandler = new Handler(); | |
Runnable mTabSelector; | |
private int mCurWindowVisibility = View.VISIBLE; | |
private boolean mHiddenByApp; | |
private boolean mHiddenBySystem; | |
private boolean mShowingForMode; | |
private boolean mNowShowing = true; | |
private boolean mShowHideAnimationEnabled; | |
private Callback mCallback; | |
public ActionBarImplCompatBase(ActionBarPreferenceActivity activity, Callback callback) { | |
mActivity = activity; | |
mContext = activity; | |
mCallback = callback; | |
init(mActivity); | |
} | |
private void init(ActionBarPreferenceActivity activity) { | |
mOverlayLayout = (ActionBarOverlayLayout) activity.findViewById( | |
R.id.action_bar_overlay_layout); | |
if (mOverlayLayout != null) { | |
mOverlayLayout.setActionBar(this); | |
} | |
mActionView = (ActionBarView) activity.findViewById(R.id.action_bar); | |
mContextView = (ActionBarContextView) activity.findViewById(R.id.action_context_bar); | |
mContainerView = (ActionBarContainer) activity.findViewById(R.id.action_bar_container); | |
mTopVisibilityView = (ViewGroup) activity.findViewById(R.id.top_action_bar); | |
if (mTopVisibilityView == null) { | |
mTopVisibilityView = mContainerView; | |
} | |
mSplitView = (ActionBarContainer) activity.findViewById(R.id.split_action_bar); | |
if (mActionView == null || mContextView == null || mContainerView == null) { | |
throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + | |
"with a compatible window decor layout"); | |
} | |
mActionView.setContextView(mContextView); | |
mContextDisplayMode = mActionView.isSplitActionBar() ? | |
CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL; | |
// This was initially read from the action bar style | |
final int current = mActionView.getDisplayOptions(); | |
final boolean homeAsUp = (current & DISPLAY_HOME_AS_UP) != 0; | |
if (homeAsUp) { | |
mDisplayHomeAsUpSet = true; | |
} | |
ActionBarPolicy abp = ActionBarPolicy.get(mContext); | |
setHomeButtonEnabled(abp.enableHomeButtonByDefault() || homeAsUp); | |
setHasEmbeddedTabs(abp.hasEmbeddedTabs()); | |
setTitle(mActivity.getTitle()); | |
} | |
public void onConfigurationChanged(Configuration newConfig) { | |
setHasEmbeddedTabs(ActionBarPolicy.get(mContext).hasEmbeddedTabs()); | |
} | |
private void setHasEmbeddedTabs(boolean hasEmbeddedTabs) { | |
mHasEmbeddedTabs = hasEmbeddedTabs; | |
// Switch tab layout configuration if needed | |
if (!mHasEmbeddedTabs) { | |
mActionView.setEmbeddedTabView(null); | |
mContainerView.setTabContainer(mTabScrollView); | |
} else { | |
mContainerView.setTabContainer(null); | |
mActionView.setEmbeddedTabView(mTabScrollView); | |
} | |
final boolean isInTabMode = getNavigationMode() == NAVIGATION_MODE_TABS; | |
if (mTabScrollView != null) { | |
if (isInTabMode) { | |
mTabScrollView.setVisibility(View.VISIBLE); | |
} else { | |
mTabScrollView.setVisibility(View.GONE); | |
} | |
} | |
mActionView.setCollapsable(!mHasEmbeddedTabs && isInTabMode); | |
} | |
public boolean hasNonEmbeddedTabs() { | |
return !mHasEmbeddedTabs && getNavigationMode() == NAVIGATION_MODE_TABS; | |
} | |
@Override | |
public void setCustomView(View view) { | |
mActionView.setCustomNavigationView(view); | |
} | |
@Override | |
public void setCustomView(View view, LayoutParams layoutParams) { | |
view.setLayoutParams(layoutParams); | |
mActionView.setCustomNavigationView(view); | |
} | |
@Override | |
public void setCustomView(int resId) { | |
setCustomView(LayoutInflater.from(getThemedContext()) | |
.inflate(resId, mActionView, false)); | |
} | |
@Override | |
public void setIcon(int resId) { | |
mActionView.setIcon(resId); | |
} | |
@Override | |
public void setIcon(Drawable icon) { | |
mActionView.setIcon(icon); | |
} | |
@Override | |
public void setLogo(int resId) { | |
mActionView.setLogo(resId); | |
} | |
@Override | |
public void setLogo(Drawable logo) { | |
mActionView.setLogo(logo); | |
} | |
@Override | |
public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) { | |
mActionView.setDropdownAdapter(adapter); | |
mActionView.setCallback(callback); | |
} | |
@Override | |
public void setSelectedNavigationItem(int position) { | |
switch (mActionView.getNavigationMode()) { | |
case NAVIGATION_MODE_TABS: | |
selectTab(mTabs.get(position)); | |
break; | |
case NAVIGATION_MODE_LIST: | |
mActionView.setDropdownSelectedPosition(position); | |
break; | |
default: | |
throw new IllegalStateException( | |
"setSelectedNavigationIndex not valid for current navigation mode"); | |
} | |
} | |
@Override | |
public int getSelectedNavigationIndex() { | |
switch (mActionView.getNavigationMode()) { | |
case NAVIGATION_MODE_TABS: | |
return mSelectedTab != null ? mSelectedTab.getPosition() : -1; | |
case NAVIGATION_MODE_LIST: | |
return mActionView.getDropdownSelectedPosition(); | |
default: | |
return -1; | |
} | |
} | |
@Override | |
public int getNavigationItemCount() { | |
switch (mActionView.getNavigationMode()) { | |
case NAVIGATION_MODE_TABS: | |
return mTabs.size(); | |
case NAVIGATION_MODE_LIST: | |
SpinnerAdapter adapter = mActionView.getDropdownAdapter(); | |
return adapter != null ? adapter.getCount() : 0; | |
default: | |
return 0; | |
} | |
} | |
@Override | |
public void setTitle(CharSequence title) { | |
mActionView.setTitle(title); | |
} | |
@Override | |
public void setTitle(int resId) { | |
setTitle(mContext.getString(resId)); | |
} | |
@Override | |
public void setSubtitle(CharSequence subtitle) { | |
mActionView.setSubtitle(subtitle); | |
} | |
@Override | |
public void setSubtitle(int resId) { | |
setSubtitle(mContext.getString(resId)); | |
} | |
@Override | |
public void setDisplayOptions(int options) { | |
if ((options & DISPLAY_HOME_AS_UP) != 0) { | |
mDisplayHomeAsUpSet = true; | |
} | |
mActionView.setDisplayOptions(options); | |
} | |
@Override | |
public void setDisplayOptions(int options, int mask) { | |
final int current = mActionView.getDisplayOptions(); | |
if ((mask & DISPLAY_HOME_AS_UP) != 0) { | |
mDisplayHomeAsUpSet = true; | |
} | |
mActionView.setDisplayOptions((options & mask) | (current & ~mask)); | |
} | |
@Override | |
public void setDisplayUseLogoEnabled(boolean useLogo) { | |
setDisplayOptions(useLogo ? DISPLAY_USE_LOGO : 0, DISPLAY_USE_LOGO); | |
} | |
@Override | |
public void setDisplayShowHomeEnabled(boolean showHome) { | |
setDisplayOptions(showHome ? DISPLAY_SHOW_HOME : 0, DISPLAY_SHOW_HOME); | |
} | |
@Override | |
public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) { | |
setDisplayOptions(showHomeAsUp ? DISPLAY_HOME_AS_UP : 0, DISPLAY_HOME_AS_UP); | |
} | |
@Override | |
public void setDisplayShowTitleEnabled(boolean showTitle) { | |
setDisplayOptions(showTitle ? DISPLAY_SHOW_TITLE : 0, DISPLAY_SHOW_TITLE); | |
} | |
@Override | |
public void setDisplayShowCustomEnabled(boolean showCustom) { | |
setDisplayOptions(showCustom ? DISPLAY_SHOW_CUSTOM : 0, DISPLAY_SHOW_CUSTOM); | |
} | |
@Override | |
public void setHomeButtonEnabled(boolean enable) { | |
mActionView.setHomeButtonEnabled(enable); | |
} | |
@Override | |
public void setBackgroundDrawable(Drawable d) { | |
mContainerView.setPrimaryBackground(d); | |
} | |
@Override | |
public View getCustomView() { | |
return mActionView.getCustomNavigationView(); | |
} | |
@Override | |
public CharSequence getTitle() { | |
return mActionView.getTitle(); | |
} | |
@Override | |
public CharSequence getSubtitle() { | |
return mActionView.getSubtitle(); | |
} | |
@Override | |
public int getNavigationMode() { | |
return mActionView.getNavigationMode(); | |
} | |
@Override | |
public void setNavigationMode(int mode) { | |
final int oldMode = mActionView.getNavigationMode(); | |
switch (oldMode) { | |
case NAVIGATION_MODE_TABS: | |
mSavedTabPosition = getSelectedNavigationIndex(); | |
selectTab(null); | |
mTabScrollView.setVisibility(View.GONE); | |
break; | |
} | |
mActionView.setNavigationMode(mode); | |
switch (mode) { | |
case NAVIGATION_MODE_TABS: | |
ensureTabsExist(); | |
mTabScrollView.setVisibility(View.VISIBLE); | |
if (mSavedTabPosition != INVALID_POSITION) { | |
setSelectedNavigationItem(mSavedTabPosition); | |
mSavedTabPosition = INVALID_POSITION; | |
} | |
break; | |
} | |
mActionView.setCollapsable(mode == NAVIGATION_MODE_TABS && !mHasEmbeddedTabs); | |
} | |
@Override | |
public int getDisplayOptions() { | |
return mActionView.getDisplayOptions(); | |
} | |
@Override | |
public Tab newTab() { | |
return new TabImpl(); | |
} | |
@Override | |
public void addTab(Tab tab) { | |
addTab(tab, mTabs.isEmpty()); | |
} | |
@Override | |
public void addTab(Tab tab, boolean setSelected) { | |
ensureTabsExist(); | |
mTabScrollView.addTab(tab, setSelected); | |
configureTab(tab, mTabs.size()); | |
if (setSelected) { | |
selectTab(tab); | |
} | |
} | |
@Override | |
public void addTab(Tab tab, int position) { | |
addTab(tab, position, mTabs.isEmpty()); | |
} | |
@Override | |
public void addTab(Tab tab, int position, boolean setSelected) { | |
ensureTabsExist(); | |
mTabScrollView.addTab(tab, position, setSelected); | |
configureTab(tab, position); | |
if (setSelected) { | |
selectTab(tab); | |
} | |
} | |
@Override | |
public void removeTab(Tab tab) { | |
removeTabAt(tab.getPosition()); | |
} | |
@Override | |
public void removeTabAt(int position) { | |
if (mTabScrollView == null) { | |
// No tabs around to remove | |
return; | |
} | |
int selectedTabPosition = mSelectedTab != null | |
? mSelectedTab.getPosition() : mSavedTabPosition; | |
mTabScrollView.removeTabAt(position); | |
TabImpl removedTab = mTabs.remove(position); | |
if (removedTab != null) { | |
removedTab.setPosition(-1); | |
} | |
final int newTabCount = mTabs.size(); | |
for (int i = position; i < newTabCount; i++) { | |
mTabs.get(i).setPosition(i); | |
} | |
if (selectedTabPosition == position) { | |
selectTab(mTabs.isEmpty() ? null : mTabs.get(Math.max(0, position - 1))); | |
} | |
} | |
@Override | |
public void removeAllTabs() { | |
cleanupTabs(); | |
} | |
@Override | |
public void selectTab(Tab tab) { | |
if (getNavigationMode() != NAVIGATION_MODE_TABS) { | |
mSavedTabPosition = tab != null ? tab.getPosition() : INVALID_POSITION; | |
return; | |
} | |
final FragmentTransaction trans = mActivity.getSupportFragmentManager().beginTransaction() | |
.disallowAddToBackStack(); | |
if (mSelectedTab == tab) { | |
if (mSelectedTab != null) { | |
mSelectedTab.getCallback().onTabReselected(mSelectedTab, trans); | |
mTabScrollView.animateToTab(tab.getPosition()); | |
} | |
} else { | |
mTabScrollView.setTabSelected(tab != null ? tab.getPosition() : Tab.INVALID_POSITION); | |
if (mSelectedTab != null) { | |
mSelectedTab.getCallback().onTabUnselected(mSelectedTab, trans); | |
} | |
mSelectedTab = (TabImpl) tab; | |
if (mSelectedTab != null) { | |
mSelectedTab.getCallback().onTabSelected(mSelectedTab, trans); | |
} | |
} | |
if (!trans.isEmpty()) { | |
trans.commit(); | |
} | |
} | |
@Override | |
public Tab getSelectedTab() { | |
return mSelectedTab; | |
} | |
@Override | |
public Tab getTabAt(int index) { | |
return mTabs.get(index); | |
} | |
@Override | |
public int getTabCount() { | |
return mTabs.size(); | |
} | |
@Override | |
public Context getThemedContext() { | |
if (mThemedContext == null) { | |
TypedValue outValue = new TypedValue(); | |
Resources.Theme currentTheme = mContext.getTheme(); | |
currentTheme.resolveAttribute(R.attr.actionBarWidgetTheme, outValue, true); | |
final int targetThemeRes = outValue.resourceId; | |
if (targetThemeRes != 0) { | |
mThemedContext = new ContextThemeWrapper(mContext, targetThemeRes); | |
} else { | |
mThemedContext = mContext; | |
} | |
} | |
return mThemedContext; | |
} | |
@Override | |
public int getHeight() { | |
return mContainerView.getHeight(); | |
} | |
@Override | |
public void show() { | |
if (mHiddenByApp) { | |
mHiddenByApp = false; | |
updateVisibility(false); | |
} | |
} | |
void showForActionMode() { | |
if (!mShowingForMode) { | |
mShowingForMode = true; | |
updateVisibility(false); | |
} | |
} | |
@Override | |
public void hide() { | |
if (!mHiddenByApp) { | |
mHiddenByApp = true; | |
updateVisibility(false); | |
} | |
} | |
void hideForActionMode() { | |
if (mShowingForMode) { | |
mShowingForMode = false; | |
updateVisibility(false); | |
} | |
} | |
@Override | |
public boolean isShowing() { | |
return mNowShowing; | |
} | |
@Override | |
public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { | |
mMenuVisibilityListeners.add(listener); | |
} | |
@Override | |
public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) { | |
mMenuVisibilityListeners.remove(listener); | |
} | |
public ActionMode startActionMode(ActionMode.Callback callback) { | |
if (mActionMode != null) { | |
mActionMode.finish(); | |
} | |
mContextView.killMode(); | |
ActionModeImpl mode = new ActionModeImpl(callback); | |
if (mode.dispatchOnCreate()) { | |
mode.invalidate(); | |
mContextView.initForMode(mode); | |
animateToMode(true); | |
if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) { | |
if (mSplitView.getVisibility() != View.VISIBLE) { | |
mSplitView.setVisibility(View.VISIBLE); | |
} | |
} | |
mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); | |
mActionMode = mode; | |
return mode; | |
} | |
return null; | |
} | |
void animateToMode(boolean toActionMode) { | |
if (toActionMode) { | |
showForActionMode(); | |
} else { | |
hideForActionMode(); | |
} | |
mActionView.animateToVisibility(toActionMode ? View.INVISIBLE : View.VISIBLE); | |
mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE); | |
if (mTabScrollView != null && !mActionView.hasEmbeddedTabs() && mActionView.isCollapsed()) { | |
mTabScrollView.setVisibility(toActionMode ? View.GONE : View.VISIBLE); | |
} | |
} | |
/** | |
* @hide | |
*/ | |
public class TabImpl extends Tab { | |
private TabListener mCallback; | |
private Object mTag; | |
private Drawable mIcon; | |
private CharSequence mText; | |
private CharSequence mContentDesc; | |
private int mPosition = -1; | |
private View mCustomView; | |
@Override | |
public Object getTag() { | |
return mTag; | |
} | |
@Override | |
public Tab setTag(Object tag) { | |
mTag = tag; | |
return this; | |
} | |
public TabListener getCallback() { | |
return mCallback; | |
} | |
@Override | |
public Tab setTabListener(TabListener callback) { | |
mCallback = callback; | |
return this; | |
} | |
@Override | |
public View getCustomView() { | |
return mCustomView; | |
} | |
@Override | |
public Tab setCustomView(View view) { | |
mCustomView = view; | |
if (mPosition >= 0) { | |
mTabScrollView.updateTab(mPosition); | |
} | |
return this; | |
} | |
@Override | |
public Tab setCustomView(int layoutResId) { | |
return setCustomView(LayoutInflater.from(getThemedContext()) | |
.inflate(layoutResId, null)); | |
} | |
@Override | |
public Drawable getIcon() { | |
return mIcon; | |
} | |
@Override | |
public int getPosition() { | |
return mPosition; | |
} | |
public void setPosition(int position) { | |
mPosition = position; | |
} | |
@Override | |
public CharSequence getText() { | |
return mText; | |
} | |
@Override | |
public Tab setIcon(Drawable icon) { | |
mIcon = icon; | |
if (mPosition >= 0) { | |
mTabScrollView.updateTab(mPosition); | |
} | |
return this; | |
} | |
@Override | |
public Tab setIcon(int resId) { | |
return setIcon(mContext.getResources().getDrawable(resId)); | |
} | |
@Override | |
public Tab setText(CharSequence text) { | |
mText = text; | |
if (mPosition >= 0) { | |
mTabScrollView.updateTab(mPosition); | |
} | |
return this; | |
} | |
@Override | |
public Tab setText(int resId) { | |
return setText(mContext.getResources().getText(resId)); | |
} | |
@Override | |
public void select() { | |
selectTab(this); | |
} | |
@Override | |
public Tab setContentDescription(int resId) { | |
return setContentDescription(mContext.getResources().getText(resId)); | |
} | |
@Override | |
public Tab setContentDescription(CharSequence contentDesc) { | |
mContentDesc = contentDesc; | |
if (mPosition >= 0) { | |
mTabScrollView.updateTab(mPosition); | |
} | |
return this; | |
} | |
@Override | |
public CharSequence getContentDescription() { | |
return mContentDesc; | |
} | |
} | |
class ActionModeImpl extends ActionMode implements MenuBuilder.Callback { | |
private Callback mCallback; | |
private MenuBuilder mMenu; | |
private WeakReference<View> mCustomView; | |
public ActionModeImpl(Callback callback) { | |
mCallback = callback; | |
mMenu = new MenuBuilder(getThemedContext()) | |
.setDefaultShowAsAction(SupportMenuItem.SHOW_AS_ACTION_IF_ROOM); | |
mMenu.setCallback(this); | |
} | |
@Override | |
public MenuInflater getMenuInflater() { | |
return new SupportMenuInflater(getThemedContext()); | |
} | |
@Override | |
public Menu getMenu() { | |
return mMenu; | |
} | |
@Override | |
public void finish() { | |
if (mActionMode != this) { | |
// Not the active action mode - no-op | |
return; | |
} | |
// If this change in state is going to cause the action bar | |
// to be hidden, defer the onDestroy callback until the animation | |
// is finished and associated relayout is about to happen. This lets | |
// apps better anticipate visibility and layout behavior. | |
if (!checkShowingFlags(mHiddenByApp, mHiddenBySystem, false)) { | |
// With the current state but the action bar hidden, our | |
// overall showing state is going to be false. | |
mDeferredDestroyActionMode = this; | |
mDeferredModeDestroyCallback = mCallback; | |
} else { | |
mCallback.onDestroyActionMode(this); | |
} | |
mCallback = null; | |
animateToMode(false); | |
// Clear out the context mode views after the animation finishes | |
mContextView.closeMode(); | |
mActionView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); | |
mActionMode = null; | |
} | |
@Override | |
public void invalidate() { | |
mMenu.stopDispatchingItemsChanged(); | |
try { | |
mCallback.onPrepareActionMode(this, mMenu); | |
} finally { | |
mMenu.startDispatchingItemsChanged(); | |
} | |
} | |
public boolean dispatchOnCreate() { | |
mMenu.stopDispatchingItemsChanged(); | |
try { | |
return mCallback.onCreateActionMode(this, mMenu); | |
} finally { | |
mMenu.startDispatchingItemsChanged(); | |
} | |
} | |
@Override | |
public void setCustomView(View view) { | |
mContextView.setCustomView(view); | |
mCustomView = new WeakReference<View>(view); | |
} | |
@Override | |
public void setSubtitle(CharSequence subtitle) { | |
mContextView.setSubtitle(subtitle); | |
} | |
@Override | |
public void setTitle(CharSequence title) { | |
mContextView.setTitle(title); | |
} | |
@Override | |
public void setTitle(int resId) { | |
setTitle(mContext.getResources().getString(resId)); | |
} | |
@Override | |
public void setSubtitle(int resId) { | |
setSubtitle(mContext.getResources().getString(resId)); | |
} | |
@Override | |
public CharSequence getTitle() { | |
return mContextView.getTitle(); | |
} | |
@Override | |
public CharSequence getSubtitle() { | |
return mContextView.getSubtitle(); | |
} | |
@Override | |
public void setTitleOptionalHint(boolean titleOptional) { | |
super.setTitleOptionalHint(titleOptional); | |
mContextView.setTitleOptional(titleOptional); | |
} | |
@Override | |
public boolean isTitleOptional() { | |
return mContextView.isTitleOptional(); | |
} | |
@Override | |
public View getCustomView() { | |
return mCustomView != null ? mCustomView.get() : null; | |
} | |
public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { | |
if (mCallback != null) { | |
return mCallback.onActionItemClicked(this, item); | |
} else { | |
return false; | |
} | |
} | |
@Override | |
public void onMenuModeChange(MenuBuilder menu) { | |
if (mCallback == null) { | |
return; | |
} | |
invalidate(); | |
mContextView.showOverflowMenu(); | |
} | |
public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { | |
} | |
public boolean onSubMenuSelected(SubMenuBuilder subMenu) { | |
if (mCallback == null) { | |
return false; | |
} | |
if (!subMenu.hasVisibleItems()) { | |
return true; | |
} | |
//new MenuPopupHelper(getThemedContext(), subMenu).show(); | |
return true; | |
} | |
public void onCloseSubMenu(SubMenuBuilder menu) { | |
} | |
public void onMenuModeChange(Menu menu) { | |
if (mCallback == null) { | |
return; | |
} | |
invalidate(); | |
mContextView.showOverflowMenu(); | |
} | |
} | |
private void ensureTabsExist() { | |
if (mTabScrollView != null) { | |
return; | |
} | |
ScrollingTabContainerView tabScroller = new ScrollingTabContainerView(mContext); | |
if (mHasEmbeddedTabs) { | |
tabScroller.setVisibility(View.VISIBLE); | |
mActionView.setEmbeddedTabView(tabScroller); | |
} else { | |
if (getNavigationMode() == NAVIGATION_MODE_TABS) { | |
tabScroller.setVisibility(View.VISIBLE); | |
} else { | |
tabScroller.setVisibility(View.GONE); | |
} | |
mContainerView.setTabContainer(tabScroller); | |
} | |
mTabScrollView = tabScroller; | |
} | |
private void configureTab(Tab tab, int position) { | |
final TabImpl tabi = (TabImpl) tab; | |
final TabListener callback = tabi.getCallback(); | |
if (callback == null) { | |
throw new IllegalStateException("Action Bar Tab must have a Callback"); | |
} | |
tabi.setPosition(position); | |
mTabs.add(position, tabi); | |
final int count = mTabs.size(); | |
for (int i = position + 1; i < count; i++) { | |
mTabs.get(i).setPosition(i); | |
} | |
} | |
private void cleanupTabs() { | |
if (mSelectedTab != null) { | |
selectTab(null); | |
} | |
mTabs.clear(); | |
if (mTabScrollView != null) { | |
mTabScrollView.removeAllTabs(); | |
} | |
mSavedTabPosition = INVALID_POSITION; | |
} | |
private static boolean checkShowingFlags(boolean hiddenByApp, boolean hiddenBySystem, | |
boolean showingForMode) { | |
if (showingForMode) { | |
return true; | |
} else if (hiddenByApp || hiddenBySystem) { | |
return false; | |
} else { | |
return true; | |
} | |
} | |
private void updateVisibility(boolean fromSystem) { | |
// Based on the current state, should we be hidden or shown? | |
final boolean shown = checkShowingFlags(mHiddenByApp, mHiddenBySystem, mShowingForMode); | |
if (shown) { | |
if (!mNowShowing) { | |
mNowShowing = true; | |
doShow(fromSystem); | |
} | |
} else { | |
if (mNowShowing) { | |
mNowShowing = false; | |
doHide(fromSystem); | |
} | |
} | |
} | |
public void setShowHideAnimationEnabled(boolean enabled) { | |
mShowHideAnimationEnabled = enabled; | |
if (!enabled) { | |
mTopVisibilityView.clearAnimation(); | |
if (mSplitView != null) { | |
mSplitView.clearAnimation(); | |
} | |
} | |
} | |
public void doShow(boolean fromSystem) { | |
mTopVisibilityView.clearAnimation(); | |
if (mTopVisibilityView.getVisibility() == View.VISIBLE) { | |
return; | |
} | |
final boolean animate = isShowHideAnimationEnabled() || fromSystem; | |
if (animate) { | |
Animation anim = AnimationUtils.loadAnimation(mContext, R.anim.abc_slide_in_top); | |
mTopVisibilityView.startAnimation(anim); | |
} | |
mTopVisibilityView.setVisibility(View.VISIBLE); | |
if (mSplitView != null && mSplitView.getVisibility() != View.VISIBLE) { | |
if (animate) { | |
Animation anim = AnimationUtils.loadAnimation(mContext, R.anim.abc_slide_in_bottom); | |
mSplitView.startAnimation(anim); | |
} | |
mSplitView.setVisibility(View.VISIBLE); | |
} | |
} | |
public void doHide(boolean fromSystem) { | |
mTopVisibilityView.clearAnimation(); | |
if (mTopVisibilityView.getVisibility() == View.GONE) { | |
return; | |
} | |
final boolean animate = isShowHideAnimationEnabled() || fromSystem; | |
if (animate) { | |
Animation anim = AnimationUtils.loadAnimation(mContext, R.anim.abc_slide_out_top); | |
mTopVisibilityView.startAnimation(anim); | |
} | |
mTopVisibilityView.setVisibility(View.GONE); | |
if (mSplitView != null && mSplitView.getVisibility() != View.GONE) { | |
if (animate) { | |
Animation anim = AnimationUtils | |
.loadAnimation(mContext, R.anim.abc_slide_out_bottom); | |
mSplitView.startAnimation(anim); | |
} | |
mSplitView.setVisibility(View.GONE); | |
} | |
} | |
boolean isShowHideAnimationEnabled() { | |
return mShowHideAnimationEnabled; | |
} | |
} |
/* | |
* Copyright (C) 2013 The Android Open Source Project | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package android.support.v7.app; | |
import android.support.v7.appcompat.R; | |
import android.annotation.TargetApi; | |
import android.os.Build; | |
import android.support.v7.internal.widget.NativeActionModeAwareLayout; | |
import android.view.ActionMode; | |
import android.view.Menu; | |
import android.view.MenuItem; | |
@TargetApi(Build.VERSION_CODES.HONEYCOMB) | |
class ActionBarImplCompatHC extends ActionBarImplCompatBase | |
implements NativeActionModeAwareLayout.OnActionModeForChildListener { | |
final NativeActionModeAwareLayout mNativeActionModeAwareLayout; | |
private ActionMode mCurActionMode; | |
public ActionBarImplCompatHC(ActionBarPreferenceActivity activity, Callback callback) { | |
super(activity, callback); | |
// NativeActionModeAwareLayout is used to notify us whena native Action Mode is started | |
mNativeActionModeAwareLayout = (NativeActionModeAwareLayout) activity | |
.findViewById(R.id.action_bar_root); | |
// Can be null when using FEATURE_ACTION_BAR_OVERLAY | |
if (mNativeActionModeAwareLayout != null) { | |
mNativeActionModeAwareLayout.setActionModeForChildListener(this); | |
} | |
} | |
// From NativeActionModeAwareLayout.OnActionModeForChildListener | |
@Override | |
public ActionMode.Callback onActionModeForChild(ActionMode.Callback callback) { | |
return new CallbackWrapper(callback); | |
} | |
@Override | |
public void show() { | |
super.show(); | |
if (mCurActionMode != null) { | |
mCurActionMode.finish(); | |
} | |
} | |
@Override | |
public void hide() { | |
super.hide(); | |
if (mCurActionMode != null) { | |
mCurActionMode.finish(); | |
} | |
} | |
@Override | |
boolean isShowHideAnimationEnabled() { | |
// Only allow animation if we're not currently showing an action mode | |
return mCurActionMode == null && super.isShowHideAnimationEnabled(); | |
} | |
private class CallbackWrapper implements ActionMode.Callback { | |
private final ActionMode.Callback mWrappedCallback; | |
CallbackWrapper(ActionMode.Callback callback) { | |
mWrappedCallback = callback; | |
} | |
@Override | |
public boolean onCreateActionMode(ActionMode mode, Menu menu) { | |
final boolean wrappedResult = mWrappedCallback.onCreateActionMode(mode, menu); | |
if (wrappedResult) { | |
// Keep reference to action mode | |
mCurActionMode = mode; | |
// Make sure that the compat Action Bar is shown | |
showForActionMode(); | |
} | |
return wrappedResult; | |
} | |
@Override | |
public boolean onPrepareActionMode(ActionMode mode, Menu menu) { | |
return mWrappedCallback.onPrepareActionMode(mode, menu); | |
} | |
@Override | |
public boolean onActionItemClicked(ActionMode mode, MenuItem item) { | |
return mWrappedCallback.onActionItemClicked(mode, item); | |
} | |
@Override | |
public void onDestroyActionMode(ActionMode mode) { | |
mWrappedCallback.onDestroyActionMode(mode); | |
// We previously shown the Action Bar for positioning purposes, now hide it again | |
hideForActionMode(); | |
// Remove any reference to the mode | |
mCurActionMode = null; | |
} | |
} | |
} |
/* | |
* Copyright (C) 2012 The Android Open Source Project | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package android.support.v7.app; | |
import java.lang.ref.WeakReference; | |
import java.util.ArrayList; | |
import android.annotation.TargetApi; | |
import android.app.Activity; | |
import android.content.Context; | |
import android.graphics.drawable.Drawable; | |
import android.os.Build; | |
import android.support.v4.app.FragmentTransaction; | |
import android.view.View; | |
import android.widget.SpinnerAdapter; | |
@TargetApi(Build.VERSION_CODES.HONEYCOMB) | |
class ActionBarImplCompatICS extends ActionBar { | |
final Activity mActivity; | |
final Callback mCallback; | |
final android.app.ActionBar mActionBar; | |
private ArrayList<WeakReference<OnMenuVisibilityListenerWrapper>> mAddedMenuVisWrappers = | |
new ArrayList<WeakReference<OnMenuVisibilityListenerWrapper>>(); | |
public ActionBarImplCompatICS(Activity activity, Callback callback) { | |
mActivity = activity; | |
mCallback = callback; | |
mActionBar = activity.getActionBar(); | |
} | |
private OnMenuVisibilityListenerWrapper findAndRemoveMenuVisWrapper( | |
OnMenuVisibilityListener compatListener) { | |
for (int i = 0; i < mAddedMenuVisWrappers.size(); i++) { | |
OnMenuVisibilityListenerWrapper wrapper = mAddedMenuVisWrappers.get(i).get(); | |
if (wrapper == null) { | |
mAddedMenuVisWrappers.remove(i--); | |
} else if (wrapper.mWrappedListener == compatListener) { | |
mAddedMenuVisWrappers.remove(i); | |
return wrapper; | |
} | |
} | |
return null; | |
} | |
@Override | |
public void setCustomView(View view) { | |
mActionBar.setCustomView(view); | |
} | |
@Override | |
public void setCustomView(View view, LayoutParams layoutParams) { | |
android.app.ActionBar.LayoutParams lp = | |
new android.app.ActionBar.LayoutParams(layoutParams); | |
lp.gravity = layoutParams.gravity; | |
mActionBar.setCustomView(view, lp); | |
} | |
@Override | |
public void setCustomView(int resId) { | |
mActionBar.setCustomView(resId); | |
} | |
@Override | |
public void setIcon(int resId) { | |
mActionBar.setIcon(resId); | |
} | |
@Override | |
public void setIcon(Drawable icon) { | |
mActionBar.setIcon(icon); | |
} | |
@Override | |
public void setLogo(int resId) { | |
mActionBar.setLogo(resId); | |
} | |
@Override | |
public void setLogo(Drawable logo) { | |
mActionBar.setLogo(logo); | |
} | |
@Override | |
public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) { | |
mActionBar.setListNavigationCallbacks(adapter, | |
callback != null ? new OnNavigationListenerWrapper(callback) : null); | |
} | |
@Override | |
public void setSelectedNavigationItem(int position) { | |
mActionBar.setSelectedNavigationItem(position); | |
} | |
@Override | |
public int getSelectedNavigationIndex() { | |
return mActionBar.getSelectedNavigationIndex(); | |
} | |
@Override | |
public int getNavigationItemCount() { | |
return mActionBar.getNavigationItemCount(); | |
} | |
@Override | |
public void setTitle(CharSequence title) { | |
mActionBar.setTitle(title); | |
} | |
@Override | |
public void setTitle(int resId) { | |
mActionBar.setTitle(resId); | |
} | |
@Override | |
public void setSubtitle(CharSequence subtitle) { | |
mActionBar.setSubtitle(subtitle); | |
} | |
@Override | |
public void setSubtitle(int resId) { | |
mActionBar.setSubtitle(resId); | |
} | |
@Override | |
public void setDisplayOptions(int options) { | |
mActionBar.setDisplayOptions(options); | |
} | |
@Override | |
public void setDisplayOptions(int options, int mask) { | |
mActionBar.setDisplayOptions(options, mask); | |
} | |
@Override | |
public void setDisplayUseLogoEnabled(boolean useLogo) { | |
mActionBar.setDisplayUseLogoEnabled(useLogo); | |
} | |
@Override | |
public void setDisplayShowHomeEnabled(boolean showHome) { | |
mActionBar.setDisplayShowHomeEnabled(showHome); | |
} | |
@Override | |
public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) { | |
mActionBar.setDisplayHomeAsUpEnabled(showHomeAsUp); | |
} | |
@Override | |
public void setDisplayShowTitleEnabled(boolean showTitle) { | |
mActionBar.setDisplayShowTitleEnabled(showTitle); | |
} | |
@Override | |
public void setDisplayShowCustomEnabled(boolean showCustom) { | |
mActionBar.setDisplayShowCustomEnabled(showCustom); | |
} | |
@Override | |
public void setBackgroundDrawable(Drawable d) { | |
mActionBar.setBackgroundDrawable(d); | |
} | |
@Override | |
public View getCustomView() { | |
return mActionBar.getCustomView(); | |
} | |
@Override | |
public CharSequence getTitle() { | |
return mActionBar.getTitle(); | |
} | |
@Override | |
public CharSequence getSubtitle() { | |
return mActionBar.getSubtitle(); | |
} | |
@Override | |
public int getNavigationMode() { | |
return mActionBar.getNavigationMode(); | |
} | |
@Override | |
public void setNavigationMode(int mode) { | |
mActionBar.setNavigationMode(mode); | |
} | |
@Override | |
public int getDisplayOptions() { | |
return mActionBar.getDisplayOptions(); | |
} | |
@Override | |
public Tab newTab() { | |
final android.app.ActionBar.Tab realTab = mActionBar.newTab(); | |
final TabWrapper result = new TabWrapper(realTab); | |
realTab.setTag(result); | |
return result; | |
} | |
@Override | |
public void addTab(Tab tab) { | |
mActionBar.addTab(((TabWrapper) tab).mWrappedTab); | |
} | |
@Override | |
public void addTab(Tab tab, boolean setSelected) { | |
mActionBar.addTab(((TabWrapper) tab).mWrappedTab, setSelected); | |
} | |
@Override | |
public void addTab(Tab tab, int position) { | |
mActionBar.addTab(((TabWrapper) tab).mWrappedTab, position); | |
} | |
@Override | |
public void addTab(Tab tab, int position, boolean setSelected) { | |
mActionBar.addTab(((TabWrapper) tab).mWrappedTab, position, setSelected); | |
} | |
@Override | |
public void removeTab(Tab tab) { | |
mActionBar.removeTab(((TabWrapper) tab).mWrappedTab); | |
} | |
@Override | |
public void removeTabAt(int position) { | |
mActionBar.removeTabAt(position); | |
} | |
@Override | |
public void removeAllTabs() { | |
mActionBar.removeAllTabs(); | |
} | |
@Override | |
public void selectTab(Tab tab) { | |
mActionBar.selectTab(((TabWrapper) tab).mWrappedTab); | |
} | |
@Override | |
public Tab getSelectedTab() { | |
return (Tab) mActionBar.getSelectedTab().getTag(); | |
} | |
@Override | |
public Tab getTabAt(int index) { | |
return (Tab) mActionBar.getTabAt(index).getTag(); | |
} | |
@Override | |
public int getTabCount() { | |
return mActionBar.getTabCount(); | |
} | |
@Override | |
public Context getThemedContext() { | |
return mActionBar.getThemedContext(); | |
} | |
@Override | |
public int getHeight() { | |
return mActionBar.getHeight(); | |
} | |
@Override | |
public void show() { | |
mActionBar.show(); | |
} | |
@Override | |
public void hide() { | |
mActionBar.hide(); | |
} | |
@Override | |
public boolean isShowing() { | |
return mActionBar.isShowing(); | |
} | |
@Override | |
public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { | |
if (listener != null) { | |
OnMenuVisibilityListenerWrapper w = new OnMenuVisibilityListenerWrapper(listener); | |
mAddedMenuVisWrappers.add(new WeakReference<OnMenuVisibilityListenerWrapper>(w)); | |
mActionBar.addOnMenuVisibilityListener(w); | |
} | |
} | |
@Override | |
public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) { | |
OnMenuVisibilityListenerWrapper l = findAndRemoveMenuVisWrapper(listener); | |
mActionBar.removeOnMenuVisibilityListener(l); | |
} | |
static class OnNavigationListenerWrapper implements android.app.ActionBar.OnNavigationListener { | |
private final OnNavigationListener mWrappedListener; | |
public OnNavigationListenerWrapper(OnNavigationListener l) { | |
mWrappedListener = l; | |
} | |
@Override | |
public boolean onNavigationItemSelected(int itemPosition, long itemId) { | |
return mWrappedListener.onNavigationItemSelected(itemPosition, itemId); | |
} | |
} | |
static class OnMenuVisibilityListenerWrapper implements | |
android.app.ActionBar.OnMenuVisibilityListener { | |
final OnMenuVisibilityListener mWrappedListener; | |
public OnMenuVisibilityListenerWrapper(OnMenuVisibilityListener l) { | |
mWrappedListener = l; | |
} | |
@Override | |
public void onMenuVisibilityChanged(boolean isVisible) { | |
mWrappedListener.onMenuVisibilityChanged(isVisible); | |
} | |
} | |
class TabWrapper extends Tab implements android.app.ActionBar.TabListener { | |
final android.app.ActionBar.Tab mWrappedTab; | |
private Object mTag; | |
private FragmentTransaction mActiveTransaction; | |
private CharSequence mContentDescription; | |
private TabListener mTabListener; | |
public TabWrapper(android.app.ActionBar.Tab tab) { | |
mWrappedTab = tab; | |
} | |
@Override | |
public int getPosition() { | |
return mWrappedTab.getPosition(); | |
} | |
@Override | |
public Drawable getIcon() { | |
return mWrappedTab.getIcon(); | |
} | |
@Override | |
public CharSequence getText() { | |
return mWrappedTab.getText(); | |
} | |
@Override | |
public Tab setIcon(Drawable icon) { | |
mWrappedTab.setIcon(icon); | |
return this; | |
} | |
@Override | |
public Tab setIcon(int resId) { | |
mWrappedTab.setIcon(resId); | |
return this; | |
} | |
@Override | |
public Tab setText(CharSequence text) { | |
mWrappedTab.setText(text); | |
return this; | |
} | |
@Override | |
public Tab setText(int resId) { | |
mWrappedTab.setText(resId); | |
return this; | |
} | |
@Override | |
public Tab setCustomView(View view) { | |
mWrappedTab.setCustomView(view); | |
return this; | |
} | |
@Override | |
public Tab setCustomView(int layoutResId) { | |
mWrappedTab.setCustomView(layoutResId); | |
return this; | |
} | |
@Override | |
public View getCustomView() { | |
return mWrappedTab.getCustomView(); | |
} | |
@Override | |
public Tab setTag(Object obj) { | |
mTag = obj; | |
return this; | |
} | |
@Override | |
public Object getTag() { | |
return mTag; | |
} | |
@Override | |
public Tab setTabListener(TabListener listener) { | |
mTabListener = listener; | |
mWrappedTab.setTabListener(listener != null ? this : null); | |
return this; | |
} | |
@Override | |
public void select() { | |
mWrappedTab.select(); | |
} | |
@Override | |
public Tab setContentDescription(int resId) { | |
mContentDescription = mActivity.getText(resId); | |
return this; | |
} | |
@Override | |
public Tab setContentDescription(CharSequence contentDesc) { | |
mContentDescription = contentDesc; | |
return this; | |
} | |
@Override | |
public CharSequence getContentDescription() { | |
return mContentDescription; | |
} | |
@Override | |
public void onTabSelected(android.app.ActionBar.Tab tab, | |
android.app.FragmentTransaction ft) { | |
mTabListener.onTabSelected(this, ft != null ? getActiveTransaction() : null); | |
commitActiveTransaction(); | |
} | |
@Override | |
public void onTabUnselected(android.app.ActionBar.Tab tab, | |
android.app.FragmentTransaction ft) { | |
mTabListener.onTabUnselected(this, ft != null ? getActiveTransaction() : null); | |
} | |
@Override | |
public void onTabReselected(android.app.ActionBar.Tab tab, | |
android.app.FragmentTransaction ft) { | |
mTabListener.onTabReselected(this, ft != null ? getActiveTransaction() : null); | |
commitActiveTransaction(); | |
} | |
private FragmentTransaction getActiveTransaction() { | |
if (mActiveTransaction == null) { | |
mActiveTransaction = mCallback.getSupportFragmentManager().beginTransaction() | |
.disallowAddToBackStack(); | |
} | |
return mActiveTransaction; | |
} | |
private void commitActiveTransaction() { | |
if (mActiveTransaction != null && !mActiveTransaction.isEmpty()) { | |
mActiveTransaction.commit(); | |
} | |
mActiveTransaction = null; | |
} | |
} | |
} |
package android.support.v7.app; | |
import android.annotation.SuppressLint; | |
import android.content.Intent; | |
import android.content.res.Configuration; | |
import android.os.Build; | |
import android.os.Bundle; | |
import android.preference.PreferenceActivity; | |
import android.support.v4.app.ActionBarDrawerToggle; | |
import android.support.v4.app.ActivityCompat; | |
import android.support.v4.app.FragmentManager; | |
import android.support.v4.app.NavUtils; | |
import android.support.v4.app.TaskStackBuilder; | |
import android.support.v7.view.ActionMode; | |
import android.view.Menu; | |
import android.view.MenuInflater; | |
import android.view.MenuItem; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.view.Window; | |
public class ActionBarPreferenceActivity extends PreferenceActivity implements ActionBar.Callback, | |
TaskStackBuilder.SupportParentable, ActionBarDrawerToggle.DelegateProvider { | |
ActionBarActivityDelegateCompat mImpl; | |
/** | |
* Support library version of {@link android.app.Activity#getActionBar}. | |
* | |
* <p>Retrieve a reference to this activity's ActionBar. | |
* | |
* @return The Activity's ActionBar, or null if it does not have one. | |
*/ | |
public ActionBar getSupportActionBar() { | |
return mImpl.getSupportActionBar(); | |
} | |
@Override | |
public MenuInflater getMenuInflater() { | |
return mImpl.getMenuInflater(); | |
} | |
@Override | |
public void setContentView(int layoutResID) { | |
mImpl.setContentView(layoutResID); | |
} | |
@Override | |
public void setContentView(View view) { | |
mImpl.setContentView(view); | |
} | |
@Override | |
public void setContentView(View view, ViewGroup.LayoutParams params) { | |
mImpl.setContentView(view, params); | |
} | |
@Override | |
public void addContentView(View view, ViewGroup.LayoutParams params) { | |
mImpl.addContentView(view, params); | |
} | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
mImpl = ActionBarActivityDelegateCompat.createDelegate(this); | |
super.onCreate(savedInstanceState); | |
mImpl.onCreate(savedInstanceState); | |
} | |
@Override | |
public void onConfigurationChanged(Configuration newConfig) { | |
super.onConfigurationChanged(newConfig); | |
mImpl.onConfigurationChanged(newConfig); | |
} | |
@Override | |
protected void onStop() { | |
super.onStop(); | |
mImpl.onStop(); | |
} | |
@Override | |
protected void onPostResume() { | |
super.onPostResume(); | |
mImpl.onPostResume(); | |
} | |
@Override | |
public View onCreatePanelView(int featureId) { | |
if (featureId == Window.FEATURE_OPTIONS_PANEL) { | |
return mImpl.onCreatePanelView(featureId); | |
} else { | |
return super.onCreatePanelView(featureId); | |
} | |
} | |
@Override | |
public final boolean onMenuItemSelected(int featureId, MenuItem item) { | |
if (mImpl.onMenuItemSelected(featureId, item)) { | |
return true; | |
} | |
final ActionBar ab = getSupportActionBar(); | |
if (item.getItemId() == android.R.id.home && ab != null && | |
(ab.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0) { | |
return onSupportNavigateUp(); | |
} | |
return false; | |
} | |
@Override | |
protected void onTitleChanged(CharSequence title, int color) { | |
super.onTitleChanged(title, color); | |
mImpl.setTitle(title); | |
} | |
/** | |
* Enable extended support library window features. | |
* <p> | |
* This is a convenience for calling | |
* {@link android.view.Window#requestFeature getWindow().requestFeature()}. | |
* </p> | |
* | |
* @param featureId The desired feature as defined in | |
* {@link android.view.Window} or {@link android.support.v4.view.WindowCompat}. | |
* @return Returns true if the requested feature is supported and now enabled. | |
* | |
* @see android.app.Activity#requestWindowFeature | |
* @see android.view.Window#requestFeature | |
*/ | |
public boolean supportRequestWindowFeature(int featureId) { | |
return mImpl.supportRequestWindowFeature(featureId); | |
} | |
@SuppressLint("NewApi") | |
@Override | |
public void invalidateOptionsMenu() { | |
// Only call up to super on ICS+ | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { | |
super.invalidateOptionsMenu(); | |
} | |
mImpl.supportInvalidateOptionsMenu(); | |
} | |
/** | |
* Notifies the Activity that a support action mode has been started. | |
* Activity subclasses overriding this method should call the superclass implementation. | |
* | |
* @param mode The new action mode. | |
*/ | |
public void onSupportActionModeStarted(ActionMode mode) { | |
} | |
/** | |
* Notifies the activity that a support action mode has finished. | |
* Activity subclasses overriding this method should call the superclass implementation. | |
* | |
* @param mode The action mode that just finished. | |
*/ | |
public void onSupportActionModeFinished(ActionMode mode) { | |
} | |
public ActionMode startSupportActionMode(ActionMode.Callback callback) { | |
return mImpl.startSupportActionMode(callback); | |
} | |
@Override | |
public boolean onCreatePanelMenu(int featureId, Menu menu) { | |
return mImpl.onCreatePanelMenu(featureId, menu); | |
} | |
@Override | |
public boolean onPreparePanel(int featureId, View view, Menu menu) { | |
return mImpl.onPreparePanel(featureId, view, menu); | |
} | |
void superSetContentView(int resId) { | |
super.setContentView(resId); | |
} | |
void superSetContentView(View v) { | |
super.setContentView(v); | |
} | |
void superSetContentView(View v, ViewGroup.LayoutParams lp) { | |
super.setContentView(v, lp); | |
} | |
void superAddContentView(View v, ViewGroup.LayoutParams lp) { | |
super.addContentView(v, lp); | |
} | |
boolean superOnCreatePanelMenu(int featureId, Menu frameworkMenu) { | |
return super.onCreatePanelMenu(featureId, frameworkMenu); | |
} | |
boolean superOnPreparePanel(int featureId, View view, Menu menu) { | |
return super.onPreparePanel(featureId, view, menu); | |
} | |
boolean superOnMenuItemSelected(int featureId, MenuItem menuItem) { | |
return super.onMenuItemSelected(featureId, menuItem); | |
} | |
@Override | |
public void onBackPressed() { | |
if (!mImpl.onBackPressed()) { | |
super.onBackPressed(); | |
} | |
} | |
/** | |
* Support library version of {@link android.app.Activity#setProgressBarVisibility(boolean)} | |
* <p> | |
* Sets the visibility of the progress bar in the title. | |
* <p> | |
* In order for the progress bar to be shown, the feature must be requested | |
* via {@link #supportRequestWindowFeature(int)}. | |
* | |
* @param visible Whether to show the progress bars in the title. | |
*/ | |
public void setSupportProgressBarVisibility(boolean visible) { | |
mImpl.setSupportProgressBarVisibility(visible); | |
} | |
/** | |
* Support library version of {@link android.app.Activity#setProgressBarIndeterminateVisibility(boolean)} | |
* <p> | |
* Sets the visibility of the indeterminate progress bar in the title. | |
* <p> | |
* In order for the progress bar to be shown, the feature must be requested | |
* via {@link #supportRequestWindowFeature(int)}. | |
* | |
* @param visible Whether to show the progress bars in the title. | |
*/ | |
public void setSupportProgressBarIndeterminateVisibility(boolean visible) { | |
mImpl.setSupportProgressBarIndeterminateVisibility(visible); | |
} | |
/** | |
* Support library version of {@link android.app.Activity#setProgressBarIndeterminate(boolean)} | |
* <p> | |
* Sets whether the horizontal progress bar in the title should be indeterminate (the | |
* circular is always indeterminate). | |
* <p> | |
* In order for the progress bar to be shown, the feature must be requested | |
* via {@link #supportRequestWindowFeature(int)}. | |
* | |
* @param indeterminate Whether the horizontal progress bar should be indeterminate. | |
*/ | |
public void setSupportProgressBarIndeterminate(boolean indeterminate) { | |
mImpl.setSupportProgressBarIndeterminate(indeterminate); | |
} | |
/** | |
* Support library version of {@link android.app.Activity#setProgress(int)}. | |
* <p> | |
* Sets the progress for the progress bars in the title. | |
* <p> | |
* In order for the progress bar to be shown, the feature must be requested | |
* via {@link #supportRequestWindowFeature(int)}. | |
* | |
* @param progress The progress for the progress bar. Valid ranges are from | |
* 0 to 10000 (both inclusive). If 10000 is given, the progress | |
* bar will be completely filled and will fade out. | |
*/ | |
public void setSupportProgress(int progress) { | |
mImpl.setSupportProgress(progress); | |
} | |
/** | |
* Support version of {@link #onCreateNavigateUpTaskStack(android.app.TaskStackBuilder)}. | |
* This method will be called on all platform versions. | |
* | |
* Define the synthetic task stack that will be generated during Up navigation from | |
* a different task. | |
* | |
* <p>The default implementation of this method adds the parent chain of this activity | |
* as specified in the manifest to the supplied {@link android.support.v4.app.TaskStackBuilder}. Applications | |
* may choose to override this method to construct the desired task stack in a different | |
* way.</p> | |
* | |
* <p>This method will be invoked by the default implementation of {@link #onNavigateUp()} | |
* if {@link #shouldUpRecreateTask(android.content.Intent)} returns true when supplied with the intent | |
* returned by {@link #getParentActivityIntent()}.</p> | |
* | |
* <p>Applications that wish to supply extra Intent parameters to the parent stack defined | |
* by the manifest should override | |
* {@link #onPrepareSupportNavigateUpTaskStack(android.support.v4.app.TaskStackBuilder)}.</p> | |
* | |
* @param builder An empty TaskStackBuilder - the application should add intents representing | |
* the desired task stack | |
*/ | |
public void onCreateSupportNavigateUpTaskStack(TaskStackBuilder builder) { | |
builder.addParentStack(this); | |
} | |
/** | |
* Support version of {@link #onPrepareNavigateUpTaskStack(android.app.TaskStackBuilder)}. | |
* This method will be called on all platform versions. | |
* | |
* Prepare the synthetic task stack that will be generated during Up navigation | |
* from a different task. | |
* | |
* <p>This method receives the {@link android.support.v4.app.TaskStackBuilder} with the constructed series of | |
* Intents as generated by {@link #onCreateSupportNavigateUpTaskStack(android.support.v4.app.TaskStackBuilder)}. | |
* If any extra data should be added to these intents before launching the new task, | |
* the application should override this method and add that data here.</p> | |
* | |
* @param builder A TaskStackBuilder that has been populated with Intents by | |
* onCreateNavigateUpTaskStack. | |
*/ | |
public void onPrepareSupportNavigateUpTaskStack(TaskStackBuilder builder) { | |
} | |
/** | |
* This method is called whenever the user chooses to navigate Up within your application's | |
* activity hierarchy from the action bar. | |
* | |
* <p>If a parent was specified in the manifest for this activity or an activity-alias to it, | |
* default Up navigation will be handled automatically. See | |
* {@link #getSupportParentActivityIntent()} for how to specify the parent. If any activity | |
* along the parent chain requires extra Intent arguments, the Activity subclass | |
* should override the method {@link #onPrepareSupportNavigateUpTaskStack(android.support.v4.app.TaskStackBuilder)} | |
* to supply those arguments.</p> | |
* | |
* <p>See <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and | |
* Back Stack</a> from the developer guide and | |
* <a href="{@docRoot}design/patterns/navigation.html">Navigation</a> from the design guide | |
* for more information about navigating within your app.</p> | |
* | |
* <p>See the {@link android.support.v4.app.TaskStackBuilder} class and the Activity methods | |
* {@link #getSupportParentActivityIntent()}, {@link #supportShouldUpRecreateTask(android.content.Intent)}, and | |
* {@link #supportNavigateUpTo(android.content.Intent)} for help implementing custom Up navigation.</p> | |
* | |
* @return true if Up navigation completed successfully and this Activity was finished, | |
* false otherwise. | |
*/ | |
public boolean onSupportNavigateUp() { | |
Intent upIntent = getSupportParentActivityIntent(); | |
if (upIntent != null) { | |
if (supportShouldUpRecreateTask(upIntent)) { | |
TaskStackBuilder b = TaskStackBuilder.create(this); | |
onCreateSupportNavigateUpTaskStack(b); | |
onPrepareSupportNavigateUpTaskStack(b); | |
b.startActivities(); | |
try { | |
ActivityCompat.finishAffinity(this); | |
} catch (IllegalStateException e) { | |
// This can only happen on 4.1+, when we don't have a parent or a result set. | |
// In that case we should just finish(). | |
finish(); | |
} | |
} else { | |
// This activity is part of the application's task, so simply | |
// navigate up to the hierarchical parent activity. | |
supportNavigateUpTo(upIntent); | |
} | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Obtain an {@link android.content.Intent} that will launch an explicit target activity | |
* specified by sourceActivity's {@link android.support.v4.app.NavUtils#PARENT_ACTIVITY} <meta-data> | |
* element in the application's manifest. If the device is running | |
* Jellybean or newer, the android:parentActivityName attribute will be preferred | |
* if it is present. | |
* | |
* @return a new Intent targeting the defined parent activity of sourceActivity | |
*/ | |
public Intent getSupportParentActivityIntent() { | |
return NavUtils.getParentActivityIntent(this); | |
} | |
/** | |
* Returns true if sourceActivity should recreate the task when navigating 'up' | |
* by using targetIntent. | |
* | |
* <p>If this method returns false the app can trivially call | |
* {@link #supportNavigateUpTo(android.content.Intent)} using the same parameters to correctly perform | |
* up navigation. If this method returns false, the app should synthesize a new task stack | |
* by using {@link android.support.v4.app.TaskStackBuilder} or another similar mechanism to perform up navigation.</p> | |
* | |
* @param targetIntent An intent representing the target destination for up navigation | |
* @return true if navigating up should recreate a new task stack, false if the same task | |
* should be used for the destination | |
*/ | |
public boolean supportShouldUpRecreateTask(Intent targetIntent) { | |
return NavUtils.shouldUpRecreateTask(this, targetIntent); | |
} | |
/** | |
* Navigate from sourceActivity to the activity specified by upIntent, finishing sourceActivity | |
* in the process. upIntent will have the flag {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TOP} set | |
* by this method, along with any others required for proper up navigation as outlined | |
* in the Android Design Guide. | |
* | |
* <p>This method should be used when performing up navigation from within the same task | |
* as the destination. If up navigation should cross tasks in some cases, see | |
* {@link #supportShouldUpRecreateTask(android.content.Intent)}.</p> | |
* | |
* @param upIntent An intent representing the target destination for up navigation | |
*/ | |
public void supportNavigateUpTo(Intent upIntent) { | |
NavUtils.navigateUpTo(this, upIntent); | |
} | |
@Override | |
public final ActionBarDrawerToggle.Delegate getDrawerToggleDelegate() { | |
return mImpl.getDrawerToggleDelegate(); | |
} | |
@Override | |
public FragmentManager getSupportFragmentManager() { | |
new UnsupportedOperationException("not allowed in PreferenceActivity()").printStackTrace(); | |
return null; | |
} | |
} |
I've done a modification and pushed, it might work for pre4.0.
I'm trying to use this, with the following things in my build.gradle:
compileSdkVersion 21
// compileSdkVersion "Google Inc.:Google APIs:21"
buildToolsVersion '21.0.0'
defaultConfig {
minSdkVersion 11
targetSdkVersion 21
dependencies {
compile 'com.android.support:support-v4:21.0.0'
compile 'com.android.support:appcompat-v7:21.0.0'
However unfortunatelly something seems to be changed in API 21, because in ActionBarActivityDelegateCompatBase I get dozens of errors, like:
it can't import android.support.v7.internal.widget.ActionBarView and android.support.v7.internal.widget.ProgressBarICS, and 1/3 of the lines are red in Android Studio. Do you have any idea how to fix this?
For the record: I managed to compile it with the following settings:
compileSdkVersion "Google Inc.:Google APIs:19"
buildToolsVersion '19.1.0'
defaultConfig {
minSdkVersion 11
targetSdkVersion 19
dependencies {
compile 'com.android.support:support-v4:20.0.0'
compile 'com.android.support:appcompat-v7:20.0.0'
Though still would be nice to be able to use the latest (21) versions
Have you made any modification?
Does this work?