summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/view/View.java58
-rw-r--r--core/java/android/view/ViewDebug.java33
-rw-r--r--core/java/android/view/WindowManagerPolicy.java5
-rw-r--r--core/java/android/widget/FrameLayout.java54
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);
}
}