| /* |
| * Copyright (C) 2010 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.policy.impl; |
| |
| import android.content.Context; |
| import android.graphics.Canvas; |
| import android.graphics.Rect; |
| import android.graphics.drawable.Drawable; |
| import android.util.AttributeSet; |
| import android.util.Log; |
| import android.view.Gravity; |
| import android.view.View; |
| import android.widget.LinearLayout; |
| |
| /** |
| * A vertical linear layout. However, instead of drawing the background |
| * behnd the items, it draws the background outside the items based on the |
| * padding. If there isn't enough room to draw both, it clips the background |
| * instead of the contents. |
| */ |
| public class RecentApplicationsBackground extends LinearLayout { |
| private static final String TAG = "RecentApplicationsBackground"; |
| |
| private boolean mBackgroundSizeChanged; |
| private Drawable mBackground; |
| private Rect mTmp0 = new Rect(); |
| private Rect mTmp1 = new Rect(); |
| |
| public RecentApplicationsBackground(Context context) { |
| this(context, null); |
| init(); |
| } |
| |
| public RecentApplicationsBackground(Context context, AttributeSet attrs) { |
| super(context, attrs); |
| init(); |
| } |
| |
| private void init() { |
| mBackground = getBackground(); |
| setBackgroundDrawable(null); |
| setPadding(0, 0, 0, 0); |
| setGravity(Gravity.CENTER); |
| } |
| |
| @Override |
| protected boolean setFrame(int left, int top, int right, int bottom) { |
| setWillNotDraw(false); |
| if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) { |
| mBackgroundSizeChanged = true; |
| } |
| return super.setFrame(left, top, right, bottom); |
| } |
| |
| @Override |
| protected boolean verifyDrawable(Drawable who) { |
| return who == mBackground || super.verifyDrawable(who); |
| } |
| |
| @Override |
| protected void drawableStateChanged() { |
| Drawable d = mBackground; |
| if (d != null && d.isStateful()) { |
| d.setState(getDrawableState()); |
| } |
| super.drawableStateChanged(); |
| } |
| |
| @Override |
| public void draw(Canvas canvas) { |
| final Drawable background = mBackground; |
| if (background != null) { |
| if (mBackgroundSizeChanged) { |
| mBackgroundSizeChanged = false; |
| Rect chld = mTmp0; |
| Rect bkg = mTmp1; |
| mBackground.getPadding(bkg); |
| getChildBounds(chld); |
| // This doesn't clamp to this view's bounds, which is what we want, |
| // so that the drawing is clipped. |
| final int top = chld.top - bkg.top; |
| final int bottom = chld.bottom + bkg.bottom; |
| // The background here is a gradient that wants to |
| // extend the full width of the screen (whatever that |
| // may be). |
| int left, right; |
| if (false) { |
| // This limits the width of the drawable. |
| left = chld.left - bkg.left; |
| right = chld.right + bkg.right; |
| } else { |
| // This expands it to full width. |
| left = 0; |
| right = getRight(); |
| } |
| background.setBounds(left, top, right, bottom); |
| } |
| } |
| mBackground.draw(canvas); |
| |
| if (false) { |
| android.graphics.Paint p = new android.graphics.Paint(); |
| p.setColor(0x88ffff00); |
| canvas.drawRect(background.getBounds(), p); |
| } |
| canvas.drawARGB((int)(0.75*0xff), 0, 0, 0); |
| |
| super.draw(canvas); |
| } |
| |
| @Override |
| protected void onAttachedToWindow() { |
| super.onAttachedToWindow(); |
| mBackground.setCallback(this); |
| setWillNotDraw(false); |
| } |
| |
| @Override |
| protected void onDetachedFromWindow() { |
| super.onDetachedFromWindow(); |
| mBackground.setCallback(null); |
| } |
| |
| private void getChildBounds(Rect r) { |
| r.left = r.top = Integer.MAX_VALUE; |
| r.bottom = r.right = Integer.MIN_VALUE; |
| final int N = getChildCount(); |
| for (int i=0; i<N; i++) { |
| View v = getChildAt(i); |
| if (v.getVisibility() == View.VISIBLE) { |
| r.left = Math.min(r.left, v.getLeft()); |
| r.top = Math.min(r.top, v.getTop()); |
| r.right = Math.max(r.right, v.getRight()); |
| r.bottom = Math.max(r.bottom, v.getBottom()); |
| } |
| } |
| } |
| } |