diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java index 0105f51ff0100..d24f32fafe591 100644 --- a/core/java/com/android/internal/widget/ActionBarContainer.java +++ b/core/java/com/android/internal/widget/ActionBarContainer.java @@ -22,6 +22,7 @@ import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Outline; +import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.ActionMode; @@ -384,7 +385,23 @@ public class ActionBarContainer extends FrameLayout { @Override public int getOpacity() { - return 0; + if (mIsSplit) { + if (mSplitBackground != null + && mSplitBackground.getOpacity() == PixelFormat.OPAQUE) { + return PixelFormat.OPAQUE; + } + } else { + if (mIsStacked && (mStackedBackground == null + || mStackedBackground.getOpacity() != PixelFormat.OPAQUE)) { + return PixelFormat.UNKNOWN; + } + if (!isCollapsed(mActionBarView) && mBackground != null + && mBackground.getOpacity() == PixelFormat.OPAQUE) { + return PixelFormat.OPAQUE; + } + } + + return PixelFormat.UNKNOWN; } } } diff --git a/core/java/com/android/internal/widget/BackgroundFallback.java b/core/java/com/android/internal/widget/BackgroundFallback.java new file mode 100644 index 0000000000000..4adba4db4f2e4 --- /dev/null +++ b/core/java/com/android/internal/widget/BackgroundFallback.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2014 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 com.android.internal.widget; + +import android.graphics.Canvas; +import android.graphics.PixelFormat; +import android.graphics.drawable.Drawable; +import android.view.View; +import android.view.ViewGroup; + +/** + * Helper class for drawing a fallback background in framework decor layouts. + * Useful for when an app has not set a window background but we're asked to draw + * an uncovered area. + */ +public class BackgroundFallback { + private Drawable mBackgroundFallback; + + public void setDrawable(Drawable d) { + mBackgroundFallback = d; + } + + public boolean hasFallback() { + return mBackgroundFallback != null; + } + + public void draw(ViewGroup root, Canvas c, View content) { + if (!hasFallback()) { + return; + } + + // Draw the fallback in the padding. + final int width = root.getWidth(); + final int height = root.getHeight(); + int left = width; + int top = height; + int right = 0; + int bottom = 0; + + final int childCount = root.getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = root.getChildAt(i); + final Drawable childBg = child.getBackground(); + if (child == content) { + // We always count the content view container unless it has no background + // and no children. + if (childBg == null && child instanceof ViewGroup && + ((ViewGroup) child).getChildCount() == 0) { + continue; + } + } else if (child.getVisibility() != View.VISIBLE || childBg == null || + childBg.getOpacity() != PixelFormat.OPAQUE) { + // Potentially translucent or invisible children don't count, and we assume + // the content view will cover the whole area if we're in a background + // fallback situation. + continue; + } + left = Math.min(left, child.getLeft()); + top = Math.min(top, child.getTop()); + right = Math.max(right, child.getRight()); + bottom = Math.max(bottom, child.getBottom()); + } + + if (left >= right || top >= bottom) { + // No valid area to draw in. + return; + } + + if (top > 0) { + mBackgroundFallback.setBounds(0, 0, width, top); + mBackgroundFallback.draw(c); + } + if (left > 0) { + mBackgroundFallback.setBounds(0, top, left, height); + mBackgroundFallback.draw(c); + } + if (right < width) { + mBackgroundFallback.setBounds(right, top, width, height); + mBackgroundFallback.draw(c); + } + if (bottom < height) { + mBackgroundFallback.setBounds(left, bottom, right, height); + mBackgroundFallback.draw(c); + } + } +} diff --git a/core/java/com/android/internal/widget/DecorContentParent.java b/core/java/com/android/internal/widget/DecorContentParent.java index 4fa370ad2bbaa..ac524f929d1ba 100644 --- a/core/java/com/android/internal/widget/DecorContentParent.java +++ b/core/java/com/android/internal/widget/DecorContentParent.java @@ -49,5 +49,4 @@ public interface DecorContentParent { void saveToolbarHierarchyState(SparseArray toolbarStates); void restoreToolbarHierarchyState(SparseArray toolbarStates); void dismissPopups(); - } diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 0e597d0c1a70b..516b08846b2c9 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -308,6 +308,10 @@ null so it will not be drawn. --> + + @@ -1772,6 +1776,7 @@ + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 0c13bd5fb29d3..dfd3071550e7d 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2060,4 +2060,5 @@ + diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index d0097aacf7f3d..05776592d5124 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -169,6 +169,7 @@ please see themes_device_defaults.xml. @drawable/screen_background_selector_dark + ?attr/colorBackground false @null false diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml index 008e1700d215c..aefca726eacb7 100644 --- a/core/res/res/values/themes_material.xml +++ b/core/res/res/values/themes_material.xml @@ -145,7 +145,7 @@ please see themes_device_defaults.xml. @drawable/gallery_item_background - @color/background_material_dark + ?attr/colorBackground true @null false @@ -489,7 +489,7 @@ please see themes_device_defaults.xml. @drawable/gallery_item_background - @color/background_material_light + ?attr/colorBackground true @null false diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index 92171c1c4d129..6f7f1fb595538 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -33,6 +33,7 @@ import com.android.internal.view.menu.MenuDialogHelper; import com.android.internal.view.menu.MenuPresenter; import com.android.internal.view.menu.MenuView; import com.android.internal.widget.ActionBarContextView; +import com.android.internal.widget.BackgroundFallback; import com.android.internal.widget.DecorContentParent; import com.android.internal.widget.SwipeDismissLayout; @@ -211,6 +212,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private ProgressBar mHorizontalProgressBar; private int mBackgroundResource = 0; + private int mBackgroundFallbackResource = 0; private Drawable mBackgroundDrawable; @@ -1326,6 +1328,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (mDecor != null) { mDecor.setWindowBackground(drawable); } + if (mBackgroundFallbackResource != 0) { + mDecor.setBackgroundFallback(drawable != null ? 0 : mBackgroundFallbackResource); + } } } @@ -2153,6 +2158,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { private View mStatusColorView; private View mNavigationColorView; + private final BackgroundFallback mBackgroundFallback = new BackgroundFallback(); private int mLastTopInset = 0; private int mLastBottomInset = 0; @@ -2165,6 +2171,17 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { mFeatureId = featureId; } + public void setBackgroundFallback(int resId) { + mBackgroundFallback.setDrawable(resId != 0 ? getContext().getDrawable(resId) : null); + setWillNotDraw(getBackground() == null && !mBackgroundFallback.hasFallback()); + } + + @Override + public void onDraw(Canvas c) { + super.onDraw(c); + mBackgroundFallback.draw(mContentRoot, c, mContentParent); + } + @Override public boolean dispatchKeyEvent(KeyEvent event) { final int keyCode = event.getKeyCode(); @@ -3342,6 +3359,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (mFrameResource == 0) { mFrameResource = a.getResourceId(R.styleable.Window_windowFrame, 0); } + mBackgroundFallbackResource = a.getResourceId( + R.styleable.Window_windowBackgroundFallback, 0); if (false) { System.out.println("Background: " + Integer.toHexString(mBackgroundResource) + " Frame: " @@ -3557,6 +3576,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } } + if (mDecor.getBackground() == null && mBackgroundFallbackResource != 0) { + mDecor.setBackgroundFallback(mBackgroundFallbackResource); + } + // Only inflate or create a new TransitionManager if the caller hasn't // already set a custom one. if (hasFeature(FEATURE_ACTIVITY_TRANSITIONS)) {