| Index: chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/UrlContainer.java
|
| diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/UrlContainer.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/UrlContainer.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e599b2974b1f41dd5b032e1004edca7fad70758e
|
| --- /dev/null
|
| +++ b/chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/UrlContainer.java
|
| @@ -0,0 +1,274 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.chrome.browser.omnibox;
|
| +
|
| +import android.animation.Animator;
|
| +import android.animation.AnimatorListenerAdapter;
|
| +import android.animation.AnimatorSet;
|
| +import android.animation.ObjectAnimator;
|
| +import android.annotation.SuppressLint;
|
| +import android.content.Context;
|
| +import android.os.SystemClock;
|
| +import android.text.Layout;
|
| +import android.text.TextUtils;
|
| +import android.util.AttributeSet;
|
| +import android.util.LayoutDirection;
|
| +import android.view.View;
|
| +import android.view.ViewGroup;
|
| +import android.widget.TextView;
|
| +
|
| +import com.google.android.apps.chrome.R;
|
| +
|
| +import org.chromium.base.ApiCompatibilityUtils;
|
| +import org.chromium.chrome.browser.util.MathUtils;
|
| +import org.chromium.ui.interpolators.BakedBezierInterpolator;
|
| +
|
| +/**
|
| + * Widget that handles displaying the URL. Adds the capability to show the trailing portion
|
| + * of the URL in a separate text widget for animations.
|
| + */
|
| +public class UrlContainer extends ViewGroup {
|
| + private static final int MIN_TRAILING_TEXT_SHOW_DURATION_MS = 3000;
|
| + private static final int MAX_TRAILING_TEXT_SHOW_DURATION_MS = 6000;
|
| + private static final int TRAILING_TEXT_ANIMATION_DURATION_MS = 200;
|
| + private static final float TRAILING_TEXT_TRANSLATION_X = 50f;
|
| +
|
| + private final Runnable mTriggerHideRunnable;
|
| + private final Runnable mTriggerHideAnimationRunnable;
|
| +
|
| + private UrlBar mUrlBarView;
|
| + private TextView mTrailingTextView;
|
| +
|
| + private int mUrlBarTextWidth;
|
| + private boolean mShowTrailingText;
|
| + private Animator mTrailingTextAnimator;
|
| + private long mLastShowRequestTime;
|
| + private boolean mUseDarkColors;
|
| +
|
| + /**
|
| + * Constructor used to inflate from XML.
|
| + */
|
| + public UrlContainer(Context context, AttributeSet attrs) {
|
| + super(context, attrs);
|
| +
|
| + mTriggerHideRunnable = new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + setTrailingTextVisible(false);
|
| + }
|
| + };
|
| + mTriggerHideAnimationRunnable = new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + hideTrailingText();
|
| + }
|
| + };
|
| +
|
| + mUseDarkColors = true;
|
| + }
|
| +
|
| + @Override
|
| + protected void onFinishInflate() {
|
| + super.onFinishInflate();
|
| +
|
| + mUrlBarView = (UrlBar) findViewById(R.id.url_bar);
|
| + assert mUrlBarView != null : "url_bar is not defined as a child.";
|
| +
|
| + mTrailingTextView = (TextView) findViewById(R.id.trailing_text);
|
| + assert mTrailingTextView != null : "trailing_text is not defined as a child.";
|
| +
|
| + setClickable(true);
|
| + }
|
| +
|
| + @Override
|
| + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
| + super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
| +
|
| + int specWidth = MeasureSpec.getSize(widthMeasureSpec);
|
| + mUrlBarView.measure(
|
| + MeasureSpec.makeMeasureSpec(specWidth, MeasureSpec.EXACTLY), heightMeasureSpec);
|
| +
|
| + if (TextUtils.isEmpty(mUrlBarView.getText())) {
|
| + mUrlBarTextWidth = specWidth;
|
| + } else if (mUrlBarView.hasFocus()) {
|
| + mUrlBarTextWidth = specWidth;
|
| + } else {
|
| + mUrlBarTextWidth = (int) Math.ceil(Math.min(specWidth,
|
| + Layout.getDesiredWidth(mUrlBarView.getText(), mUrlBarView.getPaint())));
|
| + }
|
| + mTrailingTextView.measure(
|
| + MeasureSpec.makeMeasureSpec(specWidth - mUrlBarTextWidth, MeasureSpec.EXACTLY),
|
| + heightMeasureSpec);
|
| + }
|
| +
|
| + @SuppressLint("NewApi")
|
| + @Override
|
| + public void onRtlPropertiesChanged(int layoutDirection) {
|
| + super.onRtlPropertiesChanged(layoutDirection);
|
| +
|
| + // Layout direction is driven by the text direction of the URL bar, so we just force
|
| + // the path text view to match.
|
| + switch (layoutDirection) {
|
| + case LayoutDirection.LTR:
|
| + ApiCompatibilityUtils.setTextDirection(mTrailingTextView, TEXT_DIRECTION_LTR);
|
| + break;
|
| + case LayoutDirection.RTL:
|
| + ApiCompatibilityUtils.setTextDirection(mTrailingTextView, TEXT_DIRECTION_RTL);
|
| + break;
|
| + case LayoutDirection.LOCALE:
|
| + ApiCompatibilityUtils.setTextDirection(mTrailingTextView, TEXT_DIRECTION_LOCALE);
|
| + break;
|
| + case LayoutDirection.INHERIT:
|
| + default:
|
| + ApiCompatibilityUtils.setTextDirection(mTrailingTextView, TEXT_DIRECTION_INHERIT);
|
| + break;
|
| + }
|
| + }
|
| +
|
| + @Override
|
| + protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
| + int height = b - t;
|
| + layoutChild(mUrlBarView, height, 0);
|
| + if (ApiCompatibilityUtils.isLayoutRtl(mUrlBarView)) {
|
| + layoutChild(mTrailingTextView, height, 0);
|
| + } else {
|
| + layoutChild(mTrailingTextView, height, mUrlBarTextWidth);
|
| + }
|
| + }
|
| +
|
| + private static void layoutChild(View view, int parentHeight, int childLeft) {
|
| + int childTop = (parentHeight - view.getMeasuredHeight()) / 2;
|
| + view.layout(
|
| + childLeft,
|
| + childTop,
|
| + childLeft + view.getMeasuredWidth(),
|
| + childTop + view.getMeasuredHeight());
|
| + }
|
| +
|
| + /**
|
| + * Sets the text to be displayed.
|
| + *
|
| + * @param displayText The primary display text to be shown.
|
| + * @param trailingText The additional trailing text to be shown after the display text.
|
| + * @param originalText The text that will be displayed if no display text is specified, and
|
| + * is also supplied to features such as cut and copy.
|
| + * @return Whether any components of the URL have changed.
|
| + */
|
| + public boolean setUrlText(String displayText, String trailingText, String originalText) {
|
| + boolean changed = mUrlBarView.setUrl(originalText, displayText);
|
| + if (changed && mTrailingTextView.getVisibility() == VISIBLE) requestLayout();
|
| +
|
| + if (trailingText == null) trailingText = "";
|
| + if (!trailingText.equals(mTrailingTextView.getText())) {
|
| + mTrailingTextView.setText(trailingText);
|
| + changed |= true;
|
| + }
|
| + return changed;
|
| + }
|
| +
|
| + /**
|
| + * Specifies whether the trailing URL text should use dark text colors or light colors.
|
| + * @param useDarkColors Whether the text colors should be dark (i.e. appropriate for use
|
| + * on a light background).
|
| + */
|
| + public void setUseDarkTextColors(boolean useDarkColors) {
|
| + mUseDarkColors = useDarkColors;
|
| + mUrlBarView.setUseDarkTextColors(mUseDarkColors);
|
| +
|
| + int trailingTextColorId = R.color.url_emphasis_non_emphasized_text;
|
| + if (!mUseDarkColors) {
|
| + trailingTextColorId = R.color.url_emphasis_light_non_emphasized_text;
|
| + }
|
| + mTrailingTextView.setTextColor(getResources().getColor(trailingTextColorId));
|
| + }
|
| +
|
| + /**
|
| + * Updates the visibility of the trailing text view.
|
| + * @param visible Whether the trailing text view should be visible.
|
| + */
|
| + public void setTrailingTextVisible(boolean visible) {
|
| + if (visible) mLastShowRequestTime = SystemClock.uptimeMillis();
|
| +
|
| + if (visible == mShowTrailingText) return;
|
| + mShowTrailingText = visible;
|
| +
|
| + removeCallbacks(mTriggerHideRunnable);
|
| + removeCallbacks(mTriggerHideAnimationRunnable);
|
| +
|
| + if (visible) {
|
| + if (mTrailingTextAnimator != null && mTrailingTextAnimator.isRunning()) {
|
| + mTrailingTextAnimator.cancel();
|
| + } else {
|
| + float translationX = MathUtils.flipSignIf(
|
| + TRAILING_TEXT_TRANSLATION_X, ApiCompatibilityUtils.isLayoutRtl(this));
|
| + mTrailingTextView.setAlpha(0f);
|
| + mTrailingTextView.setTranslationX(translationX);
|
| + }
|
| + // Canceling the other animation will set the visibility to GONE, so only update
|
| + // this to VISIBLE after the above call to cancel().
|
| + mTrailingTextView.setVisibility(VISIBLE);
|
| +
|
| + if (!TextUtils.isEmpty(mTrailingTextView.getText())) {
|
| + mUrlBarView.setAccessibilityTextOverride(
|
| + TextUtils.concat(mUrlBarView.getText(), mTrailingTextView.getText())
|
| + .toString());
|
| + }
|
| +
|
| + AnimatorSet set = new AnimatorSet();
|
| + set.playTogether(
|
| + ObjectAnimator.ofFloat(mTrailingTextView, ALPHA, 1f),
|
| + ObjectAnimator.ofFloat(mTrailingTextView, TRANSLATION_X, 0f));
|
| + set.setDuration(TRAILING_TEXT_ANIMATION_DURATION_MS);
|
| + set.setInterpolator(BakedBezierInterpolator.FADE_IN_CURVE);
|
| + set.addListener(new AnimatorListenerAdapter() {
|
| + @Override
|
| + public void onAnimationEnd(Animator animation) {
|
| + super.onAnimationEnd(animation);
|
| + mTrailingTextAnimator = null;
|
| + }
|
| + });
|
| + set.start();
|
| + mTrailingTextAnimator = set;
|
| +
|
| + postDelayed(mTriggerHideRunnable, MAX_TRAILING_TEXT_SHOW_DURATION_MS);
|
| + } else {
|
| + long elapsedTime = SystemClock.uptimeMillis() - mLastShowRequestTime;
|
| + if (elapsedTime >= MIN_TRAILING_TEXT_SHOW_DURATION_MS) {
|
| + hideTrailingText();
|
| + } else {
|
| + postDelayed(mTriggerHideAnimationRunnable,
|
| + MIN_TRAILING_TEXT_SHOW_DURATION_MS - elapsedTime);
|
| + }
|
| + }
|
| + }
|
| +
|
| + private void hideTrailingText() {
|
| + if (mTrailingTextAnimator != null && mTrailingTextAnimator.isRunning()) {
|
| + mTrailingTextAnimator.cancel();
|
| + }
|
| +
|
| + mUrlBarView.setAccessibilityTextOverride(null);
|
| +
|
| + float translationX = MathUtils.flipSignIf(
|
| + TRAILING_TEXT_TRANSLATION_X, ApiCompatibilityUtils.isLayoutRtl(this));
|
| +
|
| + AnimatorSet set = new AnimatorSet();
|
| + set.playTogether(
|
| + ObjectAnimator.ofFloat(mTrailingTextView, ALPHA, 0f),
|
| + ObjectAnimator.ofFloat(mTrailingTextView, TRANSLATION_X, translationX));
|
| + set.setDuration(TRAILING_TEXT_ANIMATION_DURATION_MS);
|
| + set.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE);
|
| + set.addListener(new AnimatorListenerAdapter() {
|
| + @Override
|
| + public void onAnimationEnd(Animator animation) {
|
| + super.onAnimationEnd(animation);
|
| + mTrailingTextView.setVisibility(GONE);
|
| + mTrailingTextAnimator = null;
|
| + }
|
| + });
|
| + set.start();
|
| + mTrailingTextAnimator = set;
|
| + }
|
| +}
|
|
|