Loading api/current.txt +7 −0 Original line number Diff line number Diff line Loading @@ -24148,15 +24148,18 @@ package android.view { } public final class ViewTreeObserver { method public void addOnDrawListener(android.view.ViewTreeObserver.OnDrawListener); method public void addOnGlobalFocusChangeListener(android.view.ViewTreeObserver.OnGlobalFocusChangeListener); method public void addOnGlobalLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener); method public void addOnPreDrawListener(android.view.ViewTreeObserver.OnPreDrawListener); method public void addOnScrollChangedListener(android.view.ViewTreeObserver.OnScrollChangedListener); method public void addOnTouchModeChangeListener(android.view.ViewTreeObserver.OnTouchModeChangeListener); method public final void dispatchOnDraw(); method public final void dispatchOnGlobalLayout(); method public final boolean dispatchOnPreDraw(); method public boolean isAlive(); method public deprecated void removeGlobalOnLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener); method public void removeOnDrawListener(android.view.ViewTreeObserver.OnDrawListener); method public void removeOnGlobalFocusChangeListener(android.view.ViewTreeObserver.OnGlobalFocusChangeListener); method public void removeOnGlobalLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener); method public void removeOnPreDrawListener(android.view.ViewTreeObserver.OnPreDrawListener); Loading @@ -24164,6 +24167,10 @@ package android.view { method public void removeOnTouchModeChangeListener(android.view.ViewTreeObserver.OnTouchModeChangeListener); } public static abstract interface ViewTreeObserver.OnDrawListener { method public abstract void onDraw(); } public static abstract interface ViewTreeObserver.OnGlobalFocusChangeListener { method public abstract void onGlobalFocusChanged(android.view.View, android.view.View); } core/java/android/view/ViewRootImpl.java +145 −132 Original line number Diff line number Diff line Loading @@ -2039,9 +2039,10 @@ public final class ViewRootImpl implements ViewParent, scrollToRectOrFocus(null, false); if (mAttachInfo.mViewScrollChanged) { mAttachInfo.mViewScrollChanged = false; mAttachInfo.mTreeObserver.dispatchOnScrollChanged(); final AttachInfo attachInfo = mAttachInfo; if (attachInfo.mViewScrollChanged) { attachInfo.mViewScrollChanged = false; attachInfo.mTreeObserver.dispatchOnScrollChanged(); } int yoff; Loading @@ -2056,8 +2057,8 @@ public final class ViewRootImpl implements ViewParent, fullRedrawNeeded = true; } final float appScale = mAttachInfo.mApplicationScale; final boolean scalingRequired = mAttachInfo.mScalingRequired; final float appScale = attachInfo.mApplicationScale; final boolean scalingRequired = attachInfo.mScalingRequired; int resizeAlpha = 0; if (mResizeBuffer != null) { Loading Loading @@ -2086,7 +2087,7 @@ public final class ViewRootImpl implements ViewParent, } if (fullRedrawNeeded) { mAttachInfo.mIgnoreDirtyState = true; attachInfo.mIgnoreDirtyState = true; dirty.set(0, 0, (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f)); } Loading @@ -2099,8 +2100,10 @@ public final class ViewRootImpl implements ViewParent, appScale + ", width=" + mWidth + ", height=" + mHeight); } attachInfo.mTreeObserver.dispatchOnDraw(); if (!dirty.isEmpty() || mIsAnimating) { if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) { if (attachInfo.mHardwareRenderer != null && attachInfo.mHardwareRenderer.isEnabled()) { // Draw with hardware renderer. mIsAnimating = false; mHardwareYOffset = yoff; Loading @@ -2111,11 +2114,27 @@ public final class ViewRootImpl implements ViewParent, mPreviousDirty.set(dirty); dirty.setEmpty(); if (mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this, if (attachInfo.mHardwareRenderer.draw(mView, attachInfo, this, animating ? null : mCurrentDirty)) { mPreviousDirty.set(0, 0, mWidth, mHeight); } } else { } else if (!drawSoftware(surface, attachInfo, yoff, scalingRequired, dirty)) { return; } } if (animating) { mFullRedrawNeeded = true; scheduleTraversals(); } } /** * @return true if drawing was succesful, false if an error occured */ private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int yoff, boolean scalingRequired, Rect dirty) { // Draw with software renderer. Canvas canvas; try { Loading @@ -2139,7 +2158,7 @@ public final class ViewRootImpl implements ViewParent, if (left != dirty.left || top != dirty.top || right != dirty.right || bottom != dirty.bottom) { mAttachInfo.mIgnoreDirtyState = true; attachInfo.mIgnoreDirtyState = true; } // TODO: Do this in native Loading @@ -2154,14 +2173,14 @@ public final class ViewRootImpl implements ViewParent, } catch (RemoteException ex) { } mLayoutRequested = true; // ask wm for a new surface next time. return; return false; } catch (IllegalArgumentException e) { Log.e(TAG, "IllegalArgumentException locking surface", e); // Don't assume this is due to out of memory, it could be // something else, and if it is something else then we could // kill stuff (or ourself) for no reason. mLayoutRequested = true; // ask wm for a new surface next time. return; return false; } try { Loading Loading @@ -2190,7 +2209,7 @@ public final class ViewRootImpl implements ViewParent, dirty.setEmpty(); mIsAnimating = false; mAttachInfo.mDrawingTime = SystemClock.uptimeMillis(); attachInfo.mDrawingTime = SystemClock.uptimeMillis(); mView.mPrivateFlags |= View.DRAWN; if (DEBUG_DRAW) { Loading @@ -2206,7 +2225,7 @@ public final class ViewRootImpl implements ViewParent, } canvas.setScreenDensity(scalingRequired ? DisplayMetrics.DENSITY_DEVICE : 0); mAttachInfo.mSetIgnoreDirtyState = false; attachInfo.mSetIgnoreDirtyState = false; final long drawStartTime; if (ViewDebug.DEBUG_LATENCY) { Loading @@ -2221,9 +2240,9 @@ public final class ViewRootImpl implements ViewParent, + ((now - drawStartTime) * 0.000001f) + "ms"); } } finally { if (!mAttachInfo.mSetIgnoreDirtyState) { if (!attachInfo.mSetIgnoreDirtyState) { // Only clear the flag if it was not set during the mView.draw() call mAttachInfo.mIgnoreDirtyState = false; attachInfo.mIgnoreDirtyState = false; } } Loading Loading @@ -2252,13 +2271,7 @@ public final class ViewRootImpl implements ViewParent, Log.v(TAG, "Surface " + surface + " unlockCanvasAndPost"); } } } } if (animating) { mFullRedrawNeeded = true; scheduleTraversals(); } return true; } void invalidateDisplayLists() { Loading core/java/android/view/ViewTreeObserver.java +94 −25 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ public final class ViewTreeObserver { private CopyOnWriteArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners; private CopyOnWriteArrayList<OnScrollChangedListener> mOnScrollChangedListeners; private ArrayList<OnPreDrawListener> mOnPreDrawListeners; private ArrayList<OnDrawListener> mOnDrawListeners; private boolean mAlive = true; Loading Loading @@ -89,6 +90,27 @@ public final class ViewTreeObserver { public boolean onPreDraw(); } /** * Interface definition for a callback to be invoked when the view tree is about to be drawn. */ public interface OnDrawListener { /** * <p>Callback method to be invoked when the view tree is about to be drawn. At this point, * views cannot be modified in any way.</p> * * <p>Unlike with {@link OnPreDrawListener}, this method cannot be used to cancel the * current drawing pass.</p> * * <p>An {@link OnDrawListener} listener <strong>cannot be added or removed</strong> * from this method.</p> * * @see android.view.View#onMeasure * @see android.view.View#onLayout * @see android.view.View#onDraw */ public void onDraw(); } /** * Interface definition for a callback to be invoked when the touch mode changes. */ Loading Loading @@ -172,10 +194,6 @@ public final class ViewTreeObserver { mTouchableInsets = val; } public int getTouchableInsets() { return mTouchableInsets; } int mTouchableInsets; void reset() { Loading @@ -186,25 +204,24 @@ public final class ViewTreeObserver { } @Override public boolean equals(Object o) { try { if (o == null) { return false; public int hashCode() { int result = contentInsets != null ? contentInsets.hashCode() : 0; result = 31 * result + (visibleInsets != null ? visibleInsets.hashCode() : 0); result = 31 * result + (touchableRegion != null ? touchableRegion.hashCode() : 0); result = 31 * result + mTouchableInsets; return result; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; InternalInsetsInfo other = (InternalInsetsInfo)o; if (mTouchableInsets != other.mTouchableInsets) { return false; } if (!contentInsets.equals(other.contentInsets)) { return false; } if (!visibleInsets.equals(other.visibleInsets)) { return false; } return touchableRegion.equals(other.touchableRegion); } catch (ClassCastException e) { return false; } return mTouchableInsets == other.mTouchableInsets && contentInsets.equals(other.contentInsets) && visibleInsets.equals(other.visibleInsets) && touchableRegion.equals(other.touchableRegion); } void set(InternalInsetsInfo other) { Loading Loading @@ -419,6 +436,44 @@ public final class ViewTreeObserver { mOnPreDrawListeners.remove(victim); } /** * <p>Register a callback to be invoked when the view tree is about to be drawn.</p> * <p><strong>Note:</strong> this method <strong>cannot</strong> be invoked from * {@link android.view.ViewTreeObserver.OnDrawListener#onDraw()}.</p> * * @param listener The callback to add * * @throws IllegalStateException If {@link #isAlive()} returns false */ public void addOnDrawListener(OnDrawListener listener) { checkIsAlive(); if (mOnDrawListeners == null) { mOnDrawListeners = new ArrayList<OnDrawListener>(); } mOnDrawListeners.add(listener); } /** * <p>Remove a previously installed pre-draw callback.</p> * <p><strong>Note:</strong> this method <strong>cannot</strong> be invoked from * {@link android.view.ViewTreeObserver.OnDrawListener#onDraw()}.</p> * * @param victim The callback to remove * * @throws IllegalStateException If {@link #isAlive()} returns false * * @see #addOnDrawListener(OnDrawListener) */ public void removeOnDrawListener(OnDrawListener victim) { checkIsAlive(); if (mOnDrawListeners == null) { return; } mOnDrawListeners.remove(victim); } /** * Register a callback to be invoked when a view has been scrolled. * Loading Loading @@ -601,6 +656,7 @@ public final class ViewTreeObserver { * * @return True if the current draw should be canceled and resceduled, false otherwise. */ @SuppressWarnings("unchecked") public final boolean dispatchOnPreDraw() { // NOTE: we *must* clone the listener list to perform the dispatching. // The clone is a safe guard against listeners that Loading @@ -618,6 +674,19 @@ public final class ViewTreeObserver { return cancelDraw; } /** * Notifies registered listeners that the drawing pass is about to start. */ public final void dispatchOnDraw() { if (mOnDrawListeners != null) { final ArrayList<OnDrawListener> listeners = mOnDrawListeners; int numListeners = listeners.size(); for (int i = 0; i < numListeners; ++i) { listeners.get(i).onDraw(); } } } /** * Notifies registered listeners that the touch mode has changed. * Loading Loading
api/current.txt +7 −0 Original line number Diff line number Diff line Loading @@ -24148,15 +24148,18 @@ package android.view { } public final class ViewTreeObserver { method public void addOnDrawListener(android.view.ViewTreeObserver.OnDrawListener); method public void addOnGlobalFocusChangeListener(android.view.ViewTreeObserver.OnGlobalFocusChangeListener); method public void addOnGlobalLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener); method public void addOnPreDrawListener(android.view.ViewTreeObserver.OnPreDrawListener); method public void addOnScrollChangedListener(android.view.ViewTreeObserver.OnScrollChangedListener); method public void addOnTouchModeChangeListener(android.view.ViewTreeObserver.OnTouchModeChangeListener); method public final void dispatchOnDraw(); method public final void dispatchOnGlobalLayout(); method public final boolean dispatchOnPreDraw(); method public boolean isAlive(); method public deprecated void removeGlobalOnLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener); method public void removeOnDrawListener(android.view.ViewTreeObserver.OnDrawListener); method public void removeOnGlobalFocusChangeListener(android.view.ViewTreeObserver.OnGlobalFocusChangeListener); method public void removeOnGlobalLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener); method public void removeOnPreDrawListener(android.view.ViewTreeObserver.OnPreDrawListener); Loading @@ -24164,6 +24167,10 @@ package android.view { method public void removeOnTouchModeChangeListener(android.view.ViewTreeObserver.OnTouchModeChangeListener); } public static abstract interface ViewTreeObserver.OnDrawListener { method public abstract void onDraw(); } public static abstract interface ViewTreeObserver.OnGlobalFocusChangeListener { method public abstract void onGlobalFocusChanged(android.view.View, android.view.View); }
core/java/android/view/ViewRootImpl.java +145 −132 Original line number Diff line number Diff line Loading @@ -2039,9 +2039,10 @@ public final class ViewRootImpl implements ViewParent, scrollToRectOrFocus(null, false); if (mAttachInfo.mViewScrollChanged) { mAttachInfo.mViewScrollChanged = false; mAttachInfo.mTreeObserver.dispatchOnScrollChanged(); final AttachInfo attachInfo = mAttachInfo; if (attachInfo.mViewScrollChanged) { attachInfo.mViewScrollChanged = false; attachInfo.mTreeObserver.dispatchOnScrollChanged(); } int yoff; Loading @@ -2056,8 +2057,8 @@ public final class ViewRootImpl implements ViewParent, fullRedrawNeeded = true; } final float appScale = mAttachInfo.mApplicationScale; final boolean scalingRequired = mAttachInfo.mScalingRequired; final float appScale = attachInfo.mApplicationScale; final boolean scalingRequired = attachInfo.mScalingRequired; int resizeAlpha = 0; if (mResizeBuffer != null) { Loading Loading @@ -2086,7 +2087,7 @@ public final class ViewRootImpl implements ViewParent, } if (fullRedrawNeeded) { mAttachInfo.mIgnoreDirtyState = true; attachInfo.mIgnoreDirtyState = true; dirty.set(0, 0, (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f)); } Loading @@ -2099,8 +2100,10 @@ public final class ViewRootImpl implements ViewParent, appScale + ", width=" + mWidth + ", height=" + mHeight); } attachInfo.mTreeObserver.dispatchOnDraw(); if (!dirty.isEmpty() || mIsAnimating) { if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) { if (attachInfo.mHardwareRenderer != null && attachInfo.mHardwareRenderer.isEnabled()) { // Draw with hardware renderer. mIsAnimating = false; mHardwareYOffset = yoff; Loading @@ -2111,11 +2114,27 @@ public final class ViewRootImpl implements ViewParent, mPreviousDirty.set(dirty); dirty.setEmpty(); if (mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this, if (attachInfo.mHardwareRenderer.draw(mView, attachInfo, this, animating ? null : mCurrentDirty)) { mPreviousDirty.set(0, 0, mWidth, mHeight); } } else { } else if (!drawSoftware(surface, attachInfo, yoff, scalingRequired, dirty)) { return; } } if (animating) { mFullRedrawNeeded = true; scheduleTraversals(); } } /** * @return true if drawing was succesful, false if an error occured */ private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int yoff, boolean scalingRequired, Rect dirty) { // Draw with software renderer. Canvas canvas; try { Loading @@ -2139,7 +2158,7 @@ public final class ViewRootImpl implements ViewParent, if (left != dirty.left || top != dirty.top || right != dirty.right || bottom != dirty.bottom) { mAttachInfo.mIgnoreDirtyState = true; attachInfo.mIgnoreDirtyState = true; } // TODO: Do this in native Loading @@ -2154,14 +2173,14 @@ public final class ViewRootImpl implements ViewParent, } catch (RemoteException ex) { } mLayoutRequested = true; // ask wm for a new surface next time. return; return false; } catch (IllegalArgumentException e) { Log.e(TAG, "IllegalArgumentException locking surface", e); // Don't assume this is due to out of memory, it could be // something else, and if it is something else then we could // kill stuff (or ourself) for no reason. mLayoutRequested = true; // ask wm for a new surface next time. return; return false; } try { Loading Loading @@ -2190,7 +2209,7 @@ public final class ViewRootImpl implements ViewParent, dirty.setEmpty(); mIsAnimating = false; mAttachInfo.mDrawingTime = SystemClock.uptimeMillis(); attachInfo.mDrawingTime = SystemClock.uptimeMillis(); mView.mPrivateFlags |= View.DRAWN; if (DEBUG_DRAW) { Loading @@ -2206,7 +2225,7 @@ public final class ViewRootImpl implements ViewParent, } canvas.setScreenDensity(scalingRequired ? DisplayMetrics.DENSITY_DEVICE : 0); mAttachInfo.mSetIgnoreDirtyState = false; attachInfo.mSetIgnoreDirtyState = false; final long drawStartTime; if (ViewDebug.DEBUG_LATENCY) { Loading @@ -2221,9 +2240,9 @@ public final class ViewRootImpl implements ViewParent, + ((now - drawStartTime) * 0.000001f) + "ms"); } } finally { if (!mAttachInfo.mSetIgnoreDirtyState) { if (!attachInfo.mSetIgnoreDirtyState) { // Only clear the flag if it was not set during the mView.draw() call mAttachInfo.mIgnoreDirtyState = false; attachInfo.mIgnoreDirtyState = false; } } Loading Loading @@ -2252,13 +2271,7 @@ public final class ViewRootImpl implements ViewParent, Log.v(TAG, "Surface " + surface + " unlockCanvasAndPost"); } } } } if (animating) { mFullRedrawNeeded = true; scheduleTraversals(); } return true; } void invalidateDisplayLists() { Loading
core/java/android/view/ViewTreeObserver.java +94 −25 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ public final class ViewTreeObserver { private CopyOnWriteArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners; private CopyOnWriteArrayList<OnScrollChangedListener> mOnScrollChangedListeners; private ArrayList<OnPreDrawListener> mOnPreDrawListeners; private ArrayList<OnDrawListener> mOnDrawListeners; private boolean mAlive = true; Loading Loading @@ -89,6 +90,27 @@ public final class ViewTreeObserver { public boolean onPreDraw(); } /** * Interface definition for a callback to be invoked when the view tree is about to be drawn. */ public interface OnDrawListener { /** * <p>Callback method to be invoked when the view tree is about to be drawn. At this point, * views cannot be modified in any way.</p> * * <p>Unlike with {@link OnPreDrawListener}, this method cannot be used to cancel the * current drawing pass.</p> * * <p>An {@link OnDrawListener} listener <strong>cannot be added or removed</strong> * from this method.</p> * * @see android.view.View#onMeasure * @see android.view.View#onLayout * @see android.view.View#onDraw */ public void onDraw(); } /** * Interface definition for a callback to be invoked when the touch mode changes. */ Loading Loading @@ -172,10 +194,6 @@ public final class ViewTreeObserver { mTouchableInsets = val; } public int getTouchableInsets() { return mTouchableInsets; } int mTouchableInsets; void reset() { Loading @@ -186,25 +204,24 @@ public final class ViewTreeObserver { } @Override public boolean equals(Object o) { try { if (o == null) { return false; public int hashCode() { int result = contentInsets != null ? contentInsets.hashCode() : 0; result = 31 * result + (visibleInsets != null ? visibleInsets.hashCode() : 0); result = 31 * result + (touchableRegion != null ? touchableRegion.hashCode() : 0); result = 31 * result + mTouchableInsets; return result; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; InternalInsetsInfo other = (InternalInsetsInfo)o; if (mTouchableInsets != other.mTouchableInsets) { return false; } if (!contentInsets.equals(other.contentInsets)) { return false; } if (!visibleInsets.equals(other.visibleInsets)) { return false; } return touchableRegion.equals(other.touchableRegion); } catch (ClassCastException e) { return false; } return mTouchableInsets == other.mTouchableInsets && contentInsets.equals(other.contentInsets) && visibleInsets.equals(other.visibleInsets) && touchableRegion.equals(other.touchableRegion); } void set(InternalInsetsInfo other) { Loading Loading @@ -419,6 +436,44 @@ public final class ViewTreeObserver { mOnPreDrawListeners.remove(victim); } /** * <p>Register a callback to be invoked when the view tree is about to be drawn.</p> * <p><strong>Note:</strong> this method <strong>cannot</strong> be invoked from * {@link android.view.ViewTreeObserver.OnDrawListener#onDraw()}.</p> * * @param listener The callback to add * * @throws IllegalStateException If {@link #isAlive()} returns false */ public void addOnDrawListener(OnDrawListener listener) { checkIsAlive(); if (mOnDrawListeners == null) { mOnDrawListeners = new ArrayList<OnDrawListener>(); } mOnDrawListeners.add(listener); } /** * <p>Remove a previously installed pre-draw callback.</p> * <p><strong>Note:</strong> this method <strong>cannot</strong> be invoked from * {@link android.view.ViewTreeObserver.OnDrawListener#onDraw()}.</p> * * @param victim The callback to remove * * @throws IllegalStateException If {@link #isAlive()} returns false * * @see #addOnDrawListener(OnDrawListener) */ public void removeOnDrawListener(OnDrawListener victim) { checkIsAlive(); if (mOnDrawListeners == null) { return; } mOnDrawListeners.remove(victim); } /** * Register a callback to be invoked when a view has been scrolled. * Loading Loading @@ -601,6 +656,7 @@ public final class ViewTreeObserver { * * @return True if the current draw should be canceled and resceduled, false otherwise. */ @SuppressWarnings("unchecked") public final boolean dispatchOnPreDraw() { // NOTE: we *must* clone the listener list to perform the dispatching. // The clone is a safe guard against listeners that Loading @@ -618,6 +674,19 @@ public final class ViewTreeObserver { return cancelDraw; } /** * Notifies registered listeners that the drawing pass is about to start. */ public final void dispatchOnDraw() { if (mOnDrawListeners != null) { final ArrayList<OnDrawListener> listeners = mOnDrawListeners; int numListeners = listeners.size(); for (int i = 0; i < numListeners; ++i) { listeners.get(i).onDraw(); } } } /** * Notifies registered listeners that the touch mode has changed. * Loading