diff options
Diffstat (limited to 'core/java/com')
5 files changed, 226 insertions, 55 deletions
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java index 20d209f..9dabb4e 100644 --- a/core/java/com/android/internal/app/AlertController.java +++ b/core/java/com/android/internal/app/AlertController.java @@ -20,6 +20,7 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import com.android.internal.R; +import android.annotation.Nullable; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; @@ -38,7 +39,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewParent; -import android.view.ViewTreeObserver; +import android.view.ViewStub; import android.view.Window; import android.view.WindowInsets; import android.view.WindowManager; @@ -450,27 +451,107 @@ public class AlertController { } } + /** + * Resolves whether a custom or default panel should be used. Removes the + * default panel if a custom panel should be used. If the resolved panel is + * a view stub, inflates before returning. + * + * @param customPanel the custom panel + * @param defaultPanel the default panel + * @return the panel to use + */ + @Nullable + private ViewGroup resolvePanel(@Nullable View customPanel, @Nullable View defaultPanel) { + if (customPanel == null) { + // Inflate the default panel, if needed. + if (defaultPanel instanceof ViewStub) { + defaultPanel = ((ViewStub) defaultPanel).inflate(); + } + + return (ViewGroup) defaultPanel; + } + + // Remove the default panel entirely. + if (defaultPanel != null) { + final ViewParent parent = defaultPanel.getParent(); + if (parent instanceof ViewGroup) { + ((ViewGroup) parent).removeView(defaultPanel); + } + } + + // Inflate the custom panel, if needed. + if (customPanel instanceof ViewStub) { + customPanel = ((ViewStub) customPanel).inflate(); + } + + return (ViewGroup) customPanel; + } + private void setupView() { - final ViewGroup contentPanel = (ViewGroup) mWindow.findViewById(R.id.contentPanel); - setupContent(contentPanel); - final boolean hasButtons = setupButtons(); + final View parentPanel = mWindow.findViewById(R.id.parentPanel); + final View defaultTopPanel = parentPanel.findViewById(R.id.topPanel); + final View defaultContentPanel = parentPanel.findViewById(R.id.contentPanel); + final View defaultButtonPanel = parentPanel.findViewById(R.id.buttonPanel); - final ViewGroup topPanel = (ViewGroup) mWindow.findViewById(R.id.topPanel); - final TypedArray a = mContext.obtainStyledAttributes( - null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0); - final boolean hasTitle = setupTitle(topPanel); + // Install custom content before setting up the title or buttons so + // that we can handle panel overrides. + final ViewGroup customPanel = (ViewGroup) parentPanel.findViewById(R.id.customPanel); + setupCustomContent(customPanel); - final View buttonPanel = mWindow.findViewById(R.id.buttonPanel); - if (!hasButtons) { - buttonPanel.setVisibility(View.GONE); - final View spacer = mWindow.findViewById(R.id.textSpacerNoButtons); - if (spacer != null) { - spacer.setVisibility(View.VISIBLE); + final View customTopPanel = customPanel.findViewById(R.id.topPanel); + final View customContentPanel = customPanel.findViewById(R.id.contentPanel); + final View customButtonPanel = customPanel.findViewById(R.id.buttonPanel); + + // Resolve the correct panels and remove the defaults, if needed. + final ViewGroup topPanel = resolvePanel(customTopPanel, defaultTopPanel); + final ViewGroup contentPanel = resolvePanel(customContentPanel, defaultContentPanel); + final ViewGroup buttonPanel = resolvePanel(customButtonPanel, defaultButtonPanel); + + setupContent(contentPanel); + setupButtons(buttonPanel); + setupTitle(topPanel); + + final boolean hasCustomPanel = customPanel != null + && customPanel.getVisibility() != View.GONE; + final boolean hasTopPanel = topPanel != null + && topPanel.getVisibility() != View.GONE; + final boolean hasButtonPanel = buttonPanel != null + && buttonPanel.getVisibility() != View.GONE; + + // Only display the text spacer if we don't have buttons. + if (!hasButtonPanel) { + if (contentPanel != null) { + final View spacer = contentPanel.findViewById(R.id.textSpacerNoButtons); + if (spacer != null) { + spacer.setVisibility(View.VISIBLE); + } } mWindow.setCloseOnTouchOutsideIfNotSet(true); } - final FrameLayout customPanel = (FrameLayout) mWindow.findViewById(R.id.customPanel); + // Only display the divider if we have a title and a custom view or a + // message. + if (hasTopPanel) { + final View divider; + if (mMessage != null || hasCustomPanel || mListView != null) { + divider = topPanel.findViewById(R.id.titleDivider); + } else { + divider = topPanel.findViewById(R.id.titleDividerTop); + } + + if (divider != null) { + divider.setVisibility(View.VISIBLE); + } + } + + final TypedArray a = mContext.obtainStyledAttributes( + null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0); + setBackground(a, topPanel, contentPanel, customPanel, buttonPanel, + hasTopPanel, hasCustomPanel, hasButtonPanel); + a.recycle(); + } + + private void setupCustomContent(ViewGroup customPanel) { final View customView; if (mView != null) { customView = mView; @@ -502,30 +583,9 @@ public class AlertController { } else { customPanel.setVisibility(View.GONE); } - - // Only display the divider if we have a title and a custom view or a - // message. - if (hasTitle) { - final View divider; - if (mMessage != null || customView != null || mListView != null) { - divider = mWindow.findViewById(R.id.titleDivider); - } else { - divider = mWindow.findViewById(R.id.titleDividerTop); - } - - if (divider != null) { - divider.setVisibility(View.VISIBLE); - } - } - - setBackground(a, topPanel, contentPanel, customPanel, buttonPanel, hasTitle, hasCustomView, - hasButtons); - a.recycle(); } - private boolean setupTitle(ViewGroup topPanel) { - boolean hasTitle = true; - + private void setupTitle(ViewGroup topPanel) { if (mCustomTitleView != null) { // Add the custom title view directly to the topPanel layout LayoutParams lp = new LayoutParams( @@ -567,18 +627,16 @@ public class AlertController { titleTemplate.setVisibility(View.GONE); mIconView.setVisibility(View.GONE); topPanel.setVisibility(View.GONE); - hasTitle = false; } } - return hasTitle; } private void setupContent(ViewGroup contentPanel) { - mScrollView = (ScrollView) mWindow.findViewById(R.id.scrollView); + mScrollView = (ScrollView) contentPanel.findViewById(R.id.scrollView); mScrollView.setFocusable(false); // Special case for users that only want to display a String - mMessageView = (TextView) mWindow.findViewById(R.id.message); + mMessageView = (TextView) contentPanel.findViewById(R.id.message); if (mMessageView == null) { return; } @@ -601,8 +659,8 @@ public class AlertController { } // Set up scroll indicators (if present). - final View indicatorUp = mWindow.findViewById(R.id.scrollIndicatorUp); - final View indicatorDown = mWindow.findViewById(R.id.scrollIndicatorDown); + final View indicatorUp = contentPanel.findViewById(R.id.scrollIndicatorUp); + final View indicatorDown = contentPanel.findViewById(R.id.scrollIndicatorDown); if (indicatorUp != null || indicatorDown != null) { if (mMessage != null) { // We're just showing the ScrollView, set up listener. @@ -663,12 +721,12 @@ public class AlertController { } } - private boolean setupButtons() { + private void setupButtons(ViewGroup buttonPanel) { int BIT_BUTTON_POSITIVE = 1; int BIT_BUTTON_NEGATIVE = 2; int BIT_BUTTON_NEUTRAL = 4; int whichButtons = 0; - mButtonPositive = (Button) mWindow.findViewById(R.id.button1); + mButtonPositive = (Button) buttonPanel.findViewById(R.id.button1); mButtonPositive.setOnClickListener(mButtonHandler); if (TextUtils.isEmpty(mButtonPositiveText)) { @@ -679,7 +737,7 @@ public class AlertController { whichButtons = whichButtons | BIT_BUTTON_POSITIVE; } - mButtonNegative = (Button) mWindow.findViewById(R.id.button2); + mButtonNegative = (Button) buttonPanel.findViewById(R.id.button2); mButtonNegative.setOnClickListener(mButtonHandler); if (TextUtils.isEmpty(mButtonNegativeText)) { @@ -691,7 +749,7 @@ public class AlertController { whichButtons = whichButtons | BIT_BUTTON_NEGATIVE; } - mButtonNeutral = (Button) mWindow.findViewById(R.id.button3); + mButtonNeutral = (Button) buttonPanel.findViewById(R.id.button3); mButtonNeutral.setOnClickListener(mButtonHandler); if (TextUtils.isEmpty(mButtonNeutralText)) { @@ -717,7 +775,10 @@ public class AlertController { } } - return whichButtons != 0; + final boolean hasButtons = whichButtons != 0; + if (!hasButtons) { + buttonPanel.setVisibility(View.GONE); + } } private void centerButton(Button button) { diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl index 6d90420..8f549a6 100644 --- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl +++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl @@ -26,9 +26,11 @@ import android.service.voice.IVoiceInteractionService; import android.service.voice.IVoiceInteractionSession; interface IVoiceInteractionManagerService { - void startSession(IVoiceInteractionService service, in Bundle sessionArgs, int flags); + void showSession(IVoiceInteractionService service, in Bundle sessionArgs, int flags); boolean deliverNewSession(IBinder token, IVoiceInteractionSession session, IVoiceInteractor interactor); + boolean showSessionFromSession(IBinder token, in Bundle sessionArgs, int flags); + boolean hideSessionFromSession(IBinder token); int startVoiceActivity(IBinder token, in Intent intent, String resolvedType); void finish(IBinder token); diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java index ed676bb..00af401 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuItem.java +++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java @@ -18,6 +18,8 @@ package com.android.internal.view.menu; import android.content.Context; import android.content.Intent; +import android.content.res.ColorStateList; +import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.view.ActionProvider; import android.view.ContextMenu.ContextMenuInfo; @@ -42,6 +44,7 @@ public class ActionMenuItem implements MenuItem { private Drawable mIconDrawable; private int mIconResId = NO_ICON; + private TintInfo mIconTintInfo; private Context mContext; @@ -158,12 +161,14 @@ public class ActionMenuItem implements MenuItem { public MenuItem setIcon(Drawable icon) { mIconDrawable = icon; mIconResId = NO_ICON; + applyIconTint(); return this; } public MenuItem setIcon(int iconRes) { mIconResId = iconRes; mIconDrawable = mContext.getDrawable(iconRes); + applyIconTint(); return this; } @@ -274,4 +279,48 @@ public class ActionMenuItem implements MenuItem { // No need to save the listener; ActionMenuItem does not support collapsing items. return this; } + + @Override + public MenuItem setIconTintList(ColorStateList tintList) { + if (mIconTintInfo == null) { + mIconTintInfo = new TintInfo(); + } + mIconTintInfo.mTintList = tintList; + mIconTintInfo.mHasTintList = true; + applyIconTint(); + return this; + } + + @Override + public MenuItem setIconTintMode(PorterDuff.Mode tintMode) { + if (mIconTintInfo == null) { + mIconTintInfo = new TintInfo(); + } + mIconTintInfo.mTintMode = tintMode; + mIconTintInfo.mHasTintMode = true; + applyIconTint(); + return this; + } + + private void applyIconTint() { + final TintInfo tintInfo = mIconTintInfo; + if (mIconDrawable != null && tintInfo != null) { + if (tintInfo.mHasTintList || tintInfo.mHasTintMode) { + mIconDrawable = mIconDrawable.mutate(); + if (tintInfo.mHasTintList) { + mIconDrawable.setTintList(tintInfo.mTintList); + } + if (tintInfo.mHasTintMode) { + mIconDrawable.setTintMode(tintInfo.mTintMode); + } + } + } + } + + private static class TintInfo { + ColorStateList mTintList; + PorterDuff.Mode mTintMode; + boolean mHasTintMode; + boolean mHasTintList; + } } diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java index 3b1f20d..ef4e546 100644 --- a/core/java/com/android/internal/view/menu/MenuItemImpl.java +++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java @@ -21,6 +21,8 @@ import com.android.internal.view.menu.MenuView.ItemView; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; +import android.content.res.ColorStateList; +import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.util.Log; import android.view.ActionProvider; @@ -60,6 +62,11 @@ public final class MenuItemImpl implements MenuItem { * needed). */ private int mIconResId = NO_ICON; + + /** + * Tint info for the icon + */ + private TintInfo mIconTintInfo; /** The menu to which this item belongs */ private MenuBuilder mMenu; @@ -385,10 +392,10 @@ public final class MenuItemImpl implements MenuItem { } if (mIconResId != NO_ICON) { - Drawable icon = mMenu.getContext().getDrawable(mIconResId); + mIconDrawable = mMenu.getContext().getDrawable(mIconResId); mIconResId = NO_ICON; - mIconDrawable = icon; - return icon; + applyIconTint(); + return mIconDrawable; } return null; @@ -397,6 +404,7 @@ public final class MenuItemImpl implements MenuItem { public MenuItem setIcon(Drawable icon) { mIconResId = NO_ICON; mIconDrawable = icon; + applyIconTint(); mMenu.onItemsChanged(false); return this; @@ -670,4 +678,48 @@ public final class MenuItemImpl implements MenuItem { public boolean isActionViewExpanded() { return mIsActionViewExpanded; } + + @Override + public MenuItem setIconTintList(ColorStateList tintList) { + if (mIconTintInfo == null) { + mIconTintInfo = new TintInfo(); + } + mIconTintInfo.mTintList = tintList; + mIconTintInfo.mHasTintList = true; + applyIconTint(); + return this; + } + + @Override + public MenuItem setIconTintMode(PorterDuff.Mode tintMode) { + if (mIconTintInfo == null) { + mIconTintInfo = new TintInfo(); + } + mIconTintInfo.mTintMode = tintMode; + mIconTintInfo.mHasTintMode = true; + applyIconTint(); + return this; + } + + private void applyIconTint() { + final TintInfo tintInfo = mIconTintInfo; + if (mIconDrawable != null && tintInfo != null) { + if (tintInfo.mHasTintList || tintInfo.mHasTintMode) { + mIconDrawable = mIconDrawable.mutate(); + if (tintInfo.mHasTintList) { + mIconDrawable.setTintList(tintInfo.mTintList); + } + if (tintInfo.mHasTintMode) { + mIconDrawable.setTintMode(tintInfo.mTintMode); + } + } + } + } + + private static class TintInfo { + ColorStateList mTintList; + PorterDuff.Mode mTintMode; + boolean mHasTintMode; + boolean mHasTintList; + } } diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java index d617c05..89990c2 100644 --- a/core/java/com/android/internal/widget/SwipeDismissLayout.java +++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java @@ -19,6 +19,7 @@ package com.android.internal.widget; import android.animation.TimeInterpolator; import android.app.Activity; import android.content.Context; +import android.content.res.TypedArray; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; @@ -38,6 +39,7 @@ public class SwipeDismissLayout extends FrameLayout { private static final String TAG = "SwipeDismissLayout"; private static final float DISMISS_MIN_DRAG_WIDTH_RATIO = .33f; + private boolean mUseDynamicTranslucency = true; public interface OnDismissedListener { void onDismissed(SwipeDismissLayout layout); @@ -85,7 +87,7 @@ public class SwipeDismissLayout extends FrameLayout { // and temporarily disables translucency when it is fully visible. // As soon as the user starts swiping, we will re-enable // translucency. - if (getContext() instanceof Activity) { + if (mUseDynamicTranslucency && getContext() instanceof Activity) { ((Activity) getContext()).convertFromTranslucent(); } } @@ -117,6 +119,11 @@ public class SwipeDismissLayout extends FrameLayout { android.R.integer.config_shortAnimTime); mCancelInterpolator = new DecelerateInterpolator(1.5f); mDismissInterpolator = new AccelerateInterpolator(1.5f); + TypedArray a = context.getTheme().obtainStyledAttributes( + com.android.internal.R.styleable.Theme); + mUseDynamicTranslucency = !a.hasValue( + com.android.internal.R.styleable.Window_windowIsTranslucent); + a.recycle(); } public void setOnDismissedListener(OnDismissedListener listener) { @@ -230,7 +237,7 @@ public class SwipeDismissLayout extends FrameLayout { mLastX = ev.getRawX(); updateSwiping(ev); if (mSwiping) { - if (getContext() instanceof Activity) { + if (mUseDynamicTranslucency && getContext() instanceof Activity) { ((Activity) getContext()).convertToTranslucent(null, null); } setProgress(ev.getRawX() - mDownX); @@ -254,7 +261,7 @@ public class SwipeDismissLayout extends FrameLayout { } protected void cancel() { - if (getContext() instanceof Activity) { + if (mUseDynamicTranslucency && getContext() instanceof Activity) { ((Activity) getContext()).convertFromTranslucent(); } if (mProgressListener != null) { |