Position panel dynamically when expanding

Bug: 17125022
Change-Id: Ia39aa40c27958a6ba4eb183522d22bfad958fe5e
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 96e9543..e20451d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -187,6 +187,9 @@
     private boolean mExpansionIsFromHeadsUp;
     private int mBottomBarHeight;
     private boolean mExpandingFromHeadsUp;
+    private int mPositionMinSideMargin;
+    private int mLastOrientation = -1;
+
     private Runnable mHeadsUpExistenceChangedRunnable = new Runnable() {
         @Override
         public void run() {
@@ -236,6 +239,7 @@
         mAfforanceHelper = new KeyguardAffordanceHelper(this, getContext());
         mSecureCameraLaunchManager =
                 new SecureCameraLaunchManager(getContext(), mKeyguardBottomArea);
+        mLastOrientation = getResources().getConfiguration().orientation;
 
         // recompute internal state when qspanel height changes
         mQsContainer.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@@ -268,6 +272,8 @@
                 getResources().getDimensionPixelSize(R.dimen.notification_scrim_wait_distance);
         mQsFalsingThreshold = getResources().getDimensionPixelSize(
                 R.dimen.qs_falsing_threshold);
+        mPositionMinSideMargin = getResources().getDimensionPixelSize(
+                R.dimen.notification_panel_min_side_margin);
     }
 
     public void updateResources() {
@@ -692,6 +698,9 @@
         if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && handleQSTouch(event)) {
             return true;
         }
+        if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) {
+            updateVerticalPanelPosition(event.getX());
+        }
         super.onTouchEvent(event);
         return true;
     }
@@ -740,7 +749,7 @@
     }
 
     private boolean isInQsArea(float x, float y) {
-        return (x >= mScrollView.getLeft() && x <= mScrollView.getRight()) &&
+        return (x >= mScrollView.getX() && x <= mScrollView.getX() + mScrollView.getWidth()) &&
                 (y <= mNotificationStackScroller.getBottomMostNotificationBottom()
                 || y <= mQsContainer.getY() + mQsContainer.getHeight());
     }
@@ -939,7 +948,7 @@
             mKeyguardStatusBar.setAlpha(1f);
             mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE);
         }
-
+        resetVerticalPanelPosition();
         updateQsState();
     }
 
@@ -1376,7 +1385,7 @@
             return false;
         }
         View header = mKeyguardShowing ? mKeyguardStatusBar : mHeader;
-        boolean onHeader = x >= header.getLeft() && x <= header.getRight()
+        boolean onHeader = x >= header.getX() && x <= header.getX() + header.getWidth()
                 && y >= header.getTop() && y <= header.getBottom();
         if (mQsExpanded) {
             return onHeader || (mScrollView.isScrolledToBottom() && yDiff < 0) && isInQsArea(x, y);
@@ -1771,6 +1780,10 @@
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
         mAfforanceHelper.onConfigurationChanged();
+        if (newConfig.orientation != mLastOrientation) {
+            resetVerticalPanelPosition();
+        }
+        mLastOrientation = newConfig.orientation;
     }
 
     @Override
@@ -2187,4 +2200,42 @@
             mExpandingFromHeadsUp = true;
         }
     }
+
+    @Override
+    protected void onClosingFinished() {
+        super.onClosingFinished();
+        resetVerticalPanelPosition();
+    }
+
+    /**
+     * Updates the vertical position of the panel so it is positioned closer to the touch
+     * responsible for opening the panel.
+     *
+     * @param x the x-coordinate the touch event
+     */
+    private void updateVerticalPanelPosition(float x) {
+        if (mNotificationStackScroller.getWidth() * 1.75f > getWidth()) {
+            resetVerticalPanelPosition();
+            return;
+        }
+        float leftMost = mPositionMinSideMargin + mNotificationStackScroller.getWidth() / 2;
+        float rightMost = getWidth() - mPositionMinSideMargin
+                - mNotificationStackScroller.getWidth() / 2;
+        if (Math.abs(x - getWidth() / 2) < mNotificationStackScroller.getWidth() / 4) {
+            x = getWidth() / 2;
+        }
+        x = Math.min(rightMost, Math.max(leftMost, x));
+        setVerticalPanelTranslation(x -
+                (mNotificationStackScroller.getLeft() + mNotificationStackScroller.getWidth()/2));
+     }
+
+    private void resetVerticalPanelPosition() {
+        setVerticalPanelTranslation(0f);
+    }
+
+    private void setVerticalPanelTranslation(float translation) {
+        mNotificationStackScroller.setTranslationX(translation);
+        mScrollView.setTranslationX(translation);
+        mHeader.setTranslationX(translation);
+    }
 }