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

Commit 7a9b2a67 authored by Mady Mellor's avatar Mady Mellor
Browse files

Close inline controls / hide the gear when interaction outside occurs

This CL adds the behavior so that if the gear or inline controls are
visible, they will close if the user interacts with another area of
the screen (e.g. scrolls, pulls down QS, etc) this is on the lock screen
as well as the shade.

This CL makes an additional change to remove the GearDisplayedListener
and use the StackScroller to maintain state of the gear / reset as
appropriate.

Bug: 27598072
Bug: 27335311

Change-Id: Iebff9aa542c9d91389054a4ff292d0dda11fe950
parent f7d28faa
Loading
Loading
Loading
Loading
+13 −19
Original line number Diff line number Diff line
@@ -107,7 +107,6 @@ import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.statusbar.policy.RemoteInputView;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.GearDisplayedListener;
import com.android.systemui.statusbar.stack.StackStateAnimator;

import java.util.ArrayList;
@@ -120,7 +119,7 @@ import static com.android.keyguard.KeyguardHostView.OnDismissAction;
public abstract class BaseStatusBar extends SystemUI implements
        CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
        ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
        ExpandableNotificationRow.OnExpandClickListener, GearDisplayedListener {
        ExpandableNotificationRow.OnExpandClickListener {
    public static final String TAG = "StatusBar";
    public static final boolean DEBUG = false;
    public static final boolean MULTIUSER_DEBUG = false;
@@ -242,7 +241,6 @@ public abstract class BaseStatusBar extends SystemUI implements

    // which notification is currently being longpress-examined by the user
    private NotificationGuts mNotificationGutsExposed;
    private ExpandableNotificationRow mNotificationGearDisplayed;

    private KeyboardShortcuts mKeyboardShortcuts;

@@ -1067,10 +1065,6 @@ public abstract class BaseStatusBar extends SystemUI implements
        guts.bindImportance(pmUser, sbn, row, mNotificationData.getImportance(sbn.getKey()));
    }

    protected GearDisplayedListener getGearDisplayedListener() {
        return this;
    }

    protected SwipeHelper.LongPressListener getNotificationLongClicker() {
        return new SwipeHelper.LongPressListener() {
            @Override
@@ -1106,7 +1100,8 @@ public abstract class BaseStatusBar extends SystemUI implements
                // Post to ensure the the guts are properly laid out.
                guts.post(new Runnable() {
                    public void run() {
                        dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */);
                        dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */,
                                false /* animate */);
                        guts.setVisibility(View.VISIBLE);
                        final double horz = Math.max(guts.getWidth() - x, x);
                        final double vert = Math.max(guts.getHeight() - y, y);
@@ -1135,22 +1130,22 @@ public abstract class BaseStatusBar extends SystemUI implements
        };
    }

    @Override
    public void onGearDisplayed(ExpandableNotificationRow row) {
        MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
                row.getStatusBarNotification().getPackageName());
        mNotificationGearDisplayed = row;
    /**
     * Returns the exposed NotificationGuts or null if none are exposed.
     */
    public NotificationGuts getExposedGuts() {
        return mNotificationGutsExposed;
    }

    public void dismissPopups() {
        dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */);
        dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */, false /* animate */);
    }

    private void dismissPopups(int x, int y) {
        dismissPopups(x, y, true /* resetGear */);
        dismissPopups(x, y, true /* resetGear */, false /* animate */);
    }

    public void dismissPopups(int x, int y, boolean resetGear) {
    public void dismissPopups(int x, int y, boolean resetGear, boolean animate) {
        if (mNotificationGutsExposed != null) {
            final NotificationGuts v = mNotificationGutsExposed;
            mNotificationGutsExposed = null;
@@ -1178,9 +1173,8 @@ public abstract class BaseStatusBar extends SystemUI implements
            v.setExposed(false);
            mStackScroller.onHeightChanged(null, true /* needsAnimation */);
        }
        if (resetGear && mNotificationGearDisplayed != null) {
            mNotificationGearDisplayed.resetTranslation();
            mNotificationGearDisplayed = null;
        if (resetGear) {
            mStackScroller.resetExposedGearView(animate, true /* force */);
        }
    }

+2 −2
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ public class NotificationSettingsIconRow extends FrameLayout implements View.OnC
        /**
         * Called when a notification is slid back over the gear.
         */
        public void onSettingsIconRowReset(NotificationSettingsIconRow row);
        public void onSettingsIconRowReset(ExpandableNotificationRow row);
    }

    private ExpandableNotificationRow mParent;
@@ -94,7 +94,7 @@ public class NotificationSettingsIconRow extends FrameLayout implements View.OnC
        mDismissing = false;
        setIconLocation(true /* on left */, true /* force */);
        if (mListener != null) {
            mListener.onSettingsIconRowReset(this);
            mListener.onSettingsIconRowReset(mParent);
        }
    }

