Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 41d9690c authored by Adam Powell's avatar Adam Powell
Browse files

Add View#onVisibilityAggregated

There's a common misconception (even across the framework) that
View#onVisibilityChanged determines and reports visibility on 'this'
up to the changed view and the total visibility within the
window. Knowing this is useful for things like starting/stopping
animations. onVisibilityChanged only reports the visibility for the
specific changed view, not the effects that would have down the tree.

Add onVisibilityAggregated to report what some code thought it was
getting already, and move ImageView and ProgressBar over to using it.

Bug 27461617

Change-Id: I433f41de453e27a53f907f1d9805350f30f31de9
parent de2fa62f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -42609,6 +42609,7 @@ package android.view {
    method public void onStartTemporaryDetach();
    method public boolean onTouchEvent(android.view.MotionEvent);
    method public boolean onTrackballEvent(android.view.MotionEvent);
    method public void onVisibilityAggregated(android.view.View, int);
    method protected void onVisibilityChanged(android.view.View, int);
    method public void onWindowFocusChanged(boolean);
    method public void onWindowSystemUiVisibilityChanged(int);
+1 −0
Original line number Diff line number Diff line
@@ -45372,6 +45372,7 @@ package android.view {
    method public void onStartTemporaryDetach();
    method public boolean onTouchEvent(android.view.MotionEvent);
    method public boolean onTrackballEvent(android.view.MotionEvent);
    method public void onVisibilityAggregated(android.view.View, int);
    method protected void onVisibilityChanged(android.view.View, int);
    method public void onWindowFocusChanged(boolean);
    method public void onWindowSystemUiVisibilityChanged(int);
+1 −0
Original line number Diff line number Diff line
@@ -42683,6 +42683,7 @@ package android.view {
    method public void onStartTemporaryDetach();
    method public boolean onTouchEvent(android.view.MotionEvent);
    method public boolean onTrackballEvent(android.view.MotionEvent);
    method public void onVisibilityAggregated(android.view.View, int);
    method protected void onVisibilityChanged(android.view.View, int);
    method public void onWindowFocusChanged(boolean);
    method public void onWindowSystemUiVisibilityChanged(int);
+66 −15
Original line number Diff line number Diff line
@@ -84,7 +84,6 @@ import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
import android.view.AccessibilityIterators.TextSegmentIterator;
import android.view.AccessibilityIterators.WordTextSegmentIterator;
import android.view.ViewGroup.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityEventSource;
import android.view.accessibility.AccessibilityManager;
@@ -10151,19 +10150,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     *                   {@link #INVISIBLE} or {@link #GONE}.
     */
    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
        if (visible && mAttachInfo != null) {
            initialAwakenScrollBars();
        }
        final Drawable dr = mBackground;
        if (dr != null && visible != dr.isVisible()) {
            dr.setVisible(visible, false);
        }
        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
        if (fg != null && visible != fg.isVisible()) {
            fg.setVisible(visible, false);
        }
    }
    /**
@@ -10219,6 +10205,52 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        }
    }
    /**
     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
     *
     * @param changedView the view that changed, either <code>this</code> or an ancestor
     * @param visibility aggregated visibility of this view's parent or changedView, whichever
     *                   is closer
     * @return the aggregated visibility for this view
     */
    int dispatchVisibilityAggregated(View changedView, @Visibility int visibility) {
        visibility = Math.max(visibility, getVisibility());
        onVisibilityAggregated(changedView, visibility);
        return visibility;
    }
    /**
     * Called when the user-visibility of this View is potentially affected by a change
     * to this view itself, an ancestor view or the window this view is attached to.
     *
     * <p>The visibility value reported will be one of {@link #VISIBLE}, {@link #INVISIBLE}
     * or {@link #GONE}, reflecting this view's aggregated visibility within its window.
     * The visibility parameter takes this view's own visibility into account.
     * Calls to this method may be repeated with the same visibility values; implementations
     * should ensure that work done is not duplicated unnecessarily.</p>
     *
     * @param changedView the view that changed; may be <code>this</code> or an ancestor
     * @param visibility the visibility of this view in the context of the full window
     */
    @CallSuper
    public void onVisibilityAggregated(View changedView, @Visibility int visibility) {
        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
        if (visible && mAttachInfo != null) {
            initialAwakenScrollBars();
        }
        final Drawable dr = mBackground;
        if (dr != null && visible != dr.isVisible()) {
            dr.setVisible(visible, false);
        }
        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
        if (fg != null && visible != fg.isVisible()) {
            fg.setVisible(visible, false);
        }
    }
    /**
     * Returns the current visibility of the window this view is attached to
     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
@@ -11336,6 +11368,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            if (mAttachInfo != null) {
                dispatchVisibilityChanged(this, newVisibility);
                // Aggregated visibility changes are dispatched to attached views
                // in visible windows where the parent is currently shown/drawn
                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
                // discounting clipping or overlapping. This makes it a good place
                // to change animation states.
                if (mParent != null && getWindowVisibility() == VISIBLE &&
                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
                    dispatchVisibilityAggregated(this, newVisibility);
                }
                notifySubtreeAccessibilityStateChangedIfNeeded();
            }
        }
@@ -15246,6 +15288,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        int vis = info.mWindowVisibility;
        if (vis != GONE) {
            onWindowVisibilityChanged(vis);
            if (isShown()) {
                onVisibilityAggregated(this, vis);
            }
        }
        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
@@ -15266,6 +15311,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            int vis = info.mWindowVisibility;
            if (vis != GONE) {
                onWindowVisibilityChanged(GONE);
                if (isShown()) {
                    onVisibilityAggregated(this, GONE);
                }
            }
        }
@@ -17958,6 +18006,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        if (mBackground != null) {
            mBackground.setCallback(null);
            unscheduleDrawable(mBackground);
            mBackground.setVisible(false, false);
        }
        if (background != null) {
@@ -17998,7 +18047,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            if (background.isStateful()) {
                background.setState(getDrawableState());
            }
            background.setVisible(getVisibility() == VISIBLE, false);
            background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
            mBackground = background;
            applyBackgroundTint();
@@ -18180,6 +18229,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        if (mForegroundInfo.mDrawable != null) {
            mForegroundInfo.mDrawable.setCallback(null);
            unscheduleDrawable(mForegroundInfo.mDrawable);
            mForegroundInfo.mDrawable.setVisible(false, false);
        }
        mForegroundInfo.mDrawable = foreground;
@@ -18194,6 +18244,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                foreground.setState(getDrawableState());
            }
            applyForegroundTint();
            foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
            mPrivateFlags |= PFLAG_SKIP_DRAW;
        }
+17 −0
Original line number Diff line number Diff line
@@ -1290,6 +1290,23 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        }
    }

    @Override
    int dispatchVisibilityAggregated(View changedView, @Visibility int visibility) {
        visibility = super.dispatchVisibilityAggregated(changedView, visibility);
        final int count = mChildrenCount;
        final View[] children = mChildren;
        for (int i = 0; i < count; i++) {
            // Only dispatch to children with at least the same level of visibility
            // that we're reporting, otherwise it won't affect that child/subtree at all
            // so it's not worth telling them about it. Note that we use <= here
            // because VISIBLE < INVISIBLE < GONE as constant values.
            if (children[i].getVisibility() <= visibility) {
                children[i].dispatchVisibilityAggregated(changedView, visibility);
            }
        }
        return visibility;
    }

    @Override
    public void dispatchConfigurationChanged(Configuration newConfig) {
        super.dispatchConfigurationChanged(newConfig);
Loading