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

Commit cd562bb9 authored by Johannes Gallmann's avatar Johannes Gallmann
Browse files

Reapply changes of inline reply CL

Just before merging ag/20462188, I had to change the flag ID because there was a conflict. Unfortunately, a very stupid mistake happened during this minor fix. I changed the flag ID in an old version of the CL and uploaded that old version (as can be seen in the changelog of the latest uploaded patch in that CL). Therefore, this CL reapplies all changes that were undone in the latest patchset of ag/20462188 and ag/20462188.

Bug: 174148361
Test: atest RemoteInputViewTest, Manual, i.e. posting various types of Notifications from the Notify2-RVC application with a reply action added to them. Then observing the animations visually and analyzing frames from screen recordings.
Change-Id: I0f9deb15e8fae361ef6ebb6ff0119d2ee6888372
parent 8118ea49
Loading
Loading
Loading
Loading
+0 −3
Original line number Original line Diff line number Diff line
@@ -464,9 +464,6 @@ public class NotificationRemoteInputManager implements Dumpable {
        riv.getController().setRemoteInputs(inputs);
        riv.getController().setRemoteInputs(inputs);
        riv.getController().setEditedSuggestionInfo(editedSuggestionInfo);
        riv.getController().setEditedSuggestionInfo(editedSuggestionInfo);
        ViewGroup parent = view.getParent() != null ? (ViewGroup) view.getParent() : null;
        ViewGroup parent = view.getParent() != null ? (ViewGroup) view.getParent() : null;
        if (parent != null) {
            riv.setDefocusTargetHeight(parent.getHeight());
        }
        riv.focusAnimated(parent);
        riv.focusAnimated(parent);
        if (userMessageContent != null) {
        if (userMessageContent != null) {
            riv.setEditTextContent(userMessageContent);
            riv.setEditTextContent(userMessageContent);
+58 −52
Original line number Original line Diff line number Diff line
@@ -47,6 +47,7 @@ import android.view.OnReceiveContentListener;
import android.view.View;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.ViewGroup;
import android.view.ViewGroupOverlay;
import android.view.ViewRootImpl;
import android.view.ViewRootImpl;
import android.view.WindowInsets;
import android.view.WindowInsets;
import android.view.WindowInsetsAnimation;
import android.view.WindowInsetsAnimation;
@@ -57,7 +58,6 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout;
@@ -133,6 +133,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
    private RevealParams mRevealParams;
    private RevealParams mRevealParams;
    private Rect mContentBackgroundBounds;
    private Rect mContentBackgroundBounds;
    private boolean mIsFocusAnimationFlagActive;
    private boolean mIsFocusAnimationFlagActive;
    private boolean mIsAnimatingAppearance = false;


    // TODO(b/193539698): move these to a Controller
    // TODO(b/193539698): move these to a Controller
    private RemoteInputController mController;
    private RemoteInputController mController;
@@ -142,10 +143,6 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
    private boolean mSending;
    private boolean mSending;
    private NotificationViewWrapper mWrapper;
    private NotificationViewWrapper mWrapper;


    private Integer mDefocusTargetHeight = null;
    private boolean mIsAnimatingAppearance = false;


    // TODO(b/193539698): remove this; views shouldn't have access to their controller, and places
    // TODO(b/193539698): remove this; views shouldn't have access to their controller, and places
    //  that need the controller shouldn't have access to the view
    //  that need the controller shouldn't have access to the view
    private RemoteInputViewController mViewController;
    private RemoteInputViewController mViewController;
@@ -423,18 +420,6 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        return mIsAnimatingAppearance;
        return mIsAnimatingAppearance;
    }
    }


    /**
     * View will ensure to use at most the provided defocusTargetHeight, when defocusing animated.
     * This is to ensure that the parent can resize itself to the targetHeight while the defocus
     * animation of the RemoteInputView is running.
     *
     * @param defocusTargetHeight The target height the parent will resize itself to. If null, the
     *                            RemoteInputView will not resize itself.
     */
    public void setDefocusTargetHeight(Integer defocusTargetHeight) {
        mDefocusTargetHeight = defocusTargetHeight;
    }

    @VisibleForTesting
    @VisibleForTesting
    void onDefocus(boolean animate, boolean logClose) {
    void onDefocus(boolean animate, boolean logClose) {
        mController.removeRemoteInput(mEntry, mToken);
        mController.removeRemoteInput(mEntry, mToken);
@@ -443,35 +428,28 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        // During removal, we get reattached and lose focus. Not hiding in that
        // During removal, we get reattached and lose focus. Not hiding in that
        // case to prevent flicker.
        // case to prevent flicker.
        if (!mRemoved) {
        if (!mRemoved) {
            if (animate && mIsFocusAnimationFlagActive) {
            ViewGroup parent = (ViewGroup) getParent();
                Animator animator = getDefocusAnimator();
            if (animate && parent != null && mIsFocusAnimationFlagActive) {


                // When defocusing, the notification needs to shrink. Therefore, we need to free
                // up the space that is needed for the RemoteInputView. This is done by setting
                // a negative top margin of the height difference of the RemoteInputView and its
                // sibling (the actions_container_layout containing the Reply button)
                if (mDefocusTargetHeight != null && mDefocusTargetHeight < getHeight()
                        && mDefocusTargetHeight >= 0
                        && getLayoutParams() instanceof FrameLayout.LayoutParams) {
                    int heightToShrink = getHeight() - mDefocusTargetHeight;
                    FrameLayout.LayoutParams layoutParams =
                            (FrameLayout.LayoutParams) getLayoutParams();
                    layoutParams.topMargin = -heightToShrink;
                    setLayoutParams(layoutParams);
                    ((ViewGroup) getParent().getParent()).setClipChildren(false);
                }


                ViewGroup grandParent = (ViewGroup) parent.getParent();
                ViewGroupOverlay overlay = parent.getOverlay();

                // After adding this RemoteInputView to the overlay of the parent (and thus removing
                // it from the parent itself), the parent will shrink in height. This causes the
                // overlay to be moved. To correct the position of the overlay we need to offset it.
                int overlayOffsetY = getMaxSiblingHeight() - getHeight();
                overlay.add(this);
                if (grandParent != null) grandParent.setClipChildren(false);

                Animator animator = getDefocusAnimator(overlayOffsetY);
                View self = this;
                animator.addListener(new AnimatorListenerAdapter() {
                animator.addListener(new AnimatorListenerAdapter() {
                    @Override
                    @Override
                    public void onAnimationEnd(Animator animation) {
                    public void onAnimationEnd(Animator animation) {
                        //reset top margin after the animation
                        overlay.remove(self);
                        if (getLayoutParams() instanceof FrameLayout.LayoutParams) {
                        parent.addView(self);
                            FrameLayout.LayoutParams layoutParams =
                        if (grandParent != null) grandParent.setClipChildren(true);
                                    (FrameLayout.LayoutParams) getLayoutParams();
                            layoutParams.topMargin = 0;
                            setLayoutParams(layoutParams);
                            ((ViewGroup) getParent().getParent()).setClipChildren(true);
                        }
                        setVisibility(GONE);
                        setVisibility(GONE);
                        if (mWrapper != null) {
                        if (mWrapper != null) {
                            mWrapper.setRemoteInputVisible(false);
                            mWrapper.setRemoteInputVisible(false);
@@ -609,7 +587,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
    }
    }


    /**
    /**
     * Sets whether the feature flag for the updated inline reply animation is active or not.
     * Sets whether the feature flag for the revised inline reply animation is active or not.
     * @param active
     * @param active
     */
     */
    public void setIsFocusAnimationFlagActive(boolean active) {
    public void setIsFocusAnimationFlagActive(boolean active) {
@@ -846,6 +824,23 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        }
        }
    }
    }


    /**
     * @return max sibling height (0 in case of no siblings)
     */
    public int getMaxSiblingHeight() {
        ViewGroup parentView = (ViewGroup) getParent();
        int maxHeight = 0;
        if (parentView == null) return 0;
        for (int i = 0; i < parentView.getChildCount(); i++) {
            View siblingView = parentView.getChildAt(i);
            if (siblingView != this) maxHeight = Math.max(maxHeight, siblingView.getHeight());
        }
        return maxHeight;
    }

    /**
     * Creates an animator for the focus animation.
     */
    private Animator getFocusAnimator(View crossFadeView) {
    private Animator getFocusAnimator(View crossFadeView) {
        final Animator alphaAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 0f, 1f);
        final Animator alphaAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 0f, 1f);
        alphaAnimator.setStartDelay(FOCUS_ANIMATION_FADE_IN_DELAY);
        alphaAnimator.setStartDelay(FOCUS_ANIMATION_FADE_IN_DELAY);
@@ -854,7 +849,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene


        ValueAnimator scaleAnimator = ValueAnimator.ofFloat(FOCUS_ANIMATION_MIN_SCALE, 1f);
        ValueAnimator scaleAnimator = ValueAnimator.ofFloat(FOCUS_ANIMATION_MIN_SCALE, 1f);
        scaleAnimator.addUpdateListener(valueAnimator -> {
        scaleAnimator.addUpdateListener(valueAnimator -> {
            setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue());
            setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue(), 0);
        });
        });
        scaleAnimator.setDuration(FOCUS_ANIMATION_TOTAL_DURATION);
        scaleAnimator.setDuration(FOCUS_ANIMATION_TOTAL_DURATION);
        scaleAnimator.setInterpolator(InterpolatorsAndroidX.FAST_OUT_SLOW_IN);
        scaleAnimator.setInterpolator(InterpolatorsAndroidX.FAST_OUT_SLOW_IN);
@@ -875,21 +870,26 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        return animatorSet;
        return animatorSet;
    }
    }


    private Animator getDefocusAnimator() {
    /**
     * Creates an animator for the defocus animation.
     *
     * @param offsetY The RemoteInputView will be offset by offsetY during the animation
     */
    private Animator getDefocusAnimator(int offsetY) {
        final Animator alphaAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 1f, 0f);
        final Animator alphaAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 1f, 0f);
        alphaAnimator.setDuration(FOCUS_ANIMATION_CROSSFADE_DURATION);
        alphaAnimator.setDuration(FOCUS_ANIMATION_CROSSFADE_DURATION);
        alphaAnimator.setInterpolator(InterpolatorsAndroidX.LINEAR);
        alphaAnimator.setInterpolator(InterpolatorsAndroidX.LINEAR);


        ValueAnimator scaleAnimator = ValueAnimator.ofFloat(1f, FOCUS_ANIMATION_MIN_SCALE);
        ValueAnimator scaleAnimator = ValueAnimator.ofFloat(1f, FOCUS_ANIMATION_MIN_SCALE);
        scaleAnimator.addUpdateListener(valueAnimator -> {
        scaleAnimator.addUpdateListener(valueAnimator -> {
            setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue());
            setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue(), offsetY);
        });
        });
        scaleAnimator.setDuration(FOCUS_ANIMATION_TOTAL_DURATION);
        scaleAnimator.setDuration(FOCUS_ANIMATION_TOTAL_DURATION);
        scaleAnimator.setInterpolator(InterpolatorsAndroidX.FAST_OUT_SLOW_IN);
        scaleAnimator.setInterpolator(InterpolatorsAndroidX.FAST_OUT_SLOW_IN);
        scaleAnimator.addListener(new AnimatorListenerAdapter() {
        scaleAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            @Override
            public void onAnimationEnd(Animator animation, boolean isReverse) {
            public void onAnimationEnd(Animator animation, boolean isReverse) {
                setFocusAnimationScaleY(1f);
                setFocusAnimationScaleY(1f /* scaleY */, 0 /* verticalOffset */);
            }
            }
        });
        });


@@ -902,14 +902,20 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
     * Sets affected view properties for a vertical scale animation
     * Sets affected view properties for a vertical scale animation
     *
     *
     * @param scaleY         desired vertical view scale
     * @param scaleY         desired vertical view scale
     * @param verticalOffset vertical offset to apply to the RemoteInputView during the animation
     */
     */
    private void setFocusAnimationScaleY(float scaleY) {
    private void setFocusAnimationScaleY(float scaleY, int verticalOffset) {
        int verticalBoundOffset = (int) ((1f - scaleY) * 0.5f * mContentView.getHeight());
        int verticalBoundOffset = (int) ((1f - scaleY) * 0.5f * mContentView.getHeight());
        mContentBackgroundBounds = new Rect(0, verticalBoundOffset, mContentView.getWidth(),
        Rect contentBackgroundBounds = new Rect(0, verticalBoundOffset, mContentView.getWidth(),
                mContentView.getHeight() - verticalBoundOffset);
                mContentView.getHeight() - verticalBoundOffset);
        mContentBackground.setBounds(mContentBackgroundBounds);
        mContentBackground.setBounds(contentBackgroundBounds);
        mContentView.setBackground(mContentBackground);
        mContentView.setBackground(mContentBackground);
        setTranslationY(verticalBoundOffset);
        if (scaleY == 1f) {
            mContentBackgroundBounds = null;
        } else {
            mContentBackgroundBounds = contentBackgroundBounds;
        }
        setTranslationY(verticalBoundOffset + verticalOffset);
    }
    }


    /** Handler for button click on send action in IME. */
    /** Handler for button click on send action in IME. */
+3 −0
Original line number Original line Diff line number Diff line
@@ -55,6 +55,7 @@ import android.view.ViewRootImpl;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnection;
import android.widget.EditText;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageButton;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
import android.window.OnBackInvokedDispatcher;
@@ -414,7 +415,9 @@ public class RemoteInputViewTest extends SysuiTestCase {
                mDependency,
                mDependency,
                TestableLooper.get(this));
                TestableLooper.get(this));
        ExpandableNotificationRow row = helper.createRow();
        ExpandableNotificationRow row = helper.createRow();
        FrameLayout remoteInputViewParent = new FrameLayout(mContext);
        RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
        RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
        remoteInputViewParent.addView(view);
        bindController(view, row.getEntry());
        bindController(view, row.getEntry());


        // Start defocus animation
        // Start defocus animation