+0 −1
Original line number Diff line number Diff line
@@ -755,7 +755,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
                R.id.notification_stack_scroller);
        mStackScroller.setLongPressListener(getNotificationLongClicker());
        mStackScroller.setGearDisplayedListener(getGearDisplayedListener());
        mStackScroller.setPhoneStatusBar(this);
        mStackScroller.setGroupManager(mGroupManager);
        mStackScroller.setHeadsUpManager(mHeadsUpManager);
+4 −0
Original line number Diff line number Diff line
@@ -226,6 +226,10 @@ public class StatusBarWindowView extends FrameLayout {
                return false;
            }
        }
        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
            mStackScrollLayout.closeControlsIfOutsideTouch(ev);
        }

        return super.dispatchTouchEvent(ev);
    }

+81 −41
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ import com.android.systemui.statusbar.DismissView;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.NotificationGuts;
import com.android.systemui.statusbar.NotificationOverflowContainer;
import com.android.systemui.statusbar.NotificationSettingsIconRow;
import com.android.systemui.statusbar.NotificationSettingsIconRow.SettingsIconRowListener;
@@ -220,7 +221,6 @@ public class NotificationStackScrollLayout extends ViewGroup
     */
    private int mMaxScrollAfterExpand;
    private SwipeHelper.LongPressListener mLongPressListener;
    private GearDisplayedListener mGearDisplayedListener;

    private NotificationSettingsIconRow mCurrIconRow;
    private View mTranslatingParentView;
@@ -374,8 +374,12 @@ public class NotificationStackScrollLayout extends ViewGroup
    }

    @Override
    public void onSettingsIconRowReset(NotificationSettingsIconRow row) {
    public void onSettingsIconRowReset(ExpandableNotificationRow row) {
        if (mTranslatingParentView != null && row == mTranslatingParentView) {
            mSwipeHelper.setSnappedToGear(false);
            mGearExposedView = null;
            mTranslatingParentView = null;
        }
    }

    @Override
@@ -669,10 +673,6 @@ public class NotificationStackScrollLayout extends ViewGroup
        mLongPressListener = listener;
    }

    public void setGearDisplayedListener(GearDisplayedListener listener) {
        mGearDisplayedListener = listener;
    }

    public void setQsContainer(ViewGroup qsContainer) {
        mQsContainer = qsContainer;
    }
@@ -737,17 +737,9 @@ public class NotificationStackScrollLayout extends ViewGroup
            // We start the swipe and snap back in the same frame, we don't want any animation
            mDragAnimPendingChildren.remove(animView);
        }

        if (mCurrIconRow != null) {
            if (targetLeft == 0) {
        if (mCurrIconRow != null && targetLeft == 0) {
            mCurrIconRow.resetState();
            mCurrIconRow = null;
                if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) {
                    mGearExposedView = null;
                }
            } else {
                mSwipeHelper.setSnappedToGear(true);
            }
        }
    }

@@ -3470,13 +3462,6 @@ public class NotificationStackScrollLayout extends ViewGroup
        public void flingTopOverscroll(float velocity, boolean open);
    }

    /**
     * A listener that is notified when the gear is shown behind a notification.
     */
    public interface GearDisplayedListener {
        void onGearDisplayed(ExpandableNotificationRow row);
    }

    private class NotificationSwipeHelper extends SwipeHelper {
        private static final long GEAR_SHOW_DELAY = 60;
        private CheckForDrag mCheckForDrag;
@@ -3503,7 +3488,7 @@ public class NotificationStackScrollLayout extends ViewGroup
            mCurrIconRow = null;

            // Slide back any notifications that might be showing a gear
            resetExposedGearView();
            resetExposedGearView(true /* animate */, false /* force */);

            if (currView instanceof ExpandableNotificationRow) {
                // Set the listener for the current row's gear
@@ -3551,8 +3536,7 @@ public class NotificationStackScrollLayout extends ViewGroup
        public void dismissChild(final View view, float velocity,
                boolean useAccelerateInterpolator) {
            super.dismissChild(view, velocity, useAccelerateInterpolator);
            cancelCheckForDrag();
            setSnappedToGear(false);
            handleGearCoveredOrDismissed();
        }

        @Override
@@ -3560,12 +3544,18 @@ public class NotificationStackScrollLayout extends ViewGroup
            super.snapChild(animView, targetLeft, velocity);
            onDragCancelled(animView);
            if (targetLeft == 0) {
                handleGearCoveredOrDismissed();
            }
        }

        private void handleGearCoveredOrDismissed() {
            cancelCheckForDrag();
            setSnappedToGear(false);
            if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) {
                mGearExposedView = null;
            }
        }


        @Override
        public boolean handleUpEvent(MotionEvent ev, View animView, float velocity,
                float translation) {
@@ -3624,9 +3614,10 @@ public class NotificationStackScrollLayout extends ViewGroup
            final float target = mCurrIconRow.isIconOnLeft() ? snapBackThreshold
                    : -snapBackThreshold;
            mGearExposedView = mTranslatingParentView;
            if (mGearDisplayedListener != null
                    && (animView instanceof ExpandableNotificationRow)) {
                mGearDisplayedListener.onGearDisplayed((ExpandableNotificationRow) animView);
            if (animView instanceof ExpandableNotificationRow) {
                MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
                        ((ExpandableNotificationRow) animView).getStatusBarNotification()
                                .getPackageName());
            }
            if (mCurrIconRow != null) {
                mCurrIconRow.setSnapping(true);
@@ -3637,6 +3628,9 @@ public class NotificationStackScrollLayout extends ViewGroup
        }

        private boolean swipedEnoughToShowGear(View animView) {
            if (mTranslatingParentView == null) {
                return false;
            }
            final float snapBackThreshold = getSpaceForGear(animView);
            final float translation = getTranslation(animView);
            final boolean fromLeft = translation > 0;
@@ -3682,6 +3676,37 @@ public class NotificationStackScrollLayout extends ViewGroup
            }
        }

        public void closeControlsIfOutsideTouch(MotionEvent ev) {
            NotificationGuts guts = mPhoneStatusBar.getExposedGuts();
            View view = null;
            int height = 0;
            if (guts != null) {
                // Checking guts
                view = guts;
                height = guts.getActualHeight();
            } else if (mCurrIconRow != null && mCurrIconRow.isVisible()
                    && mTranslatingParentView != null) {
                // Checking gear
                view = mTranslatingParentView;
                height = ((ExpandableView) mTranslatingParentView).getActualHeight();
            }
            if (view != null) {
                final int rx = (int) ev.getRawX();
                final int ry = (int) ev.getRawY();

                getLocationOnScreen(mTempInt2);
                int[] location = new int[2];
                view.getLocationOnScreen(location);
                final int x = location[0] - mTempInt2[0];
                final int y = location[1] - mTempInt2[1];
                Rect rect = new Rect(x, y, x + view.getWidth(), y + height);
                if (!rect.contains((int) rx, (int) ry)) {
                    // Touch was outside visible guts / gear notification, close what's visible
                    mPhoneStatusBar.dismissPopups(-1, -1, true /* resetGear */, true /* animate */);
                }
            }
        }

        /**
         * Returns whether the gesture is towards the gear location or not.
         */
@@ -3729,6 +3754,9 @@ public class NotificationStackScrollLayout extends ViewGroup
        private final class CheckForDrag implements Runnable {
            @Override
            public void run() {
                if (mTranslatingParentView == null) {
                    return;
                }
                final float translation = getTranslation(mTranslatingParentView);
                final float absTransX = Math.abs(translation);
                final float bounceBackToGearWidth = getSpaceForGear(mTranslatingParentView);
@@ -3744,20 +3772,24 @@ public class NotificationStackScrollLayout extends ViewGroup
            }
        }

        private void resetExposedGearView() {
            if (mGearExposedView == null || mGearExposedView == mTranslatingParentView) {
        public void resetExposedGearView(boolean animate, boolean force) {
            if (mGearExposedView == null
                    || (!force && mGearExposedView == mTranslatingParentView)) {
                // If no gear is showing or it's showing for this view we do nothing.
                return;
            }

            final View prevGearExposedView = mGearExposedView;
            mGearExposedView = null;
            mGearSnappedTo = false;
            if (animate) {
                Animator anim = getViewTranslationAnimator(prevGearExposedView,
                        0 /* leftTarget */, null /* updateListener */);
                if (anim != null) {
                    anim.start();
                }
            } else if (mGearExposedView instanceof ExpandableNotificationRow) {
                ((ExpandableNotificationRow) mGearExposedView).resetTranslation();
            }
            mGearExposedView = null;
            mGearSnappedTo = false;
        }
    }

@@ -3773,6 +3805,14 @@ public class NotificationStackScrollLayout extends ViewGroup
        }
    }

    public void resetExposedGearView(boolean animate, boolean force) {
        mSwipeHelper.resetExposedGearView(animate, force);
    }

    public void closeControlsIfOutsideTouch(MotionEvent ev) {
        mSwipeHelper.closeControlsIfOutsideTouch(ev);
    }

    static class AnimationEvent {

        static AnimationFilter[] FILTERS = new AnimationFilter[] {