} else {
draw(canvas);
}
- drawAccessibilityFocus(canvas);
}
} finally {
renderNode.end(canvas);
} else {
draw(canvas);
}
- drawAccessibilityFocus(canvas);
canvas.restoreToCount(restoreCount);
canvas.setBitmap(null);
} else {
draw(canvas);
}
- drawAccessibilityFocus(canvas);
mPrivateFlags = flags;
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
dispatchDraw(canvas);
- if (mOverlay != null && !mOverlay.isEmpty()) {
- mOverlay.getOverlayView().draw(canvas);
- }
} else {
draw(canvas);
}
- drawAccessibilityFocus(canvas);
} else {
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
((HardwareCanvas) canvas).drawRenderNode(renderNode, null, flags);
}
/**
- * Draws the accessibility focus rect onto the specified canvas.
- *
- * @param canvas Canvas on which to draw the focus rect
- */
- private void drawAccessibilityFocus(Canvas canvas) {
- if (mAttachInfo == null) {
- return;
- }
-
- final Rect bounds = mAttachInfo.mTmpInvalRect;
- final ViewRootImpl viewRoot = getViewRootImpl();
- if (viewRoot == null || viewRoot.getAccessibilityFocusedHost() != this) {
- return;
- }
-
- final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
- if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
- return;
- }
-
- final Drawable drawable = viewRoot.getAccessibilityFocusedDrawable();
- if (drawable == null) {
- return;
- }
-
- final AccessibilityNodeInfo virtualView = viewRoot.getAccessibilityFocusedVirtualView();
- if (virtualView != null) {
- virtualView.getBoundsInScreen(bounds);
- final int[] offset = mAttachInfo.mTmpLocation;
- getLocationOnScreen(offset);
- bounds.offset(-offset[0], -offset[1]);
- } else {
- bounds.set(0, 0, mRight - mLeft, mBottom - mTop);
- }
-
- canvas.save();
- canvas.translate(mScrollX, mScrollY);
- canvas.clipRect(bounds, Region.Op.REPLACE);
- drawable.setBounds(bounds);
- drawable.draw(canvas);
- canvas.restore();
- }
-
- /**
* Draws the background onto the specified canvas.
*
* @param canvas Canvas on which to draw the background
canvas.drawHardwareLayer(mResizeBuffer, mHardwareXOffset, mHardwareYOffset,
mResizePaint);
}
+ drawAccessibilityFocusedDrawableIfNeeded(canvas);
}
/**
dirty.offset(surfaceInsets.left, surfaceInsets.right);
}
- if (!dirty.isEmpty() || mIsAnimating) {
+ boolean accessibilityFocusDirty = false;
+ final Drawable drawable = mAttachInfo.mAccessibilityFocusDrawable;
+ if (drawable != null) {
+ final Rect bounds = mAttachInfo.mTmpInvalRect;
+ final boolean hasFocus = getAccessibilityFocusedRect(bounds);
+ if (!hasFocus) {
+ bounds.setEmpty();
+ }
+ if (!bounds.equals(drawable.getBounds())) {
+ accessibilityFocusDirty = true;
+ }
+ }
+
+ if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
+ // If accessibility focus moved, always invalidate the root.
+ boolean invalidateRoot = accessibilityFocusDirty;
+
// Draw with hardware renderer.
mIsAnimating = false;
- boolean invalidateRoot = false;
+
if (mHardwareYOffset != yOffset || mHardwareXOffset != xOffset) {
mHardwareYOffset = yOffset;
mHardwareXOffset = xOffset;
- mAttachInfo.mHardwareRenderer.invalidateRoot();
+ invalidateRoot = true;
}
mResizeAlpha = resizeAlpha;
+ if (invalidateRoot) {
+ mAttachInfo.mHardwareRenderer.invalidateRoot();
+ }
+
dirty.setEmpty();
mBlockResizeBuffer = false;
attachInfo.mSetIgnoreDirtyState = false;
mView.draw(canvas);
+
+ drawAccessibilityFocusedDrawableIfNeeded(canvas);
} finally {
if (!attachInfo.mSetIgnoreDirtyState) {
// Only clear the flag if it was not set during the mView.draw() call
return true;
}
- Drawable getAccessibilityFocusedDrawable() {
+ /**
+ * We want to draw a highlight around the current accessibility focused.
+ * Since adding a style for all possible view is not a viable option we
+ * have this specialized drawing method.
+ *
+ * Note: We are doing this here to be able to draw the highlight for
+ * virtual views in addition to real ones.
+ *
+ * @param canvas The canvas on which to draw.
+ */
+ private void drawAccessibilityFocusedDrawableIfNeeded(Canvas canvas) {
+ final Rect bounds = mAttachInfo.mTmpInvalRect;
+ if (getAccessibilityFocusedRect(bounds)) {
+ final Drawable drawable = getAccessibilityFocusedDrawable();
+ if (drawable != null) {
+ drawable.setBounds(bounds);
+ drawable.draw(canvas);
+ }
+ } else if (mAttachInfo.mAccessibilityFocusDrawable != null) {
+ mAttachInfo.mAccessibilityFocusDrawable.setBounds(0, 0, 0, 0);
+ }
+ }
+
+ private boolean getAccessibilityFocusedRect(Rect bounds) {
+ final AccessibilityManager manager = AccessibilityManager.getInstance(mView.mContext);
+ if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
+ return false;
+ }
+
+ final View host = mAccessibilityFocusedHost;
+ if (host == null || host.mAttachInfo == null) {
+ return false;
+ }
+
+ final AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider();
+ if (provider == null) {
+ host.getBoundsOnScreen(bounds);
+ } else if (mAccessibilityFocusedVirtualView != null) {
+ mAccessibilityFocusedVirtualView.getBoundsInScreen(bounds);
+ } else {
+ return false;
+ }
+
+ final AttachInfo attachInfo = mAttachInfo;
+ bounds.offset(-attachInfo.mWindowLeft, -attachInfo.mWindowTop);
+ bounds.intersect(0, 0, attachInfo.mViewRootImpl.mWidth, attachInfo.mViewRootImpl.mHeight);
+ return !bounds.isEmpty();
+ }
+
+ private Drawable getAccessibilityFocusedDrawable() {
// Lazily load the accessibility focus drawable.
if (mAttachInfo.mAccessibilityFocusDrawable == null) {
final TypedValue value = new TypedValue();
if (position >= headerViewsCount && position < footerViewsStart) {
// The view will be rebound to new data, clear any
// system-managed transient state.
- if (child.isAccessibilityFocused()) {
- child.clearAccessibilityFocus();
- }
+ child.clearAccessibilityFocus();
mRecycler.addScrapView(child, position);
}
}
if (position >= headerViewsCount && position < footerViewsStart) {
// The view will be rebound to new data, clear any
// system-managed transient state.
- if (child.isAccessibilityFocused()) {
- child.clearAccessibilityFocus();
- }
+ child.clearAccessibilityFocus();
mRecycler.addScrapView(child, position);
}
}
}
private void clearAccessibilityFromScrap(View view) {
- if (view.isAccessibilityFocused()) {
- view.clearAccessibilityFocus();
- }
+ view.clearAccessibilityFocus();
view.setAccessibilityDelegate(null);
}