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

Commit af06bf22 authored by Adrian Roos's avatar Adrian Roos
Browse files

Direct Reply: Fix circular reveal origin

Makes sure the circular reveal origin matches the bounds of the
text. This is necessairy because the TextView for the last action
spans the full remaining width and is usually much larger than the
text, which makes the reveal look uncentered.

Also adds an animation for closing the direct reply view.

Bug: 29876991
Change-Id: Ib0ae8a12423f0ecfc573928a39634404c8232e40
parent f8bc27d9
Loading
Loading
Loading
Loading
+13 −5
Original line number Diff line number Diff line
@@ -472,20 +472,28 @@ public abstract class BaseStatusBar extends SystemUI implements
                }
            }

            riv.setVisibility(View.VISIBLE);
            int cx = view.getLeft() + view.getWidth() / 2;
            int width = view.getWidth();
            if (view instanceof TextView) {
                // Center the reveal on the text which might be off-center from the TextView
                TextView tv = (TextView) view;
                if (tv.getLayout() != null) {
                    int innerWidth = (int) tv.getLayout().getLineWidth(0);
                    innerWidth += tv.getCompoundPaddingLeft() + tv.getCompoundPaddingRight();
                    width = Math.min(width, innerWidth);
                }
            }
            int cx = view.getLeft() + width / 2;
            int cy = view.getTop() + view.getHeight() / 2;
            int w = riv.getWidth();
            int h = riv.getHeight();
            int r = Math.max(
                    Math.max(cx + cy, cx + (h - cy)),
                    Math.max((w - cx) + cy, (w - cx) + (h - cy)));
            ViewAnimationUtils.createCircularReveal(riv, cx, cy, 0, r)
                    .start();

            riv.setRevealParameters(cx, cy, r);
            riv.setPendingIntent(pendingIntent);
            riv.setRemoteInput(inputs, input);
            riv.focus();
            riv.focusAnimated();

            return true;
        }
+50 −9
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.systemui.statusbar.policy;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteInput;
@@ -33,6 +35,7 @@ import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.inputmethod.CompletionInfo;
@@ -47,11 +50,13 @@ import android.widget.TextView;

import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.stack.ScrollContainer;
import com.android.systemui.statusbar.stack.StackStateAnimator;

/**
 * Host for the remote input.
@@ -77,6 +82,10 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
    private View mScrollContainerChild;
    private boolean mRemoved;

    private int mRevealCx;
    private int mRevealCy;
    private int mRevealR;

    public RemoteInputView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
@@ -180,15 +189,29 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        return true;
    }

    public void onDefocus() {
    private void onDefocus(boolean animate) {
        mController.removeRemoteInput(mEntry);
        mEntry.remoteInputText = mEditText.getText();

        // During removal, we get reattached and lose focus. Not hiding in that
        // case to prevent flicker.
        if (!mRemoved) {
            if (animate && mRevealR > 0) {
                Animator reveal = ViewAnimationUtils.createCircularReveal(
                        this, mRevealCx, mRevealCy, mRevealR, 0);
                reveal.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
                reveal.setDuration(StackStateAnimator.ANIMATION_DURATION_CLOSE_REMOTE_INPUT);
                reveal.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        setVisibility(INVISIBLE);
                    }
                });
                reveal.start();
            } else {
                setVisibility(INVISIBLE);
            }
        }
        MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_CLOSE,
                mEntry.notification.getPackageName());
    }
@@ -223,6 +246,17 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        mEditText.setHint(mRemoteInput.getLabel());
    }

    public void focusAnimated() {
        if (getVisibility() != VISIBLE) {
            Animator animator = ViewAnimationUtils.createCircularReveal(
                    this, mRevealCx, mRevealCy, 0, mRevealR);
            animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
            animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
            animator.start();
        }
        focus();
    }

    public void focus() {
        MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_OPEN,
                mEntry.notification.getPackageName());
@@ -253,7 +287,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        mProgressBar.setVisibility(INVISIBLE);
        mController.removeSpinning(mEntry.key);
        updateSendButton();
        onDefocus();
        onDefocus(false /* animate */);
    }

    private void updateSendButton() {
@@ -272,7 +306,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
    }

    public void close() {
        mEditText.defocusIfNeeded();
        mEditText.defocusIfNeeded(false /* animated */);
    }

    @Override
@@ -321,6 +355,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        other.close();
        setPendingIntent(other.mPendingIntent);
        setRemoteInput(other.mRemoteInputs, other.mRemoteInput);
        setRevealParameters(other.mRevealCx, other.mRevealCy, other.mRevealR);
        focus();
    }

@@ -374,6 +409,12 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        mRemoved = true;
    }

    public void setRevealParameters(int cx, int cy, int r) {
        mRevealCx = cx;
        mRevealCy = cy;
        mRevealR = r;
    }

    /**
     * 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.
@@ -389,14 +430,14 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
            mBackground = getBackground();
        }

        private void defocusIfNeeded() {
        private void defocusIfNeeded(boolean animate) {
            if (mRemoteInputView != null && mRemoteInputView.mEntry.row.isChangingPosition()) {
                return;
            }
            if (isFocusable() && isEnabled()) {
                setInnerFocusable(false);
                if (mRemoteInputView != null) {
                    mRemoteInputView.onDefocus();
                    mRemoteInputView.onDefocus(animate);
                }
                mShowImeOnInputConnection = false;
            }
@@ -407,7 +448,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
            super.onVisibilityChanged(changedView, visibility);

            if (!isShown()) {
                defocusIfNeeded();
                defocusIfNeeded(false /* animate */);
            }
        }

@@ -415,7 +456,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
            super.onFocusChanged(focused, direction, previouslyFocusedRect);
            if (!focused) {
                defocusIfNeeded();
                defocusIfNeeded(true /* animate */);
            }
        }

@@ -434,7 +475,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
        @Override
        public boolean onKeyPreIme(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
                defocusIfNeeded();
                defocusIfNeeded(true /* animate */);
                final InputMethodManager imm = InputMethodManager.getInstance();
                imm.hideSoftInputFromWindow(getWindowToken(), 0);
                return true;
+1 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ public class StackStateAnimator {
    public static final int ANIMATION_DURATION_GO_TO_FULL_SHADE = 448;
    public static final int ANIMATION_DURATION_APPEAR_DISAPPEAR = 464;
    public static final int ANIMATION_DURATION_DIMMED_ACTIVATED = 220;
    public static final int ANIMATION_DURATION_CLOSE_REMOTE_INPUT = 150;
    public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 650;
    public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 230;
    public static final int ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING = 80;