Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Unified Diff: components/autofill/android/java/src/org/chromium/components/autofill/AutofillKeyboardAccessory.java

Issue 2874933008: Adds animation as feature variation to keyboard accessory. (Closed)
Patch Set: Switch to base/metrics/field_trial_params.h API from variations:: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/autofill/android/java/src/org/chromium/components/autofill/AutofillKeyboardAccessory.java
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillKeyboardAccessory.java b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillKeyboardAccessory.java
index 56475a385245b4eda771492457202070f1e3d3b9..b36b9f5b698fc6175a25ac93502e82980b4e591a 100644
--- a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillKeyboardAccessory.java
+++ b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillKeyboardAccessory.java
@@ -4,8 +4,13 @@
package org.chromium.components.autofill;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
+import android.graphics.PorterDuff;
import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v7.content.res.AppCompatResources;
import android.text.TextUtils;
@@ -29,19 +34,32 @@ import org.chromium.ui.base.WindowAndroid;
public class AutofillKeyboardAccessory extends LinearLayout
implements WindowAndroid.KeyboardVisibilityListener, View.OnClickListener,
View.OnLongClickListener {
+ // Time to pause before reversing animation when the first suggestion is a hint.
+ private static final long PAUSE_ANIMATION_BEFORE_REVERSE_MILLIS = 1000;
+
private final WindowAndroid mWindowAndroid;
private final AutofillDelegate mAutofillDelegate;
+ // If |mMaximumLabelWidthPx| is 0, we do not call |setMaxWidth| on the |TextView| for a fillable
+ // suggestion label.
private final int mMaximumLabelWidthPx;
private final int mMaximumSublabelWidthPx;
+ private final int mAnimationDurationMillis;
+ // We start animating by scrolling the suggestions from beyond the viewport.
+ private final int mStartAnimationTranslationPx;
+
+ private ObjectAnimator mAnimator;
+ private Runnable mReverseAnimationRunnable;
/**
* Creates an AutofillKeyboardAccessory with specified parameters.
* @param windowAndroid The owning WindowAndroid.
* @param autofillDelegate A object that handles the calls to the native
* AutofillKeyboardAccessoryView.
+ * @param animationDurationMillis If 0, do not animate.
+ * @param shouldLimitLabelWidth If true, limit suggestion label width to 1/2 device's width.
*/
- public AutofillKeyboardAccessory(
- WindowAndroid windowAndroid, AutofillDelegate autofillDelegate) {
+ public AutofillKeyboardAccessory(WindowAndroid windowAndroid, AutofillDelegate autofillDelegate,
+ int animationDurationMillis, boolean shouldLimitLabelWidth) {
super(windowAndroid.getActivity().get());
assert autofillDelegate != null;
assert windowAndroid.getActivity().get() != null;
@@ -49,13 +67,17 @@ public class AutofillKeyboardAccessory extends LinearLayout
mAutofillDelegate = autofillDelegate;
int deviceWidthPx = windowAndroid.getDisplay().getDisplayWidth();
- mMaximumLabelWidthPx = deviceWidthPx / 2;
+ mMaximumLabelWidthPx = shouldLimitLabelWidth ? deviceWidthPx / 2 : 0;
mMaximumSublabelWidthPx = deviceWidthPx / 4;
mWindowAndroid.addKeyboardVisibilityListener(this);
int horizontalPaddingPx = getResources().getDimensionPixelSize(
R.dimen.keyboard_accessory_half_padding);
setPadding(horizontalPaddingPx, 0, horizontalPaddingPx, 0);
+
+ mAnimationDurationMillis = animationDurationMillis;
+ mStartAnimationTranslationPx = getResources().getDimensionPixelSize(
+ R.dimen.keyboard_accessory_start_animation_translation);
}
/**
@@ -65,23 +87,42 @@ public class AutofillKeyboardAccessory extends LinearLayout
*/
@SuppressLint("InlinedApi")
public void showWithSuggestions(AutofillSuggestion[] suggestions, final boolean isRtl) {
+ assert suggestions.length > 0;
+ // The first suggestion may be a hint to call attention to the keyboard accessory. See
+ // |IsHintEnabledInKeyboardAccessory|. A 'hint' suggestion does not have a label and is not
+ // fillable, but has an icon.
+ final boolean isFirstSuggestionAHint = TextUtils.isEmpty(suggestions[0].getLabel());
+ if (isFirstSuggestionAHint) {
+ assert suggestions[0].getIconId() != 0 && !suggestions[0].isFillable();
+ }
+
removeAllViews();
int separatorPosition = -1;
for (int i = 0; i < suggestions.length; i++) {
AutofillSuggestion suggestion = suggestions[i];
- assert !TextUtils.isEmpty(suggestion.getLabel());
+ boolean isKeyboardAccessoryHint = i == 0 && isFirstSuggestionAHint;
+ if (!isKeyboardAccessoryHint) {
+ assert !TextUtils.isEmpty(suggestion.getLabel());
+ }
View touchTarget;
if (!suggestion.isFillable() && suggestion.getIconId() != 0) {
touchTarget = LayoutInflater.from(getContext()).inflate(
R.layout.autofill_keyboard_accessory_icon, this, false);
- if (separatorPosition == -1) separatorPosition = i;
+ if (separatorPosition == -1 && !isKeyboardAccessoryHint) separatorPosition = i;
ImageView icon = (ImageView) touchTarget;
- icon.setImageDrawable(
- AppCompatResources.getDrawable(getContext(), suggestion.getIconId()));
- icon.setContentDescription(suggestion.getLabel());
+ Drawable drawable =
+ AppCompatResources.getDrawable(getContext(), suggestion.getIconId());
+ if (isKeyboardAccessoryHint) {
+ drawable.setColorFilter(ApiCompatibilityUtils.getColor(getResources(),
+ R.color.keyboard_accessory_hint_icon),
+ PorterDuff.Mode.SRC_IN);
+ } else {
+ icon.setContentDescription(suggestion.getLabel());
+ }
+ icon.setImageDrawable(drawable);
} else {
touchTarget = LayoutInflater.from(getContext()).inflate(
R.layout.autofill_keyboard_accessory_item, this, false);
@@ -89,7 +130,7 @@ public class AutofillKeyboardAccessory extends LinearLayout
TextView label = (TextView) touchTarget.findViewById(
R.id.autofill_keyboard_accessory_item_label);
- if (suggestion.isFillable()) {
+ if (mMaximumLabelWidthPx > 0 && suggestion.isFillable()) {
label.setMaxWidth(mMaximumLabelWidthPx);
}
@@ -115,36 +156,63 @@ public class AutofillKeyboardAccessory extends LinearLayout
}
}
- touchTarget.setTag(i);
- touchTarget.setOnClickListener(this);
- if (suggestion.isDeletable()) {
- touchTarget.setOnLongClickListener(this);
+ if (!isKeyboardAccessoryHint) {
+ touchTarget.setTag(i);
+ touchTarget.setOnClickListener(this);
+ if (suggestion.isDeletable()) {
+ touchTarget.setOnLongClickListener(this);
+ }
}
-
addView(touchTarget);
}
if (separatorPosition != -1) {
- View separator = new View(getContext());
- separator.setLayoutParams(new LinearLayout.LayoutParams(0, 0, 1));
- addView(separator, separatorPosition);
+ addView(createSeparatorView(), separatorPosition);
}
+ // TODO(crbug/722897): Following does not reverse layout order for RTL.
ApiCompatibilityUtils.setLayoutDirection(
this, isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
final HorizontalScrollView container =
(HorizontalScrollView) mWindowAndroid.getKeyboardAccessoryView();
+
if (getParent() == null) {
container.addView(this);
- container.setVisibility(View.VISIBLE);
+ // If we are animating the view, we |setVisibility| in |onAnimationStart|.
+ if (mAnimationDurationMillis == 0) {
+ container.setVisibility(View.VISIBLE);
+ }
container.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
+ if (mAnimationDurationMillis > 0) {
+ cancelAnimations(container);
+ mAnimator = ObjectAnimator.ofFloat(
+ this, View.TRANSLATION_X, -mStartAnimationTranslationPx, 0);
+ mAnimator.setDuration(mAnimationDurationMillis);
+ mAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animator) {
+ container.setVisibility(View.VISIBLE);
+ }
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ mAnimator.removeListener(this);
+ if (isFirstSuggestionAHint && container.getVisibility() == View.VISIBLE) {
+ scheduleReverseAnimation(container);
+ }
+ }
+ });
+ }
container.post(new Runnable() {
@Override
public void run() {
- container.scrollTo(isRtl ? getRight() : 0, 0);
+ if (mAnimationDurationMillis > 0) {
+ mAnimator.start();
+ } else {
+ container.scrollTo(isRtl ? getRight() : 0, 0);
+ }
}
});
}
@@ -179,4 +247,56 @@ public class AutofillKeyboardAccessory extends LinearLayout
mAutofillDelegate.deleteSuggestion((int) v.getTag());
return true;
}
+
+ // Helper to create separator view so that the settings icon is aligned to the right of the
+ // screen.
+ private View createSeparatorView() {
+ View separator = new View(getContext());
+ // Specify a layout weight so that the settings icon, which is displayed after the
+ // separator, is aligned with the edge of the viewport.
+ separator.setLayoutParams(new LinearLayout.LayoutParams(0, 0, 1));
+ return separator;
+ }
+
+ // Cancels any ongoing and pending reverse animations.
+ private void cancelAnimations(View view) {
+ if (mAnimator != null && mAnimator.isStarted()) mAnimator.cancel();
+ view.removeCallbacks(mReverseAnimationRunnable);
+ mAnimator = null;
+ }
+
+ // Schedules the reverse of the animation. Scrolls the first suggestion (which is a non-fillable
+ // hint) out of the viewport at the end of the reversed animation.
+ private void scheduleReverseAnimation(final View view) {
+ assert getChildCount() > 1;
+ // We may have removed the keyboardAccessoryHint from a previous animation that we
+ // cancelled.
+ final View firstSuggestion = getChildAt(0);
+ if (!(firstSuggestion instanceof ImageView
+ && firstSuggestion.getContentDescription() == null)) {
+ return;
+ }
+
+ int hintWidth = firstSuggestion.getWidth() - firstSuggestion.getPaddingRight();
+ mAnimator = ObjectAnimator.ofFloat(this, View.TRANSLATION_X, 0, -hintWidth);
+ mAnimator.setDuration(mAnimationDurationMillis);
+ mAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ mAnimator.removeListener(this);
+ if (view.getVisibility() == View.VISIBLE) {
+ // Remove the keyboard accessory hint, reset 'X' and redraw the layout.
+ removeView(firstSuggestion);
+ setTranslationX(0);
+ }
+ }
+ });
+ mReverseAnimationRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (view.getVisibility() == View.VISIBLE) mAnimator.start();
+ }
+ };
+ view.postDelayed(mReverseAnimationRunnable, PAUSE_ANIMATION_BEFORE_REVERSE_MILLIS);
+ }
}
« no previous file with comments | « components/autofill/android/java/res/values/dimens.xml ('k') | components/autofill/core/browser/autofill_external_delegate.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698