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 draw(ViewGroup root, Canvas c, View content)42 public void draw(ViewGroup root, Canvas c, View content) { 43 if (!hasFallback()) { 44 return; 45 } 46 47 // Draw the fallback in the padding. 48 final int width = root.getWidth(); 49 final int height = root.getHeight(); 50 int left = width; 51 int top = height; 52 int right = 0; 53 int bottom = 0; 54 55 final int childCount = root.getChildCount(); 56 for (int i = 0; i < childCount; i++) { 57 final View child = root.getChildAt(i); 58 final Drawable childBg = child.getBackground(); 59 if (child == content) { 60 // We always count the content view container unless it has no background 61 // and no children. 62 if (childBg == null && child instanceof ViewGroup && 63 ((ViewGroup) child).getChildCount() == 0) { 64 continue; 65 } 66 } else if (child.getVisibility() != View.VISIBLE || childBg == null || 67 childBg.getOpacity() != PixelFormat.OPAQUE) { 68 // Potentially translucent or invisible children don't count, and we assume 69 // the content view will cover the whole area if we're in a background 70 // fallback situation. 71 continue; 72 } 73 left = Math.min(left, child.getLeft()); 74 top = Math.min(top, child.getTop()); 75 right = Math.max(right, child.getRight()); 76 bottom = Math.max(bottom, child.getBottom()); 77 } 78 79 if (left >= right || top >= bottom) { 80 // No valid area to draw in. 81 return; 82 } 83 84 if (top > 0) { 85 mBackgroundFallback.setBounds(0, 0, width, top); 86 mBackgroundFallback.draw(c); 87 } 88 if (left > 0) { 89 mBackgroundFallback.setBounds(0, top, left, height); 90 mBackgroundFallback.draw(c); 91 } 92 if (right < width) { 93 mBackgroundFallback.setBounds(right, top, width, height); 94 mBackgroundFallback.draw(c); 95 } 96 if (bottom < height) { 97 mBackgroundFallback.setBounds(left, bottom, right, height); 98 mBackgroundFallback.draw(c); 99 } 100 } 101 } 102