1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 package com.android.internal.widget; 19 20 import android.graphics.Canvas; 21 import android.graphics.PixelFormat; 22 import android.graphics.drawable.Drawable; 23 import android.view.View; 24 import android.view.ViewGroup; 25 26 /** 27 * Helper class for drawing a fallback background in framework decor layouts. 28 * Useful for when an app has not set a window background but we're asked to draw 29 * an uncovered area. 30 */ 31 public class BackgroundFallback { 32 private Drawable mBackgroundFallback; 33 setDrawable(Drawable d)34 public void setDrawable(Drawable d) { 35 mBackgroundFallback = d; 36 } 37 hasFallback()38 public boolean hasFallback() { 39 return mBackgroundFallback != null; 40 } 41 42 /** 43 * Draws the fallback background. 44 * 45 * @param boundsView The view determining with which bounds the background should be drawn. 46 * @param root The view group containing the content. 47 * @param c The canvas to draw the background onto. 48 * @param content The view where the actual app content is contained in. 49 */ draw(ViewGroup boundsView, ViewGroup root, Canvas c, View content)50 public void draw(ViewGroup boundsView, ViewGroup root, Canvas c, View content) { 51 if (!hasFallback()) { 52 return; 53 } 54 55 // Draw the fallback in the padding. 56 final int width = boundsView.getWidth(); 57 final int height = boundsView.getHeight(); 58 int left = width; 59 int top = height; 60 int right = 0; 61 int bottom = 0; 62 63 final int childCount = root.getChildCount(); 64 for (int i = 0; i < childCount; i++) { 65 final View child = root.getChildAt(i); 66 final Drawable childBg = child.getBackground(); 67 if (child == content) { 68 // We always count the content view container unless it has no background 69 // and no children. 70 if (childBg == null && child instanceof ViewGroup && 71 ((ViewGroup) child).getChildCount() == 0) { 72 continue; 73 } 74 } else if (child.getVisibility() != View.VISIBLE || childBg == null || 75 childBg.getOpacity() != PixelFormat.OPAQUE) { 76 // Potentially translucent or invisible children don't count, and we assume 77 // the content view will cover the whole area if we're in a background 78 // fallback situation. 79 continue; 80 } 81 left = Math.min(left, child.getLeft()); 82 top = Math.min(top, child.getTop()); 83 right = Math.max(right, child.getRight()); 84 bottom = Math.max(bottom, child.getBottom()); 85 } 86 87 if (left >= right || top >= bottom) { 88 // No valid area to draw in. 89 return; 90 } 91 92 if (top > 0) { 93 mBackgroundFallback.setBounds(0, 0, width, top); 94 mBackgroundFallback.draw(c); 95 } 96 if (left > 0) { 97 mBackgroundFallback.setBounds(0, top, left, height); 98 mBackgroundFallback.draw(c); 99 } 100 if (right < width) { 101 mBackgroundFallback.setBounds(right, top, width, height); 102 mBackgroundFallback.draw(c); 103 } 104 if (bottom < height) { 105 mBackgroundFallback.setBounds(left, bottom, right, height); 106 mBackgroundFallback.draw(c); 107 } 108 } 109 } 110