Merge changes from topic "inline-reply-animation" into tm-qpr-dev
* changes: Fix headsup notification RemoteInputView appearance animation Fix notification inline reply animation
This commit is contained in:
committed by
Android (Google) Code Review
commit
02358a560e
@@ -27,6 +27,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="end"
|
android:gravity="end"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:background="@color/notification_action_list_background_color"
|
android:background="@color/notification_action_list_background_color"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ android_library {
|
|||||||
"WindowManager-Shell",
|
"WindowManager-Shell",
|
||||||
"LowLightDreamLib",
|
"LowLightDreamLib",
|
||||||
"motion_tool_lib",
|
"motion_tool_lib",
|
||||||
|
"androidx.core_core-animation-testing-nodeps",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
<com.android.systemui.statusbar.policy.RemoteInputView
|
<com.android.systemui.statusbar.policy.RemoteInputView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/remote_input"
|
android:id="@+id/remote_input"
|
||||||
|
android:forceHasOverlappingRendering="false"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_width="match_parent">
|
android:layout_width="match_parent">
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
|||||||
@@ -103,6 +103,11 @@ object Flags {
|
|||||||
// TODO(b/257315550): Tracking Bug
|
// TODO(b/257315550): Tracking Bug
|
||||||
val NO_HUN_FOR_OLD_WHEN = unreleasedFlag(118, "no_hun_for_old_when", teamfood = true)
|
val NO_HUN_FOR_OLD_WHEN = unreleasedFlag(118, "no_hun_for_old_when", teamfood = true)
|
||||||
|
|
||||||
|
// TODO(b/260335638): Tracking Bug
|
||||||
|
@JvmField
|
||||||
|
val NOTIFICATION_INLINE_REPLY_ANIMATION =
|
||||||
|
unreleasedFlag(174148361, "notification_inline_reply_animation", teamfood = true)
|
||||||
|
|
||||||
val FILTER_UNSEEN_NOTIFS_ON_KEYGUARD =
|
val FILTER_UNSEEN_NOTIFS_ON_KEYGUARD =
|
||||||
unreleasedFlag(254647461, "filter_unseen_notifs_on_keyguard", teamfood = true)
|
unreleasedFlag(254647461, "filter_unseen_notifs_on_keyguard", teamfood = true)
|
||||||
|
|
||||||
|
|||||||
@@ -463,7 +463,11 @@ public class NotificationRemoteInputManager implements Dumpable {
|
|||||||
riv.getController().setRemoteInput(input);
|
riv.getController().setRemoteInput(input);
|
||||||
riv.getController().setRemoteInputs(inputs);
|
riv.getController().setRemoteInputs(inputs);
|
||||||
riv.getController().setEditedSuggestionInfo(editedSuggestionInfo);
|
riv.getController().setEditedSuggestionInfo(editedSuggestionInfo);
|
||||||
riv.focusAnimated();
|
ViewGroup parent = view.getParent() != null ? (ViewGroup) view.getParent() : null;
|
||||||
|
if (parent != null) {
|
||||||
|
riv.setDefocusTargetHeight(parent.getHeight());
|
||||||
|
}
|
||||||
|
riv.focusAnimated(parent);
|
||||||
if (userMessageContent != null) {
|
if (userMessageContent != null) {
|
||||||
riv.setEditTextContent(userMessageContent);
|
riv.setEditTextContent(userMessageContent);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.notification.collection.inflation;
|
package com.android.systemui.statusbar.notification.collection.inflation;
|
||||||
|
|
||||||
|
import static com.android.systemui.flags.Flags.NOTIFICATION_INLINE_REPLY_ANIMATION;
|
||||||
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED;
|
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED;
|
||||||
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED;
|
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED;
|
||||||
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC;
|
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC;
|
||||||
@@ -30,6 +31,7 @@ import android.view.ViewGroup;
|
|||||||
|
|
||||||
import com.android.internal.util.NotificationMessagingUtil;
|
import com.android.internal.util.NotificationMessagingUtil;
|
||||||
import com.android.systemui.dagger.SysUISingleton;
|
import com.android.systemui.dagger.SysUISingleton;
|
||||||
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationPresenter;
|
import com.android.systemui.statusbar.NotificationPresenter;
|
||||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||||
@@ -71,6 +73,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
|
|||||||
private NotificationListContainer mListContainer;
|
private NotificationListContainer mListContainer;
|
||||||
private BindRowCallback mBindRowCallback;
|
private BindRowCallback mBindRowCallback;
|
||||||
private NotificationClicker mNotificationClicker;
|
private NotificationClicker mNotificationClicker;
|
||||||
|
private FeatureFlags mFeatureFlags;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public NotificationRowBinderImpl(
|
public NotificationRowBinderImpl(
|
||||||
@@ -82,7 +85,8 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
|
|||||||
RowContentBindStage rowContentBindStage,
|
RowContentBindStage rowContentBindStage,
|
||||||
Provider<RowInflaterTask> rowInflaterTaskProvider,
|
Provider<RowInflaterTask> rowInflaterTaskProvider,
|
||||||
ExpandableNotificationRowComponent.Builder expandableNotificationRowComponentBuilder,
|
ExpandableNotificationRowComponent.Builder expandableNotificationRowComponentBuilder,
|
||||||
IconManager iconManager) {
|
IconManager iconManager,
|
||||||
|
FeatureFlags featureFlags) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mNotifBindPipeline = notifBindPipeline;
|
mNotifBindPipeline = notifBindPipeline;
|
||||||
mRowContentBindStage = rowContentBindStage;
|
mRowContentBindStage = rowContentBindStage;
|
||||||
@@ -92,6 +96,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
|
|||||||
mRowInflaterTaskProvider = rowInflaterTaskProvider;
|
mRowInflaterTaskProvider = rowInflaterTaskProvider;
|
||||||
mExpandableNotificationRowComponentBuilder = expandableNotificationRowComponentBuilder;
|
mExpandableNotificationRowComponentBuilder = expandableNotificationRowComponentBuilder;
|
||||||
mIconManager = iconManager;
|
mIconManager = iconManager;
|
||||||
|
mFeatureFlags = featureFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -176,6 +181,8 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
|
|||||||
entry.setRow(row);
|
entry.setRow(row);
|
||||||
mNotifBindPipeline.manageRow(entry, row);
|
mNotifBindPipeline.manageRow(entry, row);
|
||||||
mBindRowCallback.onBindRow(row);
|
mBindRowCallback.onBindRow(row);
|
||||||
|
row.setInlineReplyAnimationFlagEnabled(
|
||||||
|
mFeatureFlags.isEnabled(NOTIFICATION_INLINE_REPLY_ANIMATION));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -284,6 +284,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
|||||||
private View.OnClickListener mOnAppClickListener;
|
private View.OnClickListener mOnAppClickListener;
|
||||||
private View.OnClickListener mOnFeedbackClickListener;
|
private View.OnClickListener mOnFeedbackClickListener;
|
||||||
private Path mExpandingClipPath;
|
private Path mExpandingClipPath;
|
||||||
|
private boolean mIsInlineReplyAnimationFlagEnabled = false;
|
||||||
|
|
||||||
// Listener will be called when receiving a long click event.
|
// Listener will be called when receiving a long click event.
|
||||||
// Use #setLongPressPosition to optionally assign positional data with the long press.
|
// Use #setLongPressPosition to optionally assign positional data with the long press.
|
||||||
@@ -3079,6 +3080,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setInlineReplyAnimationFlagEnabled(boolean isEnabled) {
|
||||||
|
mIsInlineReplyAnimationFlagEnabled = isEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setActualHeight(int height, boolean notifyListeners) {
|
public void setActualHeight(int height, boolean notifyListeners) {
|
||||||
boolean changed = height != getActualHeight();
|
boolean changed = height != getActualHeight();
|
||||||
@@ -3098,8 +3103,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
|||||||
}
|
}
|
||||||
int contentHeight = Math.max(getMinHeight(), height);
|
int contentHeight = Math.max(getMinHeight(), height);
|
||||||
for (NotificationContentView l : mLayouts) {
|
for (NotificationContentView l : mLayouts) {
|
||||||
|
if (mIsInlineReplyAnimationFlagEnabled) {
|
||||||
|
l.setContentHeight(height);
|
||||||
|
} else {
|
||||||
l.setContentHeight(contentHeight);
|
l.setContentHeight(contentHeight);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (mIsSummaryWithChildren) {
|
if (mIsSummaryWithChildren) {
|
||||||
mChildrenContainer.setActualHeight(height);
|
mChildrenContainer.setActualHeight(height);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A frame layout containing the actual payload of the notification, including the contracted,
|
* A frame layout containing the actual payload of the notification, including the contracted,
|
||||||
* expanded and heads up layout. This class is responsible for clipping the content and and
|
* expanded and heads up layout. This class is responsible for clipping the content and
|
||||||
* switching between the expanded, contracted and the heads up view depending on its clipped size.
|
* switching between the expanded, contracted and the heads up view depending on its clipped size.
|
||||||
*/
|
*/
|
||||||
public class NotificationContentView extends FrameLayout implements NotificationFadeAware {
|
public class NotificationContentView extends FrameLayout implements NotificationFadeAware {
|
||||||
@@ -627,6 +627,13 @@ public class NotificationContentView extends FrameLayout implements Notification
|
|||||||
int hint;
|
int hint;
|
||||||
if (mHeadsUpChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_HEADSUP)) {
|
if (mHeadsUpChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_HEADSUP)) {
|
||||||
hint = getViewHeight(VISIBLE_TYPE_HEADSUP);
|
hint = getViewHeight(VISIBLE_TYPE_HEADSUP);
|
||||||
|
if (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isAnimatingAppearance()
|
||||||
|
&& mHeadsUpRemoteInputController.isFocusAnimationFlagActive()) {
|
||||||
|
// While the RemoteInputView is animating its appearance, it should be allowed
|
||||||
|
// to overlap the hint, therefore no space is reserved for the hint during the
|
||||||
|
// appearance animation of the RemoteInputView
|
||||||
|
hint = 0;
|
||||||
|
}
|
||||||
} else if (mExpandedChild != null) {
|
} else if (mExpandedChild != null) {
|
||||||
hint = getViewHeight(VISIBLE_TYPE_EXPANDED);
|
hint = getViewHeight(VISIBLE_TYPE_EXPANDED);
|
||||||
} else if (mContractedChild != null) {
|
} else if (mContractedChild != null) {
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ package com.android.systemui.statusbar.policy;
|
|||||||
|
|
||||||
import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP;
|
import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_STANDARD;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -57,6 +57,7 @@ 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;
|
||||||
@@ -67,6 +68,11 @@ import android.window.OnBackInvokedDispatcher;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.animation.Animator;
|
||||||
|
import androidx.core.animation.AnimatorListenerAdapter;
|
||||||
|
import androidx.core.animation.AnimatorSet;
|
||||||
|
import androidx.core.animation.ObjectAnimator;
|
||||||
|
import androidx.core.animation.ValueAnimator;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.graphics.ColorUtils;
|
import com.android.internal.graphics.ColorUtils;
|
||||||
@@ -74,6 +80,7 @@ import com.android.internal.logging.UiEvent;
|
|||||||
import com.android.internal.logging.UiEventLogger;
|
import com.android.internal.logging.UiEventLogger;
|
||||||
import com.android.systemui.Dependency;
|
import com.android.systemui.Dependency;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
|
import com.android.systemui.animation.InterpolatorsAndroidX;
|
||||||
import com.android.systemui.statusbar.RemoteInputController;
|
import com.android.systemui.statusbar.RemoteInputController;
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||||
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
|
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
|
||||||
@@ -97,6 +104,12 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
|
|||||||
// A marker object that let's us easily find views of this class.
|
// A marker object that let's us easily find views of this class.
|
||||||
public static final Object VIEW_TAG = new Object();
|
public static final Object VIEW_TAG = new Object();
|
||||||
|
|
||||||
|
private static final long FOCUS_ANIMATION_TOTAL_DURATION = ANIMATION_DURATION_STANDARD;
|
||||||
|
private static final long FOCUS_ANIMATION_CROSSFADE_DURATION = 50;
|
||||||
|
private static final long FOCUS_ANIMATION_FADE_IN_DELAY = 33;
|
||||||
|
private static final long FOCUS_ANIMATION_FADE_IN_DURATION = 83;
|
||||||
|
private static final float FOCUS_ANIMATION_MIN_SCALE = 0.5f;
|
||||||
|
|
||||||
public final Object mToken = new Object();
|
public final Object mToken = new Object();
|
||||||
|
|
||||||
private final SendButtonTextWatcher mTextWatcher;
|
private final SendButtonTextWatcher mTextWatcher;
|
||||||
@@ -108,6 +121,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
|
|||||||
|
|
||||||
private RemoteEditText mEditText;
|
private RemoteEditText mEditText;
|
||||||
private ImageButton mSendButton;
|
private ImageButton mSendButton;
|
||||||
|
private LinearLayout mContentView;
|
||||||
private GradientDrawable mContentBackground;
|
private GradientDrawable mContentBackground;
|
||||||
private ProgressBar mProgressBar;
|
private ProgressBar mProgressBar;
|
||||||
private ImageView mDelete;
|
private ImageView mDelete;
|
||||||
@@ -115,7 +129,10 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
|
|||||||
private boolean mColorized;
|
private boolean mColorized;
|
||||||
private int mTint;
|
private int mTint;
|
||||||
private boolean mResetting;
|
private boolean mResetting;
|
||||||
@Nullable private RevealParams mRevealParams;
|
@Nullable
|
||||||
|
private RevealParams mRevealParams;
|
||||||
|
private Rect mContentBackgroundBounds;
|
||||||
|
private boolean mIsFocusAnimationFlagActive;
|
||||||
|
|
||||||
// TODO(b/193539698): move these to a Controller
|
// TODO(b/193539698): move these to a Controller
|
||||||
private RemoteInputController mController;
|
private RemoteInputController mController;
|
||||||
@@ -125,6 +142,10 @@ 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;
|
||||||
@@ -255,8 +276,8 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
|
|||||||
mDeleteBg.setImageTintBlendMode(BlendMode.SRC_IN);
|
mDeleteBg.setImageTintBlendMode(BlendMode.SRC_IN);
|
||||||
mDelete.setImageTintBlendMode(BlendMode.SRC_IN);
|
mDelete.setImageTintBlendMode(BlendMode.SRC_IN);
|
||||||
mDelete.setOnClickListener(v -> setAttachment(null));
|
mDelete.setOnClickListener(v -> setAttachment(null));
|
||||||
LinearLayout contentView = findViewById(R.id.remote_input_content);
|
mContentView = findViewById(R.id.remote_input_content);
|
||||||
contentView.setBackground(mContentBackground);
|
mContentView.setBackground(mContentBackground);
|
||||||
mEditText = findViewById(R.id.remote_input_text);
|
mEditText = findViewById(R.id.remote_input_text);
|
||||||
mEditText.setInnerFocusable(false);
|
mEditText.setInnerFocusable(false);
|
||||||
// TextView initializes the spell checked when the view is attached to a window.
|
// TextView initializes the spell checked when the view is attached to a window.
|
||||||
@@ -398,20 +419,74 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onDefocus(boolean animate, boolean logClose) {
|
public boolean isAnimatingAppearance() {
|
||||||
|
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
|
||||||
|
void onDefocus(boolean animate, boolean logClose) {
|
||||||
mController.removeRemoteInput(mEntry, mToken);
|
mController.removeRemoteInput(mEntry, mToken);
|
||||||
mEntry.remoteInputText = mEditText.getText();
|
mEntry.remoteInputText = mEditText.getText();
|
||||||
|
|
||||||
// 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 && mRevealParams != null && mRevealParams.radius > 0) {
|
if (animate && mIsFocusAnimationFlagActive) {
|
||||||
Animator reveal = mRevealParams.createCircularHideAnimator(this);
|
Animator animator = getDefocusAnimator();
|
||||||
reveal.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
|
|
||||||
reveal.setDuration(StackStateAnimator.ANIMATION_DURATION_CLOSE_REMOTE_INPUT);
|
// When defocusing, the notification needs to shrink. Therefore, we need to free
|
||||||
reveal.addListener(new AnimatorListenerAdapter() {
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
animator.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
//reset top margin after the animation
|
||||||
|
if (getLayoutParams() instanceof FrameLayout.LayoutParams) {
|
||||||
|
FrameLayout.LayoutParams layoutParams =
|
||||||
|
(FrameLayout.LayoutParams) getLayoutParams();
|
||||||
|
layoutParams.topMargin = 0;
|
||||||
|
setLayoutParams(layoutParams);
|
||||||
|
((ViewGroup) getParent().getParent()).setClipChildren(true);
|
||||||
|
}
|
||||||
|
setVisibility(GONE);
|
||||||
|
if (mWrapper != null) {
|
||||||
|
mWrapper.setRemoteInputVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
animator.start();
|
||||||
|
|
||||||
|
} else if (animate && mRevealParams != null && mRevealParams.radius > 0) {
|
||||||
|
android.animation.Animator reveal = mRevealParams.createCircularHideAnimator(this);
|
||||||
|
reveal.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
|
||||||
|
reveal.setDuration(StackStateAnimator.ANIMATION_DURATION_CLOSE_REMOTE_INPUT);
|
||||||
|
reveal.addListener(new android.animation.AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(android.animation.Animator animation) {
|
||||||
setVisibility(GONE);
|
setVisibility(GONE);
|
||||||
if (mWrapper != null) {
|
if (mWrapper != null) {
|
||||||
mWrapper.setRemoteInputVisible(false);
|
mWrapper.setRemoteInputVisible(false);
|
||||||
@@ -533,12 +608,37 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
|
|||||||
mEditText.setText(editTextContent);
|
mEditText.setText(editTextContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void focusAnimated() {
|
/**
|
||||||
if (getVisibility() != VISIBLE && mRevealParams != null) {
|
* Sets whether the feature flag for the updated inline reply animation is active or not.
|
||||||
Animator animator = mRevealParams.createCircularRevealAnimator(this);
|
* @param active
|
||||||
|
*/
|
||||||
|
public void setIsFocusAnimationFlagActive(boolean active) {
|
||||||
|
mIsFocusAnimationFlagActive = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Focuses the RemoteInputView and animates its appearance
|
||||||
|
*
|
||||||
|
* @param crossFadeView view that will be crossfaded during the appearance animation
|
||||||
|
*/
|
||||||
|
public void focusAnimated(View crossFadeView) {
|
||||||
|
if (!mIsFocusAnimationFlagActive && getVisibility() != VISIBLE
|
||||||
|
&& mRevealParams != null) {
|
||||||
|
android.animation.Animator animator = mRevealParams.createCircularRevealAnimator(this);
|
||||||
animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
|
animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
|
||||||
animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
|
animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
|
||||||
animator.start();
|
animator.start();
|
||||||
|
} else if (mIsFocusAnimationFlagActive && getVisibility() != VISIBLE) {
|
||||||
|
mIsAnimatingAppearance = true;
|
||||||
|
setAlpha(0f);
|
||||||
|
Animator focusAnimator = getFocusAnimator(crossFadeView);
|
||||||
|
focusAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation, boolean isReverse) {
|
||||||
|
mIsAnimatingAppearance = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
focusAnimator.start();
|
||||||
}
|
}
|
||||||
focus();
|
focus();
|
||||||
}
|
}
|
||||||
@@ -737,6 +837,81 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
|
|||||||
mOnSendListeners.remove(listener);
|
mOnSendListeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||||
|
super.onLayout(changed, l, t, r, b);
|
||||||
|
if (mIsFocusAnimationFlagActive) setPivotY(getMeasuredHeight());
|
||||||
|
if (mContentBackgroundBounds != null) {
|
||||||
|
mContentBackground.setBounds(mContentBackgroundBounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Animator getFocusAnimator(View crossFadeView) {
|
||||||
|
final Animator alphaAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 0f, 1f);
|
||||||
|
alphaAnimator.setStartDelay(FOCUS_ANIMATION_FADE_IN_DELAY);
|
||||||
|
alphaAnimator.setDuration(FOCUS_ANIMATION_FADE_IN_DURATION);
|
||||||
|
alphaAnimator.setInterpolator(InterpolatorsAndroidX.LINEAR);
|
||||||
|
|
||||||
|
ValueAnimator scaleAnimator = ValueAnimator.ofFloat(FOCUS_ANIMATION_MIN_SCALE, 1f);
|
||||||
|
scaleAnimator.addUpdateListener(valueAnimator -> {
|
||||||
|
setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue());
|
||||||
|
});
|
||||||
|
scaleAnimator.setDuration(FOCUS_ANIMATION_TOTAL_DURATION);
|
||||||
|
scaleAnimator.setInterpolator(InterpolatorsAndroidX.FAST_OUT_SLOW_IN);
|
||||||
|
|
||||||
|
final Animator crossFadeViewAlphaAnimator =
|
||||||
|
ObjectAnimator.ofFloat(crossFadeView, View.ALPHA, 1f, 0f);
|
||||||
|
crossFadeViewAlphaAnimator.setDuration(FOCUS_ANIMATION_CROSSFADE_DURATION);
|
||||||
|
crossFadeViewAlphaAnimator.setInterpolator(InterpolatorsAndroidX.LINEAR);
|
||||||
|
alphaAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation, boolean isReverse) {
|
||||||
|
crossFadeView.setAlpha(1f);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final AnimatorSet animatorSet = new AnimatorSet();
|
||||||
|
animatorSet.playTogether(alphaAnimator, scaleAnimator, crossFadeViewAlphaAnimator);
|
||||||
|
return animatorSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Animator getDefocusAnimator() {
|
||||||
|
final Animator alphaAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 1f, 0f);
|
||||||
|
alphaAnimator.setDuration(FOCUS_ANIMATION_CROSSFADE_DURATION);
|
||||||
|
alphaAnimator.setInterpolator(InterpolatorsAndroidX.LINEAR);
|
||||||
|
|
||||||
|
ValueAnimator scaleAnimator = ValueAnimator.ofFloat(1f, FOCUS_ANIMATION_MIN_SCALE);
|
||||||
|
scaleAnimator.addUpdateListener(valueAnimator -> {
|
||||||
|
setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue());
|
||||||
|
});
|
||||||
|
scaleAnimator.setDuration(FOCUS_ANIMATION_TOTAL_DURATION);
|
||||||
|
scaleAnimator.setInterpolator(InterpolatorsAndroidX.FAST_OUT_SLOW_IN);
|
||||||
|
scaleAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation, boolean isReverse) {
|
||||||
|
setFocusAnimationScaleY(1f);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final AnimatorSet animatorSet = new AnimatorSet();
|
||||||
|
animatorSet.playTogether(alphaAnimator, scaleAnimator);
|
||||||
|
return animatorSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets affected view properties for a vertical scale animation
|
||||||
|
*
|
||||||
|
* @param scaleY desired vertical view scale
|
||||||
|
*/
|
||||||
|
private void setFocusAnimationScaleY(float scaleY) {
|
||||||
|
int verticalBoundOffset = (int) ((1f - scaleY) * 0.5f * mContentView.getHeight());
|
||||||
|
mContentBackgroundBounds = new Rect(0, verticalBoundOffset, mContentView.getWidth(),
|
||||||
|
mContentView.getHeight() - verticalBoundOffset);
|
||||||
|
mContentBackground.setBounds(mContentBackgroundBounds);
|
||||||
|
mContentView.setBackground(mContentBackground);
|
||||||
|
setTranslationY(verticalBoundOffset);
|
||||||
|
}
|
||||||
|
|
||||||
/** Handler for button click on send action in IME. */
|
/** Handler for button click on send action in IME. */
|
||||||
private class EditorActionHandler implements TextView.OnEditorActionListener {
|
private class EditorActionHandler implements TextView.OnEditorActionListener {
|
||||||
|
|
||||||
@@ -991,11 +1166,11 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
|
|||||||
this.radius = radius;
|
this.radius = radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
Animator createCircularHideAnimator(View view) {
|
android.animation.Animator createCircularHideAnimator(View view) {
|
||||||
return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, radius, 0);
|
return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, radius, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Animator createCircularRevealAnimator(View view) {
|
android.animation.Animator createCircularRevealAnimator(View view) {
|
||||||
return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, 0, radius);
|
return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, 0, radius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ import android.util.Log
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import com.android.internal.logging.UiEventLogger
|
import com.android.internal.logging.UiEventLogger
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
|
import com.android.systemui.flags.FeatureFlags
|
||||||
|
import com.android.systemui.flags.Flags.NOTIFICATION_INLINE_REPLY_ANIMATION
|
||||||
import com.android.systemui.statusbar.NotificationRemoteInputManager
|
import com.android.systemui.statusbar.NotificationRemoteInputManager
|
||||||
import com.android.systemui.statusbar.RemoteInputController
|
import com.android.systemui.statusbar.RemoteInputController
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||||
@@ -61,6 +63,8 @@ interface RemoteInputViewController {
|
|||||||
|
|
||||||
var revealParams: RevealParams?
|
var revealParams: RevealParams?
|
||||||
|
|
||||||
|
val isFocusAnimationFlagActive: Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the smart reply that should be inserted in the remote input, or `null` if the user is
|
* Sets the smart reply that should be inserted in the remote input, or `null` if the user is
|
||||||
* not editing a smart reply.
|
* not editing a smart reply.
|
||||||
@@ -117,7 +121,8 @@ class RemoteInputViewControllerImpl @Inject constructor(
|
|||||||
private val remoteInputQuickSettingsDisabler: RemoteInputQuickSettingsDisabler,
|
private val remoteInputQuickSettingsDisabler: RemoteInputQuickSettingsDisabler,
|
||||||
private val remoteInputController: RemoteInputController,
|
private val remoteInputController: RemoteInputController,
|
||||||
private val shortcutManager: ShortcutManager,
|
private val shortcutManager: ShortcutManager,
|
||||||
private val uiEventLogger: UiEventLogger
|
private val uiEventLogger: UiEventLogger,
|
||||||
|
private val mFlags: FeatureFlags
|
||||||
) : RemoteInputViewController {
|
) : RemoteInputViewController {
|
||||||
|
|
||||||
private val onSendListeners = ArraySet<OnSendRemoteInputListener>()
|
private val onSendListeners = ArraySet<OnSendRemoteInputListener>()
|
||||||
@@ -149,6 +154,9 @@ class RemoteInputViewControllerImpl @Inject constructor(
|
|||||||
|
|
||||||
override val isActive: Boolean get() = view.isActive
|
override val isActive: Boolean get() = view.isActive
|
||||||
|
|
||||||
|
override val isFocusAnimationFlagActive: Boolean
|
||||||
|
get() = mFlags.isEnabled(NOTIFICATION_INLINE_REPLY_ANIMATION)
|
||||||
|
|
||||||
override fun bind() {
|
override fun bind() {
|
||||||
if (isBound) return
|
if (isBound) return
|
||||||
isBound = true
|
isBound = true
|
||||||
@@ -159,6 +167,7 @@ class RemoteInputViewControllerImpl @Inject constructor(
|
|||||||
view.setSupportedMimeTypes(it.allowedDataTypes)
|
view.setSupportedMimeTypes(it.allowedDataTypes)
|
||||||
}
|
}
|
||||||
view.setRevealParameters(revealParams)
|
view.setRevealParameters(revealParams)
|
||||||
|
view.setIsFocusAnimationFlagActive(isFocusAnimationFlagActive)
|
||||||
|
|
||||||
view.addOnEditTextFocusChangedListener(onFocusChangeListener)
|
view.addOnEditTextFocusChangedListener(onFocusChangeListener)
|
||||||
view.addOnSendRemoteInputListener(onSendRemoteInputListener)
|
view.addOnSendRemoteInputListener(onSendRemoteInputListener)
|
||||||
|
|||||||
@@ -16,10 +16,14 @@ package com.android.systemui.statusbar.policy;
|
|||||||
|
|
||||||
import static android.view.ContentInfo.SOURCE_CLIPBOARD;
|
import static android.view.ContentInfo.SOURCE_CLIPBOARD;
|
||||||
|
|
||||||
|
import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_STANDARD;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static junit.framework.Assert.assertEquals;
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static junit.framework.Assert.assertFalse;
|
||||||
import static junit.framework.Assert.assertNotNull;
|
import static junit.framework.Assert.assertNotNull;
|
||||||
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
@@ -57,6 +61,7 @@ import android.window.OnBackInvokedDispatcher;
|
|||||||
import android.window.WindowOnBackInvokedDispatcher;
|
import android.window.WindowOnBackInvokedDispatcher;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.animation.AnimatorTestRule;
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.internal.logging.UiEventLogger;
|
import com.android.internal.logging.UiEventLogger;
|
||||||
@@ -64,15 +69,19 @@ import com.android.internal.logging.testing.UiEventLoggerFake;
|
|||||||
import com.android.systemui.Dependency;
|
import com.android.systemui.Dependency;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
|
import com.android.systemui.flags.FakeFeatureFlags;
|
||||||
|
import com.android.systemui.flags.Flags;
|
||||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||||
import com.android.systemui.statusbar.RemoteInputController;
|
import com.android.systemui.statusbar.RemoteInputController;
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||||
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
|
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
|
||||||
|
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
|
||||||
import com.android.systemui.statusbar.phone.LightBarController;
|
import com.android.systemui.statusbar.phone.LightBarController;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.ClassRule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
@@ -99,6 +108,9 @@ public class RemoteInputViewTest extends SysuiTestCase {
|
|||||||
private BlockingQueueIntentReceiver mReceiver;
|
private BlockingQueueIntentReceiver mReceiver;
|
||||||
private final UiEventLoggerFake mUiEventLoggerFake = new UiEventLoggerFake();
|
private final UiEventLoggerFake mUiEventLoggerFake = new UiEventLoggerFake();
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static AnimatorTestRule mAnimatorTestRule = new AnimatorTestRule();
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
allowTestableLooperAsMainThread();
|
allowTestableLooperAsMainThread();
|
||||||
@@ -294,6 +306,9 @@ public class RemoteInputViewTest extends SysuiTestCase {
|
|||||||
/* invoke the captured callback */
|
/* invoke the captured callback */
|
||||||
onBackInvokedCallbackCaptor.getValue().onBackInvoked();
|
onBackInvokedCallbackCaptor.getValue().onBackInvoked();
|
||||||
|
|
||||||
|
/* wait for RemoteInputView disappear animation to finish */
|
||||||
|
mAnimatorTestRule.advanceTimeBy(StackStateAnimator.ANIMATION_DURATION_STANDARD);
|
||||||
|
|
||||||
/* verify that the RemoteInputView goes away */
|
/* verify that the RemoteInputView goes away */
|
||||||
assertEquals(view.getVisibility(), View.GONE);
|
assertEquals(view.getVisibility(), View.GONE);
|
||||||
}
|
}
|
||||||
@@ -363,19 +378,73 @@ public class RemoteInputViewTest extends SysuiTestCase {
|
|||||||
mUiEventLoggerFake.eventId(1));
|
mUiEventLoggerFake.eventId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFocusAnimation() throws Exception {
|
||||||
|
NotificationTestHelper helper = new NotificationTestHelper(
|
||||||
|
mContext,
|
||||||
|
mDependency,
|
||||||
|
TestableLooper.get(this));
|
||||||
|
ExpandableNotificationRow row = helper.createRow();
|
||||||
|
RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
|
||||||
|
bindController(view, row.getEntry());
|
||||||
|
view.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
View crossFadeView = new View(mContext);
|
||||||
|
|
||||||
|
// Start focus animation
|
||||||
|
view.focusAnimated(crossFadeView);
|
||||||
|
|
||||||
|
assertTrue(view.isAnimatingAppearance());
|
||||||
|
|
||||||
|
// fast forward to end of animation
|
||||||
|
mAnimatorTestRule.advanceTimeBy(ANIMATION_DURATION_STANDARD);
|
||||||
|
|
||||||
|
// assert that crossFadeView's alpha is reset to 1f after the animation (hidden behind
|
||||||
|
// RemoteInputView)
|
||||||
|
assertEquals(1f, crossFadeView.getAlpha());
|
||||||
|
assertFalse(view.isAnimatingAppearance());
|
||||||
|
assertEquals(View.VISIBLE, view.getVisibility());
|
||||||
|
assertEquals(1f, view.getAlpha());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefocusAnimation() throws Exception {
|
||||||
|
NotificationTestHelper helper = new NotificationTestHelper(
|
||||||
|
mContext,
|
||||||
|
mDependency,
|
||||||
|
TestableLooper.get(this));
|
||||||
|
ExpandableNotificationRow row = helper.createRow();
|
||||||
|
RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
|
||||||
|
bindController(view, row.getEntry());
|
||||||
|
|
||||||
|
// Start defocus animation
|
||||||
|
view.onDefocus(true, false);
|
||||||
|
assertEquals(View.VISIBLE, view.getVisibility());
|
||||||
|
|
||||||
|
// fast forward to end of animation
|
||||||
|
mAnimatorTestRule.advanceTimeBy(ANIMATION_DURATION_STANDARD);
|
||||||
|
|
||||||
|
// assert that RemoteInputView is no longer visible
|
||||||
|
assertEquals(View.GONE, view.getVisibility());
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: because we're refactoring the RemoteInputView and moving logic into the
|
// NOTE: because we're refactoring the RemoteInputView and moving logic into the
|
||||||
// RemoteInputViewController, it's easiest to just test the system of the two classes together.
|
// RemoteInputViewController, it's easiest to just test the system of the two classes together.
|
||||||
@NonNull
|
@NonNull
|
||||||
private RemoteInputViewController bindController(
|
private RemoteInputViewController bindController(
|
||||||
RemoteInputView view,
|
RemoteInputView view,
|
||||||
NotificationEntry entry) {
|
NotificationEntry entry) {
|
||||||
|
FakeFeatureFlags fakeFeatureFlags = new FakeFeatureFlags();
|
||||||
|
fakeFeatureFlags.set(Flags.NOTIFICATION_INLINE_REPLY_ANIMATION, true);
|
||||||
RemoteInputViewControllerImpl viewController = new RemoteInputViewControllerImpl(
|
RemoteInputViewControllerImpl viewController = new RemoteInputViewControllerImpl(
|
||||||
view,
|
view,
|
||||||
entry,
|
entry,
|
||||||
mRemoteInputQuickSettingsDisabler,
|
mRemoteInputQuickSettingsDisabler,
|
||||||
mController,
|
mController,
|
||||||
mShortcutManager,
|
mShortcutManager,
|
||||||
mUiEventLoggerFake);
|
mUiEventLoggerFake,
|
||||||
|
fakeFeatureFlags
|
||||||
|
);
|
||||||
viewController.bind();
|
viewController.bind();
|
||||||
return viewController;
|
return viewController;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user