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

Unified Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/SuggestionView.java

Issue 1206673003: Merge java_staging/src into java/src. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 5 years, 6 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: chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/SuggestionView.java
diff --git a/chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/SuggestionView.java b/chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/SuggestionView.java
deleted file mode 100644
index e179347544bb4a5acb87ff9f3fe0eaa093167a1b..0000000000000000000000000000000000000000
--- a/chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/SuggestionView.java
+++ /dev/null
@@ -1,994 +0,0 @@
-// 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 static org.chromium.chrome.browser.omnibox.OmniboxSuggestion.Type.HISTORY_URL;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
-import android.support.v7.app.AlertDialog;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.TextPaint;
-import android.text.TextUtils;
-import android.text.style.StyleSpan;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-import android.widget.TextView.BufferType;
-
-import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.omnibox.OmniboxResultsAdapter.OmniboxResultItem;
-import org.chromium.chrome.browser.omnibox.OmniboxResultsAdapter.OmniboxSuggestionDelegate;
-import org.chromium.chrome.browser.omnibox.OmniboxSuggestion.Type;
-import org.chromium.chrome.browser.widget.TintedDrawable;
-import org.chromium.ui.base.DeviceFormFactor;
-
-import java.util.Locale;
-
-/**
- * Container view for omnibox suggestions made very specific for omnibox suggestions to minimize
- * any unnecessary measures and layouts.
- */
-class SuggestionView extends ViewGroup {
- private enum SuggestionIconType {
- BOOKMARK,
- HISTORY,
- GLOBE,
- MAGNIFIER,
- VOICE
- }
-
- private static final int FIRST_LINE_TEXT_SIZE_SP = 17;
- private static final int SECOND_LINE_TEXT_SIZE_SP = 14;
-
- private static final long RELAYOUT_DELAY_MS = 20;
-
- private static final int TITLE_COLOR_STANDARD_FONT_DARK = Color.rgb(51, 51, 51);
- private static final int TITLE_COLOR_STANDARD_FONT_LIGHT = Color.rgb(255, 255, 255);
- private static final int URL_COLOR = Color.rgb(85, 149, 254);
-
- private static final int ANSWER_IMAGE_HORIZONTAL_SPACING_DP = 4;
- private static final int ANSWER_IMAGE_VERTICAL_SPACING_DP = 5;
- private static final float ANSWER_IMAGE_SCALING_FACTOR = 1.15f;
-
- private LocationBar mLocationBar;
- private UrlBar mUrlBar;
- private ImageView mNavigationButton;
-
- private int mSuggestionHeight;
- private int mSuggestionAnswerHeight;
-
- private OmniboxResultItem mSuggestionItem;
- private OmniboxSuggestion mSuggestion;
- private OmniboxSuggestionDelegate mSuggestionDelegate;
- private Boolean mUseDarkColors;
- private int mPosition;
-
- private SuggestionContentsContainer mContentsView;
-
- private int mRefineWidth;
- private View mRefineView;
- private TintedDrawable mRefineIcon;
-
- private final int[] mViewPositionHolder = new int[2];
-
- /**
- * Constructs a new omnibox suggestion view.
- *
- * @param context The context used to construct the suggestion view.
- * @param locationBar The location bar showing these suggestions.
- */
- public SuggestionView(Context context, LocationBar locationBar) {
- super(context);
- mLocationBar = locationBar;
-
- mSuggestionHeight =
- context.getResources().getDimensionPixelOffset(R.dimen.omnibox_suggestion_height);
- mSuggestionAnswerHeight =
- context.getResources().getDimensionPixelOffset(
- R.dimen.omnibox_suggestion_answer_height);
-
- TypedArray a = getContext().obtainStyledAttributes(
- new int [] {R.attr.selectableItemBackground});
- Drawable itemBackground = a.getDrawable(0);
- a.recycle();
-
- mContentsView = new SuggestionContentsContainer(context, itemBackground);
- addView(mContentsView);
-
- mRefineView = new View(context) {
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- if (mRefineIcon == null) return;
- canvas.save();
- canvas.translate(
- (getMeasuredWidth() - mRefineIcon.getIntrinsicWidth()) / 2f,
- (getMeasuredHeight() - mRefineIcon.getIntrinsicHeight()) / 2f);
- mRefineIcon.draw(canvas);
- canvas.restore();
- }
-
- @Override
- public void setVisibility(int visibility) {
- super.setVisibility(visibility);
-
- if (visibility == VISIBLE) {
- setClickable(true);
- setFocusable(true);
- } else {
- setClickable(false);
- setFocusable(false);
- }
- }
-
- @Override
- protected void drawableStateChanged() {
- super.drawableStateChanged();
-
- if (mRefineIcon != null && mRefineIcon.isStateful()) {
- mRefineIcon.setState(getDrawableState());
- }
- }
- };
- mRefineView.setContentDescription(getContext().getString(
- R.string.accessibility_omnibox_btn_refine));
-
- // Although this has the same background as the suggestion view, it can not be shared as
- // it will result in the state of the drawable being shared and always showing up in the
- // refine view.
- mRefineView.setBackground(itemBackground.getConstantState().newDrawable());
- mRefineView.setId(R.id.refine_view_id);
- mRefineView.setClickable(true);
- mRefineView.setFocusable(true);
- mRefineView.setLayoutParams(new LayoutParams(0, 0));
- addView(mRefineView);
-
- mRefineWidth = (int) (getResources().getDisplayMetrics().density * 48);
-
- mUrlBar = (UrlBar) locationBar.getContainerView().findViewById(R.id.url_bar);
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- if (getMeasuredWidth() == 0) return;
-
- if (mSuggestion.getType() != Type.SEARCH_SUGGEST_TAIL) {
- mContentsView.resetTextWidths();
- }
-
- boolean refineVisible = mRefineView.getVisibility() == VISIBLE;
- boolean isRtl = ApiCompatibilityUtils.isLayoutRtl(this);
- int contentsViewOffsetX = isRtl ? mRefineWidth : 0;
- if (!refineVisible) contentsViewOffsetX = 0;
- mContentsView.layout(
- contentsViewOffsetX,
- 0,
- contentsViewOffsetX + mContentsView.getMeasuredWidth(),
- mContentsView.getMeasuredHeight());
- int refineViewOffsetX = isRtl ? 0 : getMeasuredWidth() - mRefineWidth;
- mRefineView.layout(
- refineViewOffsetX,
- 0,
- refineViewOffsetX + mRefineWidth,
- mContentsView.getMeasuredHeight());
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int width = MeasureSpec.getSize(widthMeasureSpec);
- int height = mSuggestionHeight;
- if (!TextUtils.isEmpty(mSuggestion.getAnswerContents())) {
- height = mSuggestionAnswerHeight;
- }
- setMeasuredDimension(width, height);
-
- // The width will be specified as 0 when determining the height of the popup, so exit early
- // after setting the height.
- if (width == 0) return;
-
- boolean refineVisible = mRefineView.getVisibility() == VISIBLE;
- int refineWidth = refineVisible ? mRefineWidth : 0;
- mContentsView.measure(
- MeasureSpec.makeMeasureSpec(width - refineWidth, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
- mContentsView.getLayoutParams().width = mContentsView.getMeasuredWidth();
- mContentsView.getLayoutParams().height = mContentsView.getMeasuredHeight();
-
- mRefineView.measure(
- MeasureSpec.makeMeasureSpec(mRefineWidth, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
- mRefineView.getLayoutParams().width = mRefineView.getMeasuredWidth();
- mRefineView.getLayoutParams().height = mRefineView.getMeasuredHeight();
- }
-
- @Override
- public void invalidate() {
- super.invalidate();
- mContentsView.invalidate();
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- // Whenever the suggestion dropdown is touched, we dispatch onGestureDown which is
- // used to let autocomplete controller know that it should stop updating suggestions.
- if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) mSuggestionDelegate.onGestureDown();
- return super.dispatchTouchEvent(ev);
- }
-
- /**
- * Sets the contents and state of the view for the given suggestion.
- *
- * @param suggestionItem The omnibox suggestion item this view represents.
- * @param suggestionDelegate The suggestion delegate.
- * @param position Position of the suggestion in the dropdown list.
- * @param useDarkColors Whether dark colors should be used for fonts and icons.
- */
- public void init(OmniboxResultItem suggestionItem,
- OmniboxSuggestionDelegate suggestionDelegate,
- int position, boolean useDarkColors) {
- // Update the position unconditionally.
- mPosition = position;
- jumpDrawablesToCurrentState();
- boolean colorsChanged = mUseDarkColors == null || mUseDarkColors != useDarkColors;
- if (suggestionItem.equals(mSuggestionItem) && !colorsChanged) return;
- mUseDarkColors = useDarkColors;
- if (colorsChanged) {
- mContentsView.mTextLine1.setTextColor(getStandardFontColor());
- setRefineIcon(true);
- }
-
- mSuggestionItem = suggestionItem;
- mSuggestion = suggestionItem.getSuggestion();
- mSuggestionDelegate = suggestionDelegate;
- // Reset old computations.
- mContentsView.resetTextWidths();
- mContentsView.mAnswerImage.setVisibility(GONE);
- mContentsView.mAnswerImage.getLayoutParams().height = 0;
- mContentsView.mAnswerImage.getLayoutParams().width = 0;
- mContentsView.mAnswerImage.setImageDrawable(null);
- mContentsView.mAnswerImageMaxSize = 0;
- mContentsView.mTextLine1.setTextSize(FIRST_LINE_TEXT_SIZE_SP);
- mContentsView.mTextLine2.setTextSize(SECOND_LINE_TEXT_SIZE_SP);
-
- // Suggestions with attached answers are rendered with rich results regardless of which
- // suggestion type they are.
- if (mSuggestion.hasAnswer()) {
- setAnswer(mSuggestion.getAnswer());
- mContentsView.setSuggestionIcon(SuggestionIconType.MAGNIFIER, colorsChanged);
- mContentsView.mTextLine2.setVisibility(VISIBLE);
- setRefinable(true);
- return;
- }
-
- boolean sameAsTyped =
- suggestionItem.getMatchedQuery().equalsIgnoreCase(mSuggestion.getDisplayText());
- Type suggestionType = mSuggestion.getType();
- switch (suggestionType) {
- case HISTORY_URL:
- case URL_WHAT_YOU_TYPED:
- case NAVSUGGEST:
- case HISTORY_TITLE:
- case HISTORY_BODY:
- case HISTORY_KEYWORD:
- case OPEN_HISTORY_PAGE:
- if (mSuggestion.isStarred()) {
- mContentsView.setSuggestionIcon(SuggestionIconType.BOOKMARK, colorsChanged);
- } else if (suggestionType == HISTORY_URL) {
- mContentsView.setSuggestionIcon(SuggestionIconType.HISTORY, colorsChanged);
- } else {
- mContentsView.setSuggestionIcon(SuggestionIconType.GLOBE, colorsChanged);
- }
- boolean urlShown = !TextUtils.isEmpty(mSuggestion.getUrl());
- boolean urlHighlighted = false;
- if (urlShown) {
- urlHighlighted = setUrlText(suggestionItem);
- } else {
- mContentsView.mTextLine2.setVisibility(INVISIBLE);
- }
- setSuggestedQuery(suggestionItem, true, urlShown, urlHighlighted);
- setRefinable(!sameAsTyped);
- break;
- case SEARCH_WHAT_YOU_TYPED:
- case SEARCH_HISTORY:
- case SEARCH_SUGGEST:
- case SEARCH_OTHER_ENGINE:
- case SEARCH_SUGGEST_ENTITY:
- case SEARCH_SUGGEST_TAIL:
- case SEARCH_SUGGEST_PERSONALIZED:
- case SEARCH_SUGGEST_PROFILE:
- case VOICE_SUGGEST:
- SuggestionIconType suggestionIcon = SuggestionIconType.MAGNIFIER;
- if (suggestionType == Type.VOICE_SUGGEST) {
- suggestionIcon = SuggestionIconType.VOICE;
- } else if ((suggestionType == Type.SEARCH_SUGGEST_PERSONALIZED)
- || (suggestionType == Type.SEARCH_HISTORY)) {
- // Show history icon for suggestions based on user queries.
- suggestionIcon = SuggestionIconType.HISTORY;
- }
- mContentsView.setSuggestionIcon(suggestionIcon, colorsChanged);
- setRefinable(!sameAsTyped);
- setSuggestedQuery(suggestionItem, false, false, false);
- if ((suggestionType == Type.SEARCH_SUGGEST_ENTITY)
- || (suggestionType == Type.SEARCH_SUGGEST_PROFILE)) {
- showDescriptionLine(
- SpannableString.valueOf(mSuggestion.getDescription()),
- getStandardFontColor());
- } else {
- mContentsView.mTextLine2.setVisibility(INVISIBLE);
- }
- break;
- default:
- assert false : "Suggestion type (" + mSuggestion.getType() + ") is not handled";
- break;
- }
- }
-
- private void setRefinable(boolean refinable) {
- if (refinable) {
- mRefineView.setVisibility(VISIBLE);
- mRefineView.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // Post the refine action to the end of the UI thread to allow the refine view
- // a chance to update its background selection state.
- PerformRefineSuggestion performRefine = new PerformRefineSuggestion();
- if (!post(performRefine)) performRefine.run();
- }
- });
- } else {
- mRefineView.setOnClickListener(null);
- mRefineView.setVisibility(GONE);
- }
- }
-
- private int getStandardFontColor() {
- return (mUseDarkColors == null || mUseDarkColors)
- ? TITLE_COLOR_STANDARD_FONT_DARK : TITLE_COLOR_STANDARD_FONT_LIGHT;
- }
-
- @Override
- public void setSelected(boolean selected) {
- super.setSelected(selected);
- if (selected && !isInTouchMode()) {
- mSuggestionDelegate.onSetUrlToSuggestion(mSuggestion);
- }
- }
-
- private void setRefineIcon(boolean invalidateIcon) {
- if (!invalidateIcon && mRefineIcon != null) return;
-
- mRefineIcon = TintedDrawable.constructTintedDrawable(
- getResources(), R.drawable.btn_suggestion_refine);
- mRefineIcon.setTint(getResources().getColorStateList(mUseDarkColors
- ? R.color.dark_mode_tint
- : R.color.light_mode_tint));
- mRefineIcon.setBounds(
- 0, 0,
- mRefineIcon.getIntrinsicWidth(),
- mRefineIcon.getIntrinsicHeight());
- mRefineIcon.setState(mRefineView.getDrawableState());
- mRefineView.postInvalidateOnAnimation();
- }
-
- /**
- * Sets (and highlights) the URL text of the second line of the omnibox suggestion.
- *
- * @param suggestion The suggestion containing the URL.
- * @return Whether the URL was highlighted based on the user query.
- */
- private boolean setUrlText(OmniboxResultItem suggestion) {
- String query = suggestion.getMatchedQuery();
- String url = suggestion.getSuggestion().getFormattedUrl();
- int index = url.indexOf(query);
- Spannable str = SpannableString.valueOf(url);
- if (index >= 0) {
- // Bold the part of the URL that matches the user query.
- str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),
- index, index + query.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- showDescriptionLine(str, URL_COLOR);
- return index >= 0;
- }
-
- /**
- * Sets a description line for the omnibox suggestion.
- *
- * @param str The description text.
- */
- private void showDescriptionLine(Spannable str, int textColor) {
- if (mContentsView.mTextLine2.getVisibility() != VISIBLE) {
- mContentsView.mTextLine2.setVisibility(VISIBLE);
- }
- mContentsView.mTextLine2.setTextColor(textColor);
- mContentsView.mTextLine2.setText(str, BufferType.SPANNABLE);
- }
-
- /**
- * Sets the text of the first line of the omnibox suggestion.
- *
- * @param suggestionItem The item containing the suggestion data.
- * @param showDescriptionIfPresent Whether to show the description text of the suggestion if
- * the item contains valid data.
- * @param isUrlQuery Whether this suggestion is showing an URL.
- * @param isUrlHighlighted Whether the URL contains any highlighted matching sections.
- */
- private void setSuggestedQuery(
- OmniboxResultItem suggestionItem, boolean showDescriptionIfPresent,
- boolean isUrlQuery, boolean isUrlHighlighted) {
- String userQuery = suggestionItem.getMatchedQuery();
- String suggestedQuery = null;
- OmniboxSuggestion suggestion = suggestionItem.getSuggestion();
- if (showDescriptionIfPresent && !TextUtils.isEmpty(suggestion.getUrl())
- && !TextUtils.isEmpty(suggestion.getDescription())) {
- suggestedQuery = suggestion.getDescription();
- } else {
- suggestedQuery = suggestion.getDisplayText();
- }
- if (suggestedQuery == null) {
- assert false : "Invalid suggestion sent with no displayable text";
- suggestedQuery = "";
- } else if (suggestedQuery.equals(suggestion.getUrl())) {
- // This is a navigation match with the title defaulted to the URL, display formatted URL
- // so that they continue matching.
- suggestedQuery = suggestion.getFormattedUrl();
- }
-
- if (mSuggestion.getType() == Type.SEARCH_SUGGEST_TAIL) {
- String fillIntoEdit = mSuggestion.getFillIntoEdit();
- // Data sanity checks.
- if (fillIntoEdit.startsWith(userQuery)
- && fillIntoEdit.endsWith(suggestedQuery)
- && fillIntoEdit.length() < userQuery.length() + suggestedQuery.length()) {
- String ignoredPrefix = fillIntoEdit.substring(
- 0, fillIntoEdit.length() - suggestedQuery.length());
- final String ellipsisPrefix = "\u2026 ";
- suggestedQuery = ellipsisPrefix + suggestedQuery;
- if (userQuery.startsWith(ignoredPrefix)) {
- userQuery = ellipsisPrefix + userQuery.substring(ignoredPrefix.length());
- }
- if (DeviceFormFactor.isTablet(getContext())) {
- TextPaint tp = mContentsView.mTextLine1.getPaint();
- mContentsView.mRequiredWidth =
- tp.measureText(fillIntoEdit, 0, fillIntoEdit.length());
- mContentsView.mMatchContentsWidth =
- tp.measureText(suggestedQuery, 0, suggestedQuery.length());
-
- // Update the max text widths values in SuggestionList. These will be passed to
- // the contents view on layout.
- mSuggestionDelegate.onTextWidthsUpdated(
- mContentsView.mRequiredWidth, mContentsView.mMatchContentsWidth);
- }
- }
- }
-
- Spannable str = SpannableString.valueOf(suggestedQuery);
- int userQueryIndex = isUrlHighlighted ? -1
- : suggestedQuery.toLowerCase(Locale.getDefault()).indexOf(
- userQuery.toLowerCase(Locale.getDefault()));
- if (userQueryIndex != -1) {
- int spanStart = 0;
- int spanEnd = 0;
- if (isUrlQuery) {
- spanStart = userQueryIndex;
- spanEnd = userQueryIndex + userQuery.length();
- } else {
- spanStart = userQueryIndex + userQuery.length();
- spanEnd = str.length();
- }
- spanStart = Math.min(spanStart, str.length());
- spanEnd = Math.min(spanEnd, str.length());
- if (spanStart != spanEnd) {
- str.setSpan(
- new StyleSpan(android.graphics.Typeface.BOLD),
- spanStart, spanEnd,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
- mContentsView.mTextLine1.setText(str, BufferType.SPANNABLE);
- }
-
- /**
- * Sets both lines of the Omnibox suggestion based on an Answers in Suggest result.
- *
- * @param answer The answer to be displayed.
- */
- private void setAnswer(SuggestionAnswer answer) {
- float density = getResources().getDisplayMetrics().density;
-
- SuggestionAnswer.ImageLine firstLine = answer.getFirstLine();
- mContentsView.mTextLine1.setTextSize(AnswerTextBuilder.getMaxTextHeightSp(firstLine));
- Spannable firstLineText = AnswerTextBuilder.buildSpannable(
- firstLine, mContentsView.mTextLine1.getPaint().getFontMetrics(), density);
- mContentsView.mTextLine1.setText(firstLineText, BufferType.SPANNABLE);
-
- SuggestionAnswer.ImageLine secondLine = answer.getSecondLine();
- mContentsView.mTextLine2.setTextSize(AnswerTextBuilder.getMaxTextHeightSp(secondLine));
- Spannable secondLineText = AnswerTextBuilder.buildSpannable(
- secondLine, mContentsView.mTextLine2.getPaint().getFontMetrics(), density);
- mContentsView.mTextLine2.setText(secondLineText, BufferType.SPANNABLE);
-
- if (secondLine.hasImage()) {
- mContentsView.mAnswerImage.setVisibility(VISIBLE);
-
- float textSize = mContentsView.mTextLine2.getTextSize();
- int imageSize = (int) (textSize * ANSWER_IMAGE_SCALING_FACTOR);
- mContentsView.mAnswerImage.getLayoutParams().height = imageSize;
- mContentsView.mAnswerImage.getLayoutParams().width = imageSize;
- mContentsView.mAnswerImageMaxSize = imageSize;
-
- String url = "https:" + secondLine.getImage().replace("\\/", "/");
- AnswersImage.requestAnswersImage(
- mLocationBar.getCurrentTab().getProfile(),
- url,
- new AnswersImage.AnswersImageObserver() {
- @Override
- public void onAnswersImageChanged(Bitmap bitmap) {
- mContentsView.mAnswerImage.setImageBitmap(bitmap);
- }
- });
- }
- }
-
- /**
- * Handles triggering a selection request for the suggestion rendered by this view.
- */
- private class PerformSelectSuggestion implements Runnable {
- @Override
- public void run() {
- mSuggestionDelegate.onSelection(mSuggestion, mPosition);
- }
- }
-
- /**
- * Handles triggering a refine request for the suggestion rendered by this view.
- */
- private class PerformRefineSuggestion implements Runnable {
- @Override
- public void run() {
- mSuggestionDelegate.onRefineSuggestion(mSuggestion);
- }
- }
-
- /**
- * @return The left offset for the suggestion text that will align it with the url text.
- */
- private int getUrlBarTextLeftPosition() {
- mUrlBar.getLocationOnScreen(mViewPositionHolder);
- return mViewPositionHolder[0] + mUrlBar.getPaddingLeft();
- }
-
- /**
- * @return The right offset for the suggestion text that will align it with the url text.
- */
- private int getUrlBarTextRightPosition() {
- mUrlBar.getLocationOnScreen(mViewPositionHolder);
- return mViewPositionHolder[0] + mUrlBar.getWidth() - mUrlBar.getPaddingRight();
- }
-
- /**
- * Container view for the contents of the suggestion (the search query, URL, and suggestion type
- * icon).
- */
- private class SuggestionContentsContainer extends ViewGroup implements OnLayoutChangeListener {
- private int mSuggestionIconLeft = Integer.MIN_VALUE;
- private int mTextLeft = Integer.MIN_VALUE;
- private int mTextRight = Integer.MIN_VALUE;
- private Drawable mSuggestionIcon;
- private SuggestionIconType mSuggestionIconType;
-
- private final TextView mTextLine1;
- private final TextView mTextLine2;
- private final ImageView mAnswerImage;
-
- private int mAnswerImageMaxSize; // getMaxWidth() is API 16+, so store it locally.
- private float mRequiredWidth;
- private float mMatchContentsWidth;
- private boolean mForceIsFocused;
-
- private final Runnable mRelayoutRunnable = new Runnable() {
- @Override
- public void run() {
- requestLayout();
- }
- };
-
- @SuppressLint("InlinedApi")
- SuggestionContentsContainer(Context context, Drawable backgroundDrawable) {
- super(context);
-
- ApiCompatibilityUtils.setLayoutDirection(this, View.LAYOUT_DIRECTION_INHERIT);
-
- setBackground(backgroundDrawable);
- setClickable(true);
- setFocusable(true);
- setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, mSuggestionHeight));
- setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // Post the selection action to the end of the UI thread to allow the suggestion
- // view a chance to update their background selection state.
- PerformSelectSuggestion performSelection = new PerformSelectSuggestion();
- if (!post(performSelection)) performSelection.run();
- }
- });
- setOnLongClickListener(new OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- RecordUserAction.record("MobileOmniboxDeleteGesture");
- if (!mSuggestion.isDeletable()) return true;
-
- AlertDialog.Builder b =
- new AlertDialog.Builder(getContext(), R.style.AlertDialogTheme);
- b.setTitle(mSuggestion.getDisplayText());
- b.setMessage(R.string.omnibox_confirm_delete);
- DialogInterface.OnClickListener okListener =
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- RecordUserAction.record("MobileOmniboxDeleteRequested");
- mSuggestionDelegate.onDeleteSuggestion(mPosition);
- }
- };
- b.setPositiveButton(android.R.string.ok, okListener);
- DialogInterface.OnClickListener cancelListener =
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.cancel();
- }
- };
- b.setNegativeButton(android.R.string.cancel, cancelListener);
-
- AlertDialog dialog = b.create();
- dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
- @Override
- public void onDismiss(DialogInterface dialog) {
- mSuggestionDelegate.onHideModal();
- }
- });
-
- mSuggestionDelegate.onShowModal();
- dialog.show();
- return true;
- }
- });
-
- mTextLine1 = new TextView(context);
- mTextLine1.setLayoutParams(
- new LayoutParams(LayoutParams.WRAP_CONTENT, mSuggestionHeight));
- mTextLine1.setSingleLine();
- mTextLine1.setTextColor(getStandardFontColor());
- addView(mTextLine1);
-
- mTextLine2 = new TextView(context);
- mTextLine2.setLayoutParams(
- new LayoutParams(LayoutParams.WRAP_CONTENT, mSuggestionHeight));
- mTextLine2.setSingleLine();
- mTextLine2.setVisibility(INVISIBLE);
- addView(mTextLine2);
-
- mAnswerImage = new ImageView(context);
- mAnswerImage.setVisibility(GONE);
- mAnswerImage.setScaleType(ImageView.ScaleType.FIT_CENTER);
- mAnswerImage.setLayoutParams(new LayoutParams(0, 0));
- mAnswerImageMaxSize = 0;
- addView(mAnswerImage);
- }
-
- private void resetTextWidths() {
- mRequiredWidth = 0;
- mMatchContentsWidth = 0;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- if (DeviceFormFactor.isTablet(getContext())) {
- // Use the same image transform matrix as the navigation icon to ensure the same
- // scaling, which requires centering vertically based on the height of the
- // navigation icon view and not the image itself.
- canvas.save();
- mSuggestionIconLeft = getSuggestionIconLeftPosition();
- canvas.translate(
- mSuggestionIconLeft,
- (getMeasuredHeight() - mNavigationButton.getMeasuredHeight()) / 2f);
- canvas.concat(mNavigationButton.getImageMatrix());
- mSuggestionIcon.draw(canvas);
- canvas.restore();
- }
- }
-
- @Override
- protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
- if (child != mTextLine1 && child != mTextLine2 && child != mAnswerImage) {
- return super.drawChild(canvas, child, drawingTime);
- }
-
- int height = getMeasuredHeight();
- int line1Height = mTextLine1.getMeasuredHeight();
- int line2Height = mTextLine2.getVisibility() == VISIBLE
- ? mTextLine2.getMeasuredHeight() : 0;
-
- int verticalOffset = 0;
- if (line1Height + line2Height > height) {
- // The text lines total height is larger than this view, snap them to the top and
- // bottom of the view.
- if (child == mTextLine1) {
- verticalOffset = 0;
- } else {
- verticalOffset = height - line2Height;
- }
- } else {
- // The text lines fit comfortably, so vertically center them.
- verticalOffset = (height - line1Height - line2Height) / 2;
- if (child == mTextLine2) verticalOffset += line1Height;
-
- // When one line is larger than the other, it contains extra vertical padding. This
- // produces more apparent whitespace above or below the text lines. Add a small
- // offset to compensate.
- if (line1Height != line2Height) {
- verticalOffset += (line2Height - line1Height) / 10;
- }
-
- // The image is positioned vertically aligned with the second text line but
- // requires a small additional offset to align with the ascent of the text instead
- // of the top of the text which includes some whitespace.
- if (child == mAnswerImage) {
- verticalOffset += ANSWER_IMAGE_VERTICAL_SPACING_DP
- * getResources().getDisplayMetrics().density;
- }
- }
-
- canvas.save();
- canvas.translate(0, verticalOffset);
- boolean retVal = super.drawChild(canvas, child, drawingTime);
- canvas.restore();
- return retVal;
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- View locationBarView = mLocationBar.getContainerView();
- if (mUrlBar == null) {
- mUrlBar = (UrlBar) locationBarView.findViewById(R.id.url_bar);
- mUrlBar.addOnLayoutChangeListener(this);
- }
- if (mNavigationButton == null) {
- mNavigationButton =
- (ImageView) locationBarView.findViewById(R.id.navigation_button);
- mNavigationButton.addOnLayoutChangeListener(this);
- }
-
- // Align the text to be pixel perfectly aligned with the text in the url bar.
- mTextLeft = getSuggestionTextLeftPosition();
- mTextRight = getSuggestionTextRightPosition();
- boolean isRTL = ApiCompatibilityUtils.isLayoutRtl(this);
- if (DeviceFormFactor.isTablet(getContext())) {
- int textWidth = isRTL ? mTextRight : (r - l - mTextLeft);
- final float maxRequiredWidth = mSuggestionDelegate.getMaxRequiredWidth();
- final float maxMatchContentsWidth = mSuggestionDelegate.getMaxMatchContentsWidth();
- float paddingStart = (textWidth > maxRequiredWidth)
- ? (mRequiredWidth - mMatchContentsWidth)
- : Math.max(textWidth - maxMatchContentsWidth, 0);
- ApiCompatibilityUtils.setPaddingRelative(
- mTextLine1, (int) paddingStart, mTextLine1.getPaddingTop(),
- 0, // TODO(skanuj) : Change to ApiCompatibilityUtils.getPaddingEnd(...).
- mTextLine1.getPaddingBottom());
- }
-
- int imageWidth = mAnswerImageMaxSize;
- int imageSpacing = 0;
- if (mAnswerImage.getVisibility() == VISIBLE && imageWidth > 0) {
- float density = getResources().getDisplayMetrics().density;
- imageSpacing = (int) (ANSWER_IMAGE_HORIZONTAL_SPACING_DP * density);
- }
- if (isRTL) {
- mTextLine1.layout(0, t, mTextRight, b);
- mAnswerImage.layout(mTextRight - imageWidth , t, mTextRight, b);
- mTextLine2.layout(0, t, mTextRight - (imageWidth + imageSpacing), b);
- } else {
- mTextLine1.layout(mTextLeft, t, r - l, b);
- mAnswerImage.layout(mTextLeft, t, mTextLeft + imageWidth, b);
- mTextLine2.layout(mTextLeft + imageWidth + imageSpacing, t, r - l, b);
- }
-
- int suggestionIconPosition = getSuggestionIconLeftPosition();
- if (mSuggestionIconLeft != suggestionIconPosition
- && mSuggestionIconLeft != Integer.MIN_VALUE) {
- mContentsView.postInvalidateOnAnimation();
- }
- mSuggestionIconLeft = suggestionIconPosition;
- }
-
- /**
- * @return The left offset for the suggestion text that will align it with the url text.
- */
- private int getSuggestionTextLeftPosition() {
- if (mLocationBar == null) return 0;
-
- int textLeftPosition = getUrlBarTextLeftPosition();
- getLocationOnScreen(mViewPositionHolder);
- return textLeftPosition - mViewPositionHolder[0];
- }
-
- /**
- * @return The right offset for the suggestion text that will align it with the url text.
- */
- private int getSuggestionTextRightPosition() {
- if (mLocationBar == null) return 0;
-
- int textRightPosition = getUrlBarTextRightPosition();
- getLocationOnScreen(mViewPositionHolder);
- return textRightPosition - mViewPositionHolder[0];
- }
-
- /**
- * @return The left offset for the suggestion type icon that aligns it with the url bar.
- */
- private int getSuggestionIconLeftPosition() {
- if (mNavigationButton == null) return 0;
-
- // Ensure the suggestion icon matches the location of the navigation icon in the omnibox
- // perfectly.
- mNavigationButton.getLocationOnScreen(mViewPositionHolder);
- int navButtonXPosition = mViewPositionHolder[0] + mNavigationButton.getPaddingLeft();
-
- getLocationOnScreen(mViewPositionHolder);
-
- return navButtonXPosition - mViewPositionHolder[0];
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
- int width = MeasureSpec.getSize(widthMeasureSpec);
- int height = MeasureSpec.getSize(heightMeasureSpec);
-
- if (mTextLine1.getMeasuredWidth() != width
- || mTextLine1.getMeasuredHeight() != height) {
- mTextLine1.measure(
- MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.AT_MOST),
- MeasureSpec.makeMeasureSpec(mSuggestionHeight, MeasureSpec.AT_MOST));
- }
-
- if (mTextLine2.getMeasuredWidth() != width
- || mTextLine2.getMeasuredHeight() != height) {
- mTextLine2.measure(
- MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.AT_MOST),
- MeasureSpec.makeMeasureSpec(mSuggestionHeight, MeasureSpec.AT_MOST));
- }
- }
-
- @Override
- public void invalidate() {
- if (getSuggestionTextLeftPosition() != mTextLeft
- || getSuggestionTextRightPosition() != mTextRight) {
- // When the text position is changed, it typically is caused by the suggestions
- // appearing while the URL bar on the phone is gaining focus (if you trigger an
- // intent that will result in suggestions being shown before focusing the omnibox).
- // Triggering a relayout will cause any animations to stutter, so we continually
- // push the relayout to end of the UI queue until the animation is complete.
- removeCallbacks(mRelayoutRunnable);
- postDelayed(mRelayoutRunnable, RELAYOUT_DELAY_MS);
- } else {
- super.invalidate();
- }
- }
-
- @Override
- public boolean isFocused() {
- return mForceIsFocused || super.isFocused();
- }
-
- @Override
- protected int[] onCreateDrawableState(int extraSpace) {
- // When creating the drawable states, treat selected as focused to get the proper
- // highlight when in non-touch mode (i.e. physical keyboard). This is because only
- // a single view in a window can have focus, and the these will only appear if
- // the omnibox has focus, so we trick the drawable state into believing it has it.
- mForceIsFocused = isSelected() && !isInTouchMode();
- int[] drawableState = super.onCreateDrawableState(extraSpace);
- mForceIsFocused = false;
- return drawableState;
- }
-
- private void setSuggestionIcon(SuggestionIconType type, boolean invalidateCurrentIcon) {
- if (mSuggestionIconType == type && !invalidateCurrentIcon) return;
-
- int drawableId = R.drawable.ic_omnibox_page;
- switch (type) {
- case BOOKMARK:
- drawableId = R.drawable.btn_star;
- break;
- case MAGNIFIER:
- drawableId = R.drawable.ic_suggestion_magnifier;
- break;
- case HISTORY:
- drawableId = R.drawable.ic_suggestion_history;
- break;
- case VOICE:
- drawableId = R.drawable.btn_mic;
- break;
- default:
- break;
- }
- mSuggestionIcon = ApiCompatibilityUtils.getDrawable(getResources(), drawableId);
- mSuggestionIcon.setColorFilter(mUseDarkColors
- ? getResources().getColor(R.color.light_normal_color)
- : Color.WHITE, PorterDuff.Mode.SRC_IN);
- mSuggestionIcon.setBounds(
- 0, 0,
- mSuggestionIcon.getIntrinsicWidth(),
- mSuggestionIcon.getIntrinsicHeight());
- mSuggestionIconType = type;
- invalidate();
- }
-
- @Override
- public void onLayoutChange(
- View v, int left, int top, int right, int bottom, int oldLeft,
- int oldTop, int oldRight, int oldBottom) {
- boolean needsInvalidate = false;
- if (v == mNavigationButton) {
- if (mSuggestionIconLeft != getSuggestionIconLeftPosition()
- && mSuggestionIconLeft != Integer.MIN_VALUE) {
- needsInvalidate = true;
- }
- } else {
- if (mTextLeft != getSuggestionTextLeftPosition()
- && mTextLeft != Integer.MIN_VALUE) {
- needsInvalidate = true;
- }
- if (mTextRight != getSuggestionTextRightPosition()
- && mTextRight != Integer.MIN_VALUE) {
- needsInvalidate = true;
- }
- }
- if (needsInvalidate) {
- removeCallbacks(mRelayoutRunnable);
- postDelayed(mRelayoutRunnable, RELAYOUT_DELAY_MS);
- }
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- if (mNavigationButton != null) mNavigationButton.addOnLayoutChangeListener(this);
- if (mUrlBar != null) mUrlBar.addOnLayoutChangeListener(this);
- if (mLocationBar != null) {
- mLocationBar.getContainerView().addOnLayoutChangeListener(this);
- }
- getRootView().addOnLayoutChangeListener(this);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- if (mNavigationButton != null) mNavigationButton.removeOnLayoutChangeListener(this);
- if (mUrlBar != null) mUrlBar.removeOnLayoutChangeListener(this);
- if (mLocationBar != null) {
- mLocationBar.getContainerView().removeOnLayoutChangeListener(this);
- }
- getRootView().removeOnLayoutChangeListener(this);
-
- super.onDetachedFromWindow();
- }
- }
-}

Powered by Google App Engine
This is Rietveld 408576698