Merge change 1825 into donut

* changes:
  Fixes #1855461, #1857290 and #1857365. Certain scrollbar styles make an opaque view not be opaque. ListView and View now account for this when indicating whether they are opaque or not.
This commit is contained in:
Android (Google) Code Review
2009-05-15 16:15:31 -07:00
2 changed files with 101 additions and 21 deletions

View File

@@ -1442,6 +1442,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
*/
static final int DIRTY_MASK = 0x00600000;
/**
* Indicates whether the background is opaque.
*
* @hide
*/
static final int OPAQUE_BACKGROUND = 0x00800000;
/**
* Indicates whether the scrollbars are opaque.
*
* @hide
*/
static final int OPAQUE_SCROLLBARS = 0x01000000;
/**
* Indicates whether the view is opaque.
*
* @hide
*/
static final int OPAQUE_MASK = 0x01800000;
/**
* The parent this view is attached to.
* {@hide}
@@ -1721,7 +1742,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
public View(Context context) {
mContext = context;
mResources = context != null ? context.getResources() : null;
mViewFlags = SOUND_EFFECTS_ENABLED|HAPTIC_FEEDBACK_ENABLED;
mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
++sInstanceCount;
}
@@ -2013,7 +2034,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
setScrollContainer(true);
}
computeOpaqueFlags();
a.recycle();
}
@@ -4700,7 +4723,35 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
*/
@ViewDebug.ExportedProperty
public boolean isOpaque() {
return mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE;
return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK;
}
private void computeOpaqueFlags() {
// Opaque if:
// - Has a background
// - Background is opaque
// - Doesn't have scrollbars or scrollbars are inside overlay
if (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE) {
mPrivateFlags |= OPAQUE_BACKGROUND;
} else {
mPrivateFlags &= ~OPAQUE_BACKGROUND;
}
final int flags = mViewFlags;
if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
(flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
mPrivateFlags |= OPAQUE_SCROLLBARS;
} else {
mPrivateFlags &= ~OPAQUE_SCROLLBARS;
}
}
/**
* @hide
*/
protected boolean hasOpaqueScrollbars() {
return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
}
/**
@@ -5027,6 +5078,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
mViewFlags ^= SCROLLBARS_HORIZONTAL;
computeOpaqueFlags();
recomputePadding();
}
}
@@ -5056,6 +5108,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
mViewFlags ^= SCROLLBARS_VERTICAL;
computeOpaqueFlags();
recomputePadding();
}
}
@@ -5084,6 +5137,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
public void setScrollBarStyle(int style) {
if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
computeOpaqueFlags();
recomputePadding();
}
}
@@ -6848,6 +6902,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
requestLayout = true;
}
computeOpaqueFlags();
if (requestLayout) {
requestLayout();
}

View File

@@ -21,6 +21,7 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.PixelFormat;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ColorDrawable;
import android.os.Parcel;
@@ -133,6 +134,7 @@ public class ListView extends AbsListView {
// used for temporary calculations.
private final Rect mTempRect = new Rect();
private Paint mDividerPaint;
// the single allocated result per list view; kinda cheesey but avoids
// allocating these thingies too often.
@@ -2813,12 +2815,20 @@ public class ListView extends AbsListView {
*/
@Override
public boolean isOpaque() {
return (mCachingStarted && mIsCacheColorOpaque && mDividerIsOpaque) || super.isOpaque();
return (mCachingStarted && mIsCacheColorOpaque && mDividerIsOpaque &&
hasOpaqueScrollbars()) || super.isOpaque();
}
@Override
public void setCacheColorHint(int color) {
mIsCacheColorOpaque = (color >>> 24) == 0xFF;
final boolean opaque = (color >>> 24) == 0xFF;
mIsCacheColorOpaque = opaque;
if (opaque) {
if (mDividerPaint == null) {
mDividerPaint = new Paint();
}
mDividerPaint.setColor(color);
}
super.setCacheColorHint(color);
}
@@ -2841,6 +2851,8 @@ public class ListView extends AbsListView {
final int first = mFirstPosition;
final boolean areAllItemsSelectable = mAreAllItemsSelectable;
final ListAdapter adapter = mAdapter;
final boolean isOpaque = isOpaque();
final Paint paint = mDividerPaint;
if (!mStackFromBottom) {
int bottom;
@@ -2852,12 +2864,18 @@ public class ListView extends AbsListView {
View child = getChildAt(i);
bottom = child.getBottom();
// Don't draw dividers next to items that are not enabled
if (bottom < listBottom && (areAllItemsSelectable ||
(adapter.isEnabled(first + i) && (i == count - 1 ||
adapter.isEnabled(first + i + 1))))) {
bounds.top = bottom;
bounds.bottom = bottom + dividerHeight;
drawDivider(canvas, bounds, i);
if (bottom < listBottom) {
if ((areAllItemsSelectable ||
(adapter.isEnabled(first + i) && (i == count - 1 ||
adapter.isEnabled(first + i + 1))))) {
bounds.top = bottom;
bounds.bottom = bottom + dividerHeight;
drawDivider(canvas, bounds, i);
} else if (isOpaque) {
bounds.top = bottom;
bounds.bottom = bottom + dividerHeight;
canvas.drawRect(bounds, paint);
}
}
}
}
@@ -2871,16 +2889,22 @@ public class ListView extends AbsListView {
View child = getChildAt(i);
top = child.getTop();
// Don't draw dividers next to items that are not enabled
if (top > listTop && (areAllItemsSelectable ||
(adapter.isEnabled(first + i) && (i == count - 1 ||
adapter.isEnabled(first + i + 1))))) {
bounds.top = top - dividerHeight;
bounds.bottom = top;
// Give the method the child ABOVE the divider, so we
// subtract one from our child
// position. Give -1 when there is no child above the
// divider.
drawDivider(canvas, bounds, i - 1);
if (top > listTop) {
if ((areAllItemsSelectable ||
(adapter.isEnabled(first + i) && (i == count - 1 ||
adapter.isEnabled(first + i + 1))))) {
bounds.top = top - dividerHeight;
bounds.bottom = top;
// Give the method the child ABOVE the divider, so we
// subtract one from our child
// position. Give -1 when there is no child above the
// divider.
drawDivider(canvas, bounds, i - 1);
} else if (isOpaque) {
bounds.top = top - dividerHeight;
bounds.bottom = top;
canvas.drawRect(bounds, paint);
}
}
}
}