Scroll to remote input view
Bug: 27668960
Fixes: 27668960
Change-Id: Ie8f7858257922362b289ea4e4e22e689e1405e58
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 e5e3caf..560dbac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1731,7 +1731,7 @@
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- mNavigationBarBottomHeight = insets.getSystemWindowInsetBottom();
+ mNavigationBarBottomHeight = insets.getStableInsetBottom();
updateMaxHeadsUpTranslation();
return insets;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
index f0df706..960515b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
@@ -75,7 +75,7 @@
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- setPadding(0, 0, 0, insets.getSystemWindowInsetBottom());
+ setPadding(0, 0, 0, insets.getStableInsetBottom());
return insets;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index ada7450..b271380 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -138,11 +138,7 @@
mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
}
- if (state.remoteInputActive) {
- mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
- } else {
- mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
- }
+ mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
}
private void applyHeight(State state) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 3a0336b..1f4ef4a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -46,7 +46,7 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.RemoteInputController;
-import com.android.systemui.statusbar.stack.LongPressCancelable;
+import com.android.systemui.statusbar.stack.ScrollContainer;
/**
* Host for the remote input.
@@ -67,7 +67,9 @@
private RemoteInputController mController;
private NotificationData.Entry mEntry;
- private LongPressCancelable mLongPressCancelable;
+
+ private ScrollContainer mScrollContainer;
+ private View mScrollContainerChild;
public RemoteInputView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -106,7 +108,7 @@
mEditText.setOnClickListener(this);
mEditText.addTextChangedListener(this);
mEditText.setInnerFocusable(false);
- mEditText.mDefocusListener = this;
+ mEditText.mRemoteInputView = this;
}
private void sendRemoteInput() {
@@ -237,23 +239,34 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- if (mLongPressCancelable == null) {
- ViewParent p = getParent();
- while (p != null) {
- if (p instanceof LongPressCancelable) {
- mLongPressCancelable = (LongPressCancelable) p;
- break;
- }
- p = p.getParent();
- }
- }
- if (mLongPressCancelable != null) {
- mLongPressCancelable.requestDisallowLongPress();
+ findScrollContainer();
+ if (mScrollContainer != null) {
+ mScrollContainer.requestDisallowLongPress();
}
}
return super.onInterceptTouchEvent(ev);
}
+ public boolean requestScrollTo() {
+ findScrollContainer();
+ mScrollContainer.scrollTo(mScrollContainerChild);
+ return true;
+ }
+
+ private void findScrollContainer() {
+ if (mScrollContainer == null) {
+ ViewParent p = this;
+ while (p != null) {
+ if (p.getParent() instanceof ScrollContainer) {
+ mScrollContainer = (ScrollContainer) p.getParent();
+ mScrollContainerChild = (View) p;
+ break;
+ }
+ p = p.getParent();
+ }
+ }
+ }
+
/**
* An EditText that changes appearance based on whether it's focusable and becomes
* un-focusable whenever the user navigates away from it or it becomes invisible.
@@ -261,7 +274,7 @@
public static class RemoteEditText extends EditText {
private final Drawable mBackground;
- private RemoteInputView mDefocusListener;
+ private RemoteInputView mRemoteInputView;
boolean mShowImeOnInputConnection;
public RemoteEditText(Context context, AttributeSet attrs) {
@@ -270,13 +283,13 @@
}
private void defocusIfNeeded() {
- if (mDefocusListener.mEntry.row.isChangingPosition()) {
+ if (mRemoteInputView != null && mRemoteInputView.mEntry.row.isChangingPosition()) {
return;
}
if (isFocusable() && isEnabled()) {
setInnerFocusable(false);
- if (mDefocusListener != null) {
- mDefocusListener.onDefocus();
+ if (mRemoteInputView != null) {
+ mRemoteInputView.onDefocus();
}
mShowImeOnInputConnection = false;
}
@@ -300,13 +313,6 @@
}
@Override
- public boolean requestRectangleOnScreen(Rect r) {
- r.top = mScrollY;
- r.bottom = mScrollY + (mBottom - mTop);
- return super.requestRectangleOnScreen(r);
- }
-
- @Override
public void getFocusedRect(Rect r) {
super.getFocusedRect(r);
r.top = mScrollY;
@@ -314,6 +320,11 @@
}
@Override
+ public boolean requestRectangleOnScreen(Rect rectangle) {
+ return mRemoteInputView.requestScrollTo();
+ }
+
+ @Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
defocusIfNeeded();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 686a712..9d3c2b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -43,6 +43,7 @@
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.WindowInsets;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.OverScroller;
@@ -83,7 +84,7 @@
public class NotificationStackScrollLayout extends ViewGroup
implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter,
ExpandableView.OnHeightChangedListener, NotificationGroupManager.OnGroupChangeListener,
- SettingsIconRowListener, LongPressCancelable {
+ SettingsIconRowListener, ScrollContainer {
public static final float BACKGROUND_ALPHA_DIMMED = 0.7f;
private static final String TAG = "StackScroller";
@@ -134,7 +135,7 @@
private int mPaddingBetweenElements;
private int mIncreasedPaddingBetweenElements;
private int mTopPadding;
- private int mCollapseSecondCardPadding;
+ private int mBottomInset = 0;
/**
* The algorithm which calculates the properties for our children
@@ -206,6 +207,7 @@
private float mStackTranslation;
private float mTopPaddingOverflow;
private boolean mDontReportNextOverScroll;
+ private boolean mDontClampNextScroll;
private boolean mRequestViewResizeAnimationOnLayout;
private boolean mNeedViewResizeAnimation;
private View mExpandedGroupView;
@@ -905,6 +907,45 @@
mScrollingEnabled = enable;
}
+ public void scrollTo(View v) {
+ ExpandableView expandableView = (ExpandableView) v;
+ int positionInLinearLayout = getPositionInLinearLayout(v);
+
+ int targetScroll = positionInLinearLayout + expandableView.getActualHeight() +
+ mBottomInset - getHeight() + getTopPadding();
+ if (mOwnScrollY < targetScroll) {
+ mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY);
+ mDontReportNextOverScroll = true;
+ postInvalidateOnAnimation();
+ }
+ }
+
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ mBottomInset = Math.max(0, insets.getSystemWindowInsetBottom()
+ - (getRootView().getHeight() - getHeight()));
+
+ int range = getScrollRange();
+ if (mOwnScrollY > range) {
+ // HACK: We're repeatedly getting staggered insets here while the IME is
+ // animating away. To work around that we'll wait until things have settled.
+ removeCallbacks(mReclamp);
+ postDelayed(mReclamp, 50);
+ }
+ return insets;
+ }
+
+ private Runnable mReclamp = new Runnable() {
+ @Override
+ public void run() {
+ int range = getScrollRange();
+ mScroller.startScroll(mScrollX, mOwnScrollY, 0, range - mOwnScrollY);
+ mDontReportNextOverScroll = true;
+ mDontClampNextScroll = true;
+ postInvalidateOnAnimation();
+ }
+ };
+
public void setExpandingEnabled(boolean enable) {
mExpandHelper.setEnabled(enable);
}
@@ -1237,7 +1278,7 @@
int y = mScroller.getCurrY();
if (oldX != x || oldY != y) {
- final int range = getScrollRange();
+ int range = getScrollRange();
if (y < 0 && oldY >= 0 || y > range && oldY <= range) {
float currVelocity = mScroller.getCurrVelocity();
if (currVelocity >= mMinimumVelocity) {
@@ -1245,6 +1286,9 @@
}
}
+ if (mDontClampNextScroll) {
+ range = Math.max(range, oldY);
+ }
overScrollBy(x - oldX, y - oldY, oldX, oldY, 0, range,
0, (int) (mMaxOverScroll), false);
onScrollChanged(mScrollX, mOwnScrollY, oldX, oldY);
@@ -1252,6 +1296,8 @@
// Keep on drawing until the animation has finished.
postInvalidateOnAnimation();
+ } else {
+ mDontClampNextScroll = false;
}
}
@@ -1455,7 +1501,9 @@
- firstChild.getMinHeight());
}
}
- return scrollRange;
+ int imeOverlap = Math.max(0,
+ getContentHeight() - (getHeight() - mBottomInset));
+ return scrollRange + imeOverlap;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ScrollContainer.java
similarity index 72%
rename from packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/stack/ScrollContainer.java
index 05f0c07..a35465e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ScrollContainer.java
@@ -16,13 +16,21 @@
package com.android.systemui.statusbar.stack;
+import android.view.View;
+
/**
- * Interface for container layouts that listen for long presses. A child that
- * wants to handle long press can use this to cancel the parents long press logic.
+ * Interface for container layouts that scroll and listen for long presses. A child that
+ * wants to handle long press can use this to cancel the parents long press logic or request
+ * to be made visible by scrolling to it.
*/
-public interface LongPressCancelable {
+public interface ScrollContainer {
/**
* Request that the view does not perform long press for the current touch.
*/
void requestDisallowLongPress();
+
+ /**
+ * Request that the view is made visible by scrolling to it.
+ */
+ void scrollTo(View v);
}