Merge "Keep RemoteInputView visible when focused" into nyc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
046f2c80ae
@@ -21,7 +21,7 @@
|
|||||||
<com.android.internal.widget.NotificationActionListLayout
|
<com.android.internal.widget.NotificationActionListLayout
|
||||||
android:id="@+id/actions"
|
android:id="@+id/actions"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="56dp"
|
android:layout_height="@dimen/notification_action_list_height"
|
||||||
android:paddingEnd="4dp"
|
android:paddingEnd="4dp"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
|
|||||||
@@ -152,6 +152,9 @@
|
|||||||
<!-- The margin on the end of the content view with a picture.-->
|
<!-- The margin on the end of the content view with a picture.-->
|
||||||
<dimen name="notification_content_picture_margin">56dp</dimen>
|
<dimen name="notification_content_picture_margin">56dp</dimen>
|
||||||
|
|
||||||
|
<!-- The height of the notification action list -->
|
||||||
|
<dimen name="notification_action_list_height">56dp</dimen>
|
||||||
|
|
||||||
<!-- height of the content margin to accomodate for the header -->
|
<!-- height of the content margin to accomodate for the header -->
|
||||||
<dimen name="notification_content_margin_top">37.5dp</dimen>
|
<dimen name="notification_content_margin_top">37.5dp</dimen>
|
||||||
|
|
||||||
|
|||||||
@@ -2584,6 +2584,8 @@
|
|||||||
<java-symbol type="dimen" name="input_extract_action_button_width" />
|
<java-symbol type="dimen" name="input_extract_action_button_width" />
|
||||||
<java-symbol type="dimen" name="input_extract_action_button_height" />
|
<java-symbol type="dimen" name="input_extract_action_button_height" />
|
||||||
|
|
||||||
|
<java-symbol type="dimen" name="notification_action_list_height" />
|
||||||
|
|
||||||
<!-- TV Remote Service package -->
|
<!-- TV Remote Service package -->
|
||||||
<java-symbol type="string" name="config_tvRemoteServicePackage" />
|
<java-symbol type="string" name="config_tvRemoteServicePackage" />
|
||||||
|
|
||||||
|
|||||||
@@ -374,10 +374,42 @@ public class NotificationContentView extends FrameLayout {
|
|||||||
mContentHeight = Math.max(Math.min(contentHeight, getHeight()), getMinHeight());;
|
mContentHeight = Math.max(Math.min(contentHeight, getHeight()), getMinHeight());;
|
||||||
mUnrestrictedContentHeight = Math.max(contentHeight, getMinHeight());
|
mUnrestrictedContentHeight = Math.max(contentHeight, getMinHeight());
|
||||||
selectLayout(mAnimate /* animate */, false /* force */);
|
selectLayout(mAnimate /* animate */, false /* force */);
|
||||||
|
|
||||||
|
int minHeightHint = getMinContentHeightHint();
|
||||||
|
|
||||||
|
NotificationViewWrapper wrapper = getVisibleWrapper(mVisibleType);
|
||||||
|
if (wrapper != null) {
|
||||||
|
wrapper.setContentHeight(mContentHeight, minHeightHint);
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper = getVisibleWrapper(mTransformationStartVisibleType);
|
||||||
|
if (wrapper != null) {
|
||||||
|
wrapper.setContentHeight(mContentHeight, minHeightHint);
|
||||||
|
}
|
||||||
|
|
||||||
updateClipping();
|
updateClipping();
|
||||||
invalidateOutline();
|
invalidateOutline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the minimum apparent height that the wrapper should allow for the purpose
|
||||||
|
* of aligning elements at the bottom edge. If this is larger than the content
|
||||||
|
* height, the notification is clipped instead of being further shrunk.
|
||||||
|
*/
|
||||||
|
private int getMinContentHeightHint() {
|
||||||
|
if (mIsChildInGroup && (mVisibleType == VISIBLE_TYPE_SINGLELINE
|
||||||
|
|| mTransformationStartVisibleType == VISIBLE_TYPE_SINGLELINE)) {
|
||||||
|
return mContext.getResources().getDimensionPixelSize(
|
||||||
|
com.android.internal.R.dimen.notification_action_list_height);
|
||||||
|
}
|
||||||
|
if (mHeadsUpChild != null) {
|
||||||
|
return mHeadsUpChild.getHeight();
|
||||||
|
} else {
|
||||||
|
return mContractedChild.getHeight() + mContext.getResources().getDimensionPixelSize(
|
||||||
|
com.android.internal.R.dimen.notification_action_list_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateContentTransformation() {
|
private void updateContentTransformation() {
|
||||||
int visibleType = calculateVisibleType();
|
int visibleType = calculateVisibleType();
|
||||||
if (visibleType != mVisibleType) {
|
if (visibleType != mVisibleType) {
|
||||||
@@ -493,11 +525,15 @@ public class NotificationContentView extends FrameLayout {
|
|||||||
} else {
|
} else {
|
||||||
int visibleType = calculateVisibleType();
|
int visibleType = calculateVisibleType();
|
||||||
if (visibleType != mVisibleType || force) {
|
if (visibleType != mVisibleType || force) {
|
||||||
View visibleView = getViewForVisibleType(visibleType);
|
View visibleView = getViewForVisibleType(visibleType);
|
||||||
if (visibleView != null) {
|
if (visibleView != null) {
|
||||||
visibleView.setVisibility(VISIBLE);
|
visibleView.setVisibility(VISIBLE);
|
||||||
transferRemoteInputFocus(visibleType);
|
transferRemoteInputFocus(visibleType);
|
||||||
}
|
}
|
||||||
|
NotificationViewWrapper visibleWrapper = getVisibleWrapper(visibleType);
|
||||||
|
if (visibleWrapper != null) {
|
||||||
|
visibleWrapper.setContentHeight(mContentHeight, getMinContentHeightHint());
|
||||||
|
}
|
||||||
|
|
||||||
if (animate && ((visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
|
if (animate && ((visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
|
||||||
|| (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null)
|
|| (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null)
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.statusbar.notification;
|
||||||
|
|
||||||
|
import android.text.Layout;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Pools;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A transform state of the action list
|
||||||
|
*/
|
||||||
|
public class ActionListTransformState extends TransformState {
|
||||||
|
|
||||||
|
private static Pools.SimplePool<ActionListTransformState> sInstancePool
|
||||||
|
= new Pools.SimplePool<>(40);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean sameAs(TransformState otherState) {
|
||||||
|
return otherState instanceof ActionListTransformState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ActionListTransformState obtain() {
|
||||||
|
ActionListTransformState instance = sInstancePool.acquire();
|
||||||
|
if (instance != null) {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
return new ActionListTransformState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void resetTransformedView() {
|
||||||
|
// We need to keep the Y transformation, because this is used to keep the action list
|
||||||
|
// aligned at the bottom, unrelated to transforms.
|
||||||
|
float y = getTransformedView().getTranslationY();
|
||||||
|
super.resetTransformedView();
|
||||||
|
getTransformedView().setTranslationY(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recycle() {
|
||||||
|
super.recycle();
|
||||||
|
sInstancePool.release(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,6 +41,10 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
|
|||||||
private ProgressBar mProgressBar;
|
private ProgressBar mProgressBar;
|
||||||
private TextView mTitle;
|
private TextView mTitle;
|
||||||
private TextView mText;
|
private TextView mText;
|
||||||
|
private View mActionsContainer;
|
||||||
|
|
||||||
|
private int mContentHeight;
|
||||||
|
private int mMinHeightHint;
|
||||||
|
|
||||||
protected NotificationTemplateViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
|
protected NotificationTemplateViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
|
||||||
super(ctx, view, row);
|
super(ctx, view, row);
|
||||||
@@ -123,6 +127,7 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
|
|||||||
// It's still a viewstub
|
// It's still a viewstub
|
||||||
mProgressBar = null;
|
mProgressBar = null;
|
||||||
}
|
}
|
||||||
|
mActionsContainer = mView.findViewById(com.android.internal.R.id.actions_container);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -225,4 +230,21 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
|
|||||||
(int) (gSource * (1f - t) + gTarget * t),
|
(int) (gSource * (1f - t) + gTarget * t),
|
||||||
(int) (bSource * (1f - t) + bTarget * t));
|
(int) (bSource * (1f - t) + bTarget * t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setContentHeight(int contentHeight, int minHeightHint) {
|
||||||
|
super.setContentHeight(contentHeight, minHeightHint);
|
||||||
|
|
||||||
|
mContentHeight = contentHeight;
|
||||||
|
mMinHeightHint = minHeightHint;
|
||||||
|
updateActionOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateActionOffset() {
|
||||||
|
if (mActionsContainer != null) {
|
||||||
|
// We should never push the actions higher than they are in the headsup view.
|
||||||
|
int constrainedContentHeight = Math.max(mContentHeight, mMinHeightHint);
|
||||||
|
mActionsContainer.setTranslationY(constrainedContentHeight - mView.getHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,4 +158,7 @@ public abstract class NotificationViewWrapper implements TransformableView {
|
|||||||
|
|
||||||
public void setShowingLegacyBackground(boolean showing) {
|
public void setShowingLegacyBackground(boolean showing) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setContentHeight(int contentHeight, int minHeightHint) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -374,6 +374,11 @@ public class TransformState {
|
|||||||
result.initFrom(view);
|
result.initFrom(view);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
if (view.getId() == com.android.internal.R.id.actions_container) {
|
||||||
|
ActionListTransformState result = ActionListTransformState.obtain();
|
||||||
|
result.initFrom(view);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
if (view instanceof NotificationHeaderView) {
|
if (view instanceof NotificationHeaderView) {
|
||||||
HeaderTransformState result = HeaderTransformState.obtain();
|
HeaderTransformState result = HeaderTransformState.obtain();
|
||||||
result.initFrom(view);
|
result.initFrom(view);
|
||||||
@@ -467,7 +472,7 @@ public class TransformState {
|
|||||||
resetTransformedView();
|
resetTransformedView();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetTransformedView() {
|
protected void resetTransformedView() {
|
||||||
mTransformedView.setTranslationX(0);
|
mTransformedView.setTranslationX(0);
|
||||||
mTransformedView.setTranslationY(0);
|
mTransformedView.setTranslationY(0);
|
||||||
mTransformedView.setScaleX(1.0f);
|
mTransformedView.setScaleX(1.0f);
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
|
|||||||
|
|
||||||
public boolean requestScrollTo() {
|
public boolean requestScrollTo() {
|
||||||
findScrollContainer();
|
findScrollContainer();
|
||||||
mScrollContainer.scrollTo(mScrollContainerChild);
|
mScrollContainer.lockScrollTo(mScrollContainerChild);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -243,6 +243,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
|||||||
= new ViewTreeObserver.OnPreDrawListener() {
|
= new ViewTreeObserver.OnPreDrawListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreDraw() {
|
public boolean onPreDraw() {
|
||||||
|
updateForcedScroll();
|
||||||
updateChildren();
|
updateChildren();
|
||||||
mChildrenUpdateRequested = false;
|
mChildrenUpdateRequested = false;
|
||||||
getViewTreeObserver().removeOnPreDrawListener(this);
|
getViewTreeObserver().removeOnPreDrawListener(this);
|
||||||
@@ -334,6 +335,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
|||||||
private boolean mDrawBackgroundAsSrc;
|
private boolean mDrawBackgroundAsSrc;
|
||||||
private boolean mFadedOut;
|
private boolean mFadedOut;
|
||||||
private boolean mGroupExpandedForMeasure;
|
private boolean mGroupExpandedForMeasure;
|
||||||
|
private View mForcedScroll;
|
||||||
private float mBackgroundFadeAmount = 1.0f;
|
private float mBackgroundFadeAmount = 1.0f;
|
||||||
private static final Property<NotificationStackScrollLayout, Float> BACKGROUND_FADE =
|
private static final Property<NotificationStackScrollLayout, Float> BACKGROUND_FADE =
|
||||||
new FloatProperty<NotificationStackScrollLayout>("backgroundFade") {
|
new FloatProperty<NotificationStackScrollLayout>("backgroundFade") {
|
||||||
@@ -591,6 +593,23 @@ public class NotificationStackScrollLayout extends ViewGroup
|
|||||||
clampScrollPosition();
|
clampScrollPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateForcedScroll() {
|
||||||
|
if (mForcedScroll != null && (!mForcedScroll.hasFocus()
|
||||||
|
|| !mForcedScroll.isAttachedToWindow())) {
|
||||||
|
mForcedScroll = null;
|
||||||
|
}
|
||||||
|
if (mForcedScroll != null) {
|
||||||
|
ExpandableView expandableView = (ExpandableView) mForcedScroll;
|
||||||
|
int positionInLinearLayout = getPositionInLinearLayout(expandableView);
|
||||||
|
int targetScroll = targetScrollForView(expandableView, positionInLinearLayout);
|
||||||
|
|
||||||
|
targetScroll = Math.max(0, Math.min(targetScroll, getScrollRange()));
|
||||||
|
if (mOwnScrollY < targetScroll || positionInLinearLayout < mOwnScrollY) {
|
||||||
|
mOwnScrollY = targetScroll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void requestChildrenUpdate() {
|
private void requestChildrenUpdate() {
|
||||||
if (!mChildrenUpdateRequested) {
|
if (!mChildrenUpdateRequested) {
|
||||||
getViewTreeObserver().addOnPreDrawListener(mChildrenUpdater);
|
getViewTreeObserver().addOnPreDrawListener(mChildrenUpdater);
|
||||||
@@ -978,11 +997,19 @@ public class NotificationStackScrollLayout extends ViewGroup
|
|||||||
mScrollingEnabled = enable;
|
mScrollingEnabled = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lockScrollTo(View v) {
|
||||||
|
if (mForcedScroll == v) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mForcedScroll = v;
|
||||||
|
scrollTo(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean scrollTo(View v) {
|
public boolean scrollTo(View v) {
|
||||||
ExpandableView expandableView = (ExpandableView) v;
|
ExpandableView expandableView = (ExpandableView) v;
|
||||||
int positionInLinearLayout = getPositionInLinearLayout(v);
|
int targetScroll = targetScrollForView(expandableView, getPositionInLinearLayout(v));
|
||||||
int targetScroll = positionInLinearLayout + expandableView.getIntrinsicHeight() +
|
|
||||||
getImeInset() - getHeight() + getTopPadding();
|
|
||||||
|
|
||||||
if (mOwnScrollY < targetScroll) {
|
if (mOwnScrollY < targetScroll) {
|
||||||
mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY);
|
mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY);
|
||||||
@@ -993,6 +1020,15 @@ public class NotificationStackScrollLayout extends ViewGroup
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the scroll necessary to make the bottom edge of {@param v} align with the top of
|
||||||
|
* the IME.
|
||||||
|
*/
|
||||||
|
private int targetScrollForView(ExpandableView v, int positionInLinearLayout) {
|
||||||
|
return positionInLinearLayout + v.getIntrinsicHeight() +
|
||||||
|
getImeInset() - getHeight() + getTopPadding();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
|
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
|
||||||
mBottomInset = insets.getSystemWindowInsetBottom();
|
mBottomInset = insets.getSystemWindowInsetBottom();
|
||||||
@@ -1111,6 +1147,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
|||||||
if (ev.getY() < mQsContainer.getBottom()) {
|
if (ev.getY() < mQsContainer.getBottom()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
mForcedScroll = null;
|
||||||
initVelocityTrackerIfNotExists();
|
initVelocityTrackerIfNotExists();
|
||||||
mVelocityTracker.addMovement(ev);
|
mVelocityTracker.addMovement(ev);
|
||||||
|
|
||||||
@@ -2786,6 +2823,14 @@ public class NotificationStackScrollLayout extends ViewGroup
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearChildFocus(View child) {
|
||||||
|
super.clearChildFocus(child);
|
||||||
|
if (mForcedScroll == child) {
|
||||||
|
mForcedScroll = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void requestDisallowLongPress() {
|
public void requestDisallowLongPress() {
|
||||||
removeLongPressCallback();
|
removeLongPressCallback();
|
||||||
|
|||||||
@@ -35,6 +35,12 @@ public interface ScrollContainer {
|
|||||||
*/
|
*/
|
||||||
boolean scrollTo(View v);
|
boolean scrollTo(View v);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like {@link #scrollTo(View)}, but keeps the scroll locked until the user
|
||||||
|
* scrolls, or {@param v} loses focus or is detached.
|
||||||
|
*/
|
||||||
|
void lockScrollTo(View v);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request that the view does not dismiss for the current touch.
|
* Request that the view does not dismiss for the current touch.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user