Skip to content

Commit 1a3ab17

Browse files
committed
Fix quickReject logic for transformed views
When a parent draws its child views, each child's bounds is checked against the current dirty region. If the view falls outside of that region is is rejected and doesn't enter into the parent's DisplayList. This works in general, for both transformed and untransformed views (because we skip this check if the view is transformed). But it breaks down when the transform properties of the view change later, since DisplayList properties simply push these values down to the view's DisplayList without invalidating the parent. If a view is rejected when untransformed, then there is nothing to cause it to be considered again until something causes an invalidate of the parent. The fix is to note when a view is rejected and record that information. Later, when one of the transform-related properties change, we invalidate the parent to force the check to happen again, which will cause the view to get drawn if it's visible. Issue #6477730 quickRejected views must recreate their DisplayLists on transform changes Change-Id: I70caf198005cd7e424a37bccc6ae050e09880a6c
1 parent 2651101 commit 1a3ab17

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

core/java/android/view/View.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2135,6 +2135,13 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
21352135
*/
21362136
static final int VIEW_IS_ANIMATING_TRANSFORM = 0x10000000;
21372137

2138+
/**
2139+
* Flag indicating whether a view failed the quickReject() check in draw(). This condition
2140+
* is used to check whether later changes to the view's transform should invalidate the
2141+
* view to force the quickReject test to run again.
2142+
*/
2143+
static final int VIEW_QUICK_REJECTED = 0x20000000;
2144+
21382145
/* End of masks for mPrivateFlags2 */
21392146

21402147
static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
@@ -8567,6 +8574,10 @@ public void setCameraDistance(float distance) {
85678574
if (mDisplayList != null) {
85688575
mDisplayList.setCameraDistance(-Math.abs(distance) / dpi);
85698576
}
8577+
if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8578+
// View was rejected last time it was drawn by its parent; this may have changed
8579+
invalidateParentIfNeeded();
8580+
}
85708581
}
85718582

85728583
/**
@@ -8609,6 +8620,10 @@ public void setRotation(float rotation) {
86098620
if (mDisplayList != null) {
86108621
mDisplayList.setRotation(rotation);
86118622
}
8623+
if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8624+
// View was rejected last time it was drawn by its parent; this may have changed
8625+
invalidateParentIfNeeded();
8626+
}
86128627
}
86138628
}
86148629

@@ -8656,6 +8671,10 @@ public void setRotationY(float rotationY) {
86568671
if (mDisplayList != null) {
86578672
mDisplayList.setRotationY(rotationY);
86588673
}
8674+
if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8675+
// View was rejected last time it was drawn by its parent; this may have changed
8676+
invalidateParentIfNeeded();
8677+
}
86598678
}
86608679
}
86618680

@@ -8703,6 +8722,10 @@ public void setRotationX(float rotationX) {
87038722
if (mDisplayList != null) {
87048723
mDisplayList.setRotationX(rotationX);
87058724
}
8725+
if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8726+
// View was rejected last time it was drawn by its parent; this may have changed
8727+
invalidateParentIfNeeded();
8728+
}
87068729
}
87078730
}
87088731

@@ -8742,6 +8765,10 @@ public void setScaleX(float scaleX) {
87428765
if (mDisplayList != null) {
87438766
mDisplayList.setScaleX(scaleX);
87448767
}
8768+
if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8769+
// View was rejected last time it was drawn by its parent; this may have changed
8770+
invalidateParentIfNeeded();
8771+
}
87458772
}
87468773
}
87478774

@@ -8781,6 +8808,10 @@ public void setScaleY(float scaleY) {
87818808
if (mDisplayList != null) {
87828809
mDisplayList.setScaleY(scaleY);
87838810
}
8811+
if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8812+
// View was rejected last time it was drawn by its parent; this may have changed
8813+
invalidateParentIfNeeded();
8814+
}
87848815
}
87858816
}
87868817

@@ -8828,6 +8859,10 @@ public void setPivotX(float pivotX) {
88288859
if (mDisplayList != null) {
88298860
mDisplayList.setPivotX(pivotX);
88308861
}
8862+
if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8863+
// View was rejected last time it was drawn by its parent; this may have changed
8864+
invalidateParentIfNeeded();
8865+
}
88318866
}
88328867
}
88338868

@@ -8874,6 +8909,10 @@ public void setPivotY(float pivotY) {
88748909
if (mDisplayList != null) {
88758910
mDisplayList.setPivotY(pivotY);
88768911
}
8912+
if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
8913+
// View was rejected last time it was drawn by its parent; this may have changed
8914+
invalidateParentIfNeeded();
8915+
}
88778916
}
88788917
}
88798918

@@ -9032,6 +9071,10 @@ public final void setTop(int top) {
90329071
}
90339072
mBackgroundSizeChanged = true;
90349073
invalidateParentIfNeeded();
9074+
if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
9075+
// View was rejected last time it was drawn by its parent; this may have changed
9076+
invalidateParentIfNeeded();
9077+
}
90359078
}
90369079
}
90379080

@@ -9101,6 +9144,10 @@ public final void setBottom(int bottom) {
91019144
}
91029145
mBackgroundSizeChanged = true;
91039146
invalidateParentIfNeeded();
9147+
if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
9148+
// View was rejected last time it was drawn by its parent; this may have changed
9149+
invalidateParentIfNeeded();
9150+
}
91049151
}
91059152
}
91069153

@@ -9164,6 +9211,10 @@ public final void setLeft(int left) {
91649211
}
91659212
mBackgroundSizeChanged = true;
91669213
invalidateParentIfNeeded();
9214+
if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
9215+
// View was rejected last time it was drawn by its parent; this may have changed
9216+
invalidateParentIfNeeded();
9217+
}
91679218
}
91689219
}
91699220

@@ -9224,6 +9275,10 @@ public final void setRight(int right) {
92249275
}
92259276
mBackgroundSizeChanged = true;
92269277
invalidateParentIfNeeded();
9278+
if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
9279+
// View was rejected last time it was drawn by its parent; this may have changed
9280+
invalidateParentIfNeeded();
9281+
}
92279282
}
92289283
}
92299284

@@ -9308,6 +9363,10 @@ public void setTranslationX(float translationX) {
93089363
if (mDisplayList != null) {
93099364
mDisplayList.setTranslationX(translationX);
93109365
}
9366+
if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
9367+
// View was rejected last time it was drawn by its parent; this may have changed
9368+
invalidateParentIfNeeded();
9369+
}
93119370
}
93129371
}
93139372

@@ -9345,6 +9404,10 @@ public void setTranslationY(float translationY) {
93459404
if (mDisplayList != null) {
93469405
mDisplayList.setTranslationY(translationY);
93479406
}
9407+
if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
9408+
// View was rejected last time it was drawn by its parent; this may have changed
9409+
invalidateParentIfNeeded();
9410+
}
93489411
}
93499412
}
93509413

@@ -12816,8 +12879,10 @@ boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
1281612879

1281712880
if (!concatMatrix && canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
1281812881
(mPrivateFlags & DRAW_ANIMATION) == 0) {
12882+
mPrivateFlags2 |= VIEW_QUICK_REJECTED;
1281912883
return more;
1282012884
}
12885+
mPrivateFlags2 &= ~VIEW_QUICK_REJECTED;
1282112886

1282212887
if (hardwareAccelerated) {
1282312888
// Clear INVALIDATED flag to allow invalidation to occur during rendering, but

0 commit comments

Comments
 (0)