diff options
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/view/View.java | 58 | ||||
-rw-r--r-- | core/java/android/view/ViewDebug.java | 33 | ||||
-rw-r--r-- | core/java/android/view/WindowManagerPolicy.java | 5 | ||||
-rw-r--r-- | core/java/android/widget/FrameLayout.java | 54 |
4 files changed, 110 insertions, 40 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 9f4143c..8a65219 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -5535,7 +5535,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE); if (width <= 0 || height <= 0 || - (width * height * (opaque ? 2 : 4) >= // Projected bitmap size in bytes + (width * height * (opaque ? 2 : 4) > // Projected bitmap size in bytes ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) { destroyDrawingCache(); return; @@ -5632,6 +5632,62 @@ public class View implements Drawable.Callback, KeyEvent.Callback { } /** + * Create a snapshot of the view into a bitmap. We should probably make + * some form of this public, but should think about the API. + */ + /*package*/ Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor) { + final int width = mRight - mLeft; + final int height = mBottom - mTop; + + Bitmap bitmap = Bitmap.createBitmap(width, height, quality); + if (bitmap == null) { + throw new OutOfMemoryError(); + } + + Canvas canvas; + final AttachInfo attachInfo = mAttachInfo; + if (attachInfo != null) { + canvas = attachInfo.mCanvas; + if (canvas == null) { + canvas = new Canvas(); + } + canvas.setBitmap(bitmap); + // Temporarily clobber the cached Canvas in case one of our children + // is also using a drawing cache. Without this, the children would + // steal the canvas by attaching their own bitmap to it and bad, bad + // things would happen (invisible views, corrupted drawings, etc.) + attachInfo.mCanvas = null; + } else { + // This case should hopefully never or seldom happen + canvas = new Canvas(bitmap); + } + + if ((backgroundColor&0xff000000) != 0) { + bitmap.eraseColor(backgroundColor); + } + + computeScroll(); + final int restoreCount = canvas.save(); + canvas.translate(-mScrollX, -mScrollY); + + // Fast path for layouts with no backgrounds + if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { + dispatchDraw(canvas); + } else { + draw(canvas); + } + + canvas.restoreToCount(restoreCount); + + if (attachInfo != null) { + // Restore the cached Canvas for our siblings + attachInfo.mCanvas = canvas; + } + + return bitmap; + } + + /** * Indicates whether this View is currently in edit mode. A View is usually * in edit mode when displayed within a developer tool. For instance, if * this View is being drawn by a visual user interface builder, this method diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index f604bc5..c1e9ed8 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -741,22 +741,18 @@ public class ViewDebug { final CountDownLatch latch = new CountDownLatch(1); final Bitmap[] cache = new Bitmap[1]; - final boolean hasCache = captureView.isDrawingCacheEnabled(); - final boolean willNotCache = captureView.willNotCacheDrawing(); - - if (willNotCache) { - // TODO: Should happen on the UI thread - captureView.setWillNotCacheDrawing(false); - } - root.post(new Runnable() { public void run() { try { - if (!hasCache) { - captureView.buildDrawingCache(); + cache[0] = captureView.createSnapshot( + Bitmap.Config.ARGB_8888, 0); + } catch (OutOfMemoryError e) { + try { + cache[0] = captureView.createSnapshot( + Bitmap.Config.ARGB_4444, 0); + } catch (OutOfMemoryError e2) { + Log.w("View", "Out of memory for bitmap"); } - - cache[0] = captureView.getDrawingCache(); } finally { latch.countDown(); } @@ -776,20 +772,15 @@ public class ViewDebug { if (out != null) { out.close(); } + cache[0].recycle(); } + } else { + Log.w("View", "Failed to create capture bitmap!"); + clientStream.close(); } } catch (InterruptedException e) { Log.w("View", "Could not complete the capture of the view " + captureView); Thread.currentThread().interrupt(); - } finally { - if (willNotCache) { - // TODO: Should happen on the UI thread - captureView.setWillNotCacheDrawing(true); - } - if (!hasCache) { - // TODO: Should happen on the UI thread - captureView.destroyDrawingCache(); - } } } } diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 220869c..1371932 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -580,8 +580,11 @@ public interface WindowManagerPolicy { * Called when layout of the windows is finished. After this function has * returned, all windows given to layoutWindow() <em>must</em> have had a * frame assigned. + * + * @return Return true if layout state may have changed (so that another + * layout will be performed). */ - public void finishLayoutLw(); + public boolean finishLayoutLw(); /** * Called when animation of the windows is about to start. diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java index 47db6f2..80fbf9e 100644 --- a/core/java/android/widget/FrameLayout.java +++ b/core/java/android/widget/FrameLayout.java @@ -24,6 +24,7 @@ import android.graphics.Region; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; +import android.view.ViewDebug; import android.view.ViewGroup; import android.view.Gravity; import android.widget.RemoteViews.RemoteView; @@ -45,21 +46,31 @@ import android.widget.RemoteViews.RemoteView; */ @RemoteView public class FrameLayout extends ViewGroup { + @ViewDebug.ExportedProperty boolean mMeasureAllChildren = false; + @ViewDebug.ExportedProperty private Drawable mForeground; + @ViewDebug.ExportedProperty private int mForegroundPaddingLeft = 0; + @ViewDebug.ExportedProperty private int mForegroundPaddingTop = 0; + @ViewDebug.ExportedProperty private int mForegroundPaddingRight = 0; + @ViewDebug.ExportedProperty private int mForegroundPaddingBottom = 0; private final Rect mSelfBounds = new Rect(); private final Rect mOverlayBounds = new Rect(); + @ViewDebug.ExportedProperty private int mForegroundGravity = Gravity.FILL; /** {@hide} */ + @ViewDebug.ExportedProperty protected boolean mForegroundInPadding = true; + boolean mForegroundBoundsChanged = false; + public FrameLayout(Context context) { super(context); } @@ -269,6 +280,8 @@ public class FrameLayout extends ViewGroup { final int parentTop = mPaddingTop + mForegroundPaddingTop; final int parentBottom = bottom - top - mPaddingBottom - mForegroundPaddingBottom; + mForegroundBoundsChanged = true; + for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { @@ -328,22 +341,7 @@ public class FrameLayout extends ViewGroup { @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); - - final Drawable foreground = mForeground; - if (foreground != null) { - final Rect selfBounds = mSelfBounds; - final Rect overlayBounds = mOverlayBounds; - - if (mForegroundInPadding) { - selfBounds.set(0, 0, w, h); - } else { - selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom); - } - - Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(), - foreground.getIntrinsicHeight(), selfBounds, overlayBounds); - foreground.setBounds(overlayBounds); - } + mForegroundBoundsChanged = true; } /** @@ -354,7 +352,29 @@ public class FrameLayout extends ViewGroup { super.draw(canvas); if (mForeground != null) { - mForeground.draw(canvas); + final Drawable foreground = mForeground; + if (mForegroundBoundsChanged) { + mForegroundBoundsChanged = false; + if (foreground != null) { + final Rect selfBounds = mSelfBounds; + final Rect overlayBounds = mOverlayBounds; + + final int w = mRight-mLeft; + final int h = mBottom-mTop; + + if (mForegroundInPadding) { + selfBounds.set(0, 0, w, h); + } else { + selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom); + } + + Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(), + foreground.getIntrinsicHeight(), selfBounds, overlayBounds); + foreground.setBounds(overlayBounds); + } + } + + foreground.draw(canvas); } } |