aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java')
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java650
1 files changed, 0 insertions, 650 deletions
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
deleted file mode 100644
index 9577d0913..000000000
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
+++ /dev/null
@@ -1,650 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.inputmethod.latin.suggestions;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.Rect;
-import android.graphics.Typeface;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.Spanned;
-import android.text.TextPaint;
-import android.text.TextUtils;
-import android.text.style.CharacterStyle;
-import android.text.style.StyleSpan;
-import android.text.style.UnderlineSpan;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.inputmethod.accessibility.AccessibilityUtils;
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.PunctuationSuggestions;
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.SuggestedWords;
-import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
-import com.android.inputmethod.latin.settings.Settings;
-import com.android.inputmethod.latin.settings.SettingsValues;
-import com.android.inputmethod.latin.utils.ResourceUtils;
-import com.android.inputmethod.latin.utils.ViewLayoutUtils;
-
-import java.util.ArrayList;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-final class SuggestionStripLayoutHelper {
- private static final int DEFAULT_SUGGESTIONS_COUNT_IN_STRIP = 3;
- private static final float DEFAULT_CENTER_SUGGESTION_PERCENTILE = 0.40f;
- private static final int DEFAULT_MAX_MORE_SUGGESTIONS_ROW = 2;
- private static final int PUNCTUATIONS_IN_STRIP = 5;
- private static final float MIN_TEXT_XSCALE = 0.70f;
-
- public final int mPadding;
- public final int mDividerWidth;
- public final int mSuggestionsStripHeight;
- private final int mSuggestionsCountInStrip;
- public final int mMoreSuggestionsRowHeight;
- private int mMaxMoreSuggestionsRow;
- public final float mMinMoreSuggestionsWidth;
- public final int mMoreSuggestionsBottomGap;
- private boolean mMoreSuggestionsAvailable;
-
- // The index of these {@link ArrayList} is the position in the suggestion strip. The indices
- // increase towards the right for LTR scripts and the left for RTL scripts, starting with 0.
- // The position of the most important suggestion is in {@link #mCenterPositionInStrip}
- private final ArrayList<TextView> mWordViews;
- private final ArrayList<View> mDividerViews;
- private final ArrayList<TextView> mDebugInfoViews;
-
- private final int mColorValidTypedWord;
- private final int mColorTypedWord;
- private final int mColorAutoCorrect;
- private final int mColorSuggested;
- private final float mAlphaObsoleted;
- private final float mCenterSuggestionWeight;
- private final int mCenterPositionInStrip;
- private final int mTypedWordPositionWhenAutocorrect;
- private final Drawable mMoreSuggestionsHint;
- private static final String MORE_SUGGESTIONS_HINT = "\u2026";
-
- private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
- private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
-
- private final int mSuggestionStripOptions;
- // These constants are the flag values of
- // {@link R.styleable#SuggestionStripView_suggestionStripOptions} attribute.
- private static final int AUTO_CORRECT_BOLD = 0x01;
- private static final int AUTO_CORRECT_UNDERLINE = 0x02;
- private static final int VALID_TYPED_WORD_BOLD = 0x04;
-
- public SuggestionStripLayoutHelper(final Context context, final AttributeSet attrs,
- final int defStyle, final ArrayList<TextView> wordViews,
- final ArrayList<View> dividerViews, final ArrayList<TextView> debugInfoViews) {
- mWordViews = wordViews;
- mDividerViews = dividerViews;
- mDebugInfoViews = debugInfoViews;
-
- final TextView wordView = wordViews.get(0);
- final View dividerView = dividerViews.get(0);
- mPadding = wordView.getCompoundPaddingLeft() + wordView.getCompoundPaddingRight();
- dividerView.measure(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
- mDividerWidth = dividerView.getMeasuredWidth();
-
- final Resources res = wordView.getResources();
- mSuggestionsStripHeight = res.getDimensionPixelSize(
- R.dimen.config_suggestions_strip_height);
-
- final TypedArray a = context.obtainStyledAttributes(attrs,
- R.styleable.SuggestionStripView, defStyle, R.style.SuggestionStripView);
- mSuggestionStripOptions = a.getInt(
- R.styleable.SuggestionStripView_suggestionStripOptions, 0);
- mAlphaObsoleted = ResourceUtils.getFraction(a,
- R.styleable.SuggestionStripView_alphaObsoleted, 1.0f);
- mColorValidTypedWord = a.getColor(R.styleable.SuggestionStripView_colorValidTypedWord, 0);
- mColorTypedWord = a.getColor(R.styleable.SuggestionStripView_colorTypedWord, 0);
- mColorAutoCorrect = a.getColor(R.styleable.SuggestionStripView_colorAutoCorrect, 0);
- mColorSuggested = a.getColor(R.styleable.SuggestionStripView_colorSuggested, 0);
- mSuggestionsCountInStrip = a.getInt(
- R.styleable.SuggestionStripView_suggestionsCountInStrip,
- DEFAULT_SUGGESTIONS_COUNT_IN_STRIP);
- mCenterSuggestionWeight = ResourceUtils.getFraction(a,
- R.styleable.SuggestionStripView_centerSuggestionPercentile,
- DEFAULT_CENTER_SUGGESTION_PERCENTILE);
- mMaxMoreSuggestionsRow = a.getInt(
- R.styleable.SuggestionStripView_maxMoreSuggestionsRow,
- DEFAULT_MAX_MORE_SUGGESTIONS_ROW);
- mMinMoreSuggestionsWidth = ResourceUtils.getFraction(a,
- R.styleable.SuggestionStripView_minMoreSuggestionsWidth, 1.0f);
- a.recycle();
-
- mMoreSuggestionsHint = getMoreSuggestionsHint(res,
- res.getDimension(R.dimen.config_more_suggestions_hint_text_size),
- mColorAutoCorrect);
- mCenterPositionInStrip = mSuggestionsCountInStrip / 2;
- // Assuming there are at least three suggestions. Also, note that the suggestions are
- // laid out according to script direction, so this is left of the center for LTR scripts
- // and right of the center for RTL scripts.
- mTypedWordPositionWhenAutocorrect = mCenterPositionInStrip - 1;
- mMoreSuggestionsBottomGap = res.getDimensionPixelOffset(
- R.dimen.config_more_suggestions_bottom_gap);
- mMoreSuggestionsRowHeight = res.getDimensionPixelSize(
- R.dimen.config_more_suggestions_row_height);
- }
-
- public int getMaxMoreSuggestionsRow() {
- return mMaxMoreSuggestionsRow;
- }
-
- private int getMoreSuggestionsHeight() {
- return mMaxMoreSuggestionsRow * mMoreSuggestionsRowHeight + mMoreSuggestionsBottomGap;
- }
-
- public void setMoreSuggestionsHeight(final int remainingHeight) {
- final int currentHeight = getMoreSuggestionsHeight();
- if (currentHeight <= remainingHeight) {
- return;
- }
-
- mMaxMoreSuggestionsRow = (remainingHeight - mMoreSuggestionsBottomGap)
- / mMoreSuggestionsRowHeight;
- }
-
- private static Drawable getMoreSuggestionsHint(final Resources res, final float textSize,
- final int color) {
- final Paint paint = new Paint();
- paint.setAntiAlias(true);
- paint.setTextAlign(Align.CENTER);
- paint.setTextSize(textSize);
- paint.setColor(color);
- final Rect bounds = new Rect();
- paint.getTextBounds(MORE_SUGGESTIONS_HINT, 0, MORE_SUGGESTIONS_HINT.length(), bounds);
- final int width = Math.round(bounds.width() + 0.5f);
- final int height = Math.round(bounds.height() + 0.5f);
- final Bitmap buffer = Bitmap.createBitmap(width, (height * 3 / 2), Bitmap.Config.ARGB_8888);
- final Canvas canvas = new Canvas(buffer);
- canvas.drawText(MORE_SUGGESTIONS_HINT, width / 2, height, paint);
- BitmapDrawable bitmapDrawable = new BitmapDrawable(res, buffer);
- bitmapDrawable.setTargetDensity(canvas);
- return bitmapDrawable;
- }
-
- private CharSequence getStyledSuggestedWord(final SuggestedWords suggestedWords,
- final int indexInSuggestedWords) {
- if (indexInSuggestedWords >= suggestedWords.size()) {
- return null;
- }
- final String word = suggestedWords.getLabel(indexInSuggestedWords);
- // TODO: don't use the index to decide whether this is the auto-correction/typed word, as
- // this is brittle
- final boolean isAutoCorrection = suggestedWords.mWillAutoCorrect
- && indexInSuggestedWords == SuggestedWords.INDEX_OF_AUTO_CORRECTION;
- final boolean isTypedWordValid = suggestedWords.mTypedWordValid
- && indexInSuggestedWords == SuggestedWords.INDEX_OF_TYPED_WORD;
- if (!isAutoCorrection && !isTypedWordValid) {
- return word;
- }
-
- final Spannable spannedWord = new SpannableString(word);
- final int options = mSuggestionStripOptions;
- if ((isAutoCorrection && (options & AUTO_CORRECT_BOLD) != 0)
- || (isTypedWordValid && (options & VALID_TYPED_WORD_BOLD) != 0)) {
- addStyleSpan(spannedWord, BOLD_SPAN);
- }
- if (isAutoCorrection && (options & AUTO_CORRECT_UNDERLINE) != 0) {
- addStyleSpan(spannedWord, UNDERLINE_SPAN);
- }
- return spannedWord;
- }
-
- /**
- * Convert an index of {@link SuggestedWords} to position in the suggestion strip.
- * @param indexInSuggestedWords the index of {@link SuggestedWords}.
- * @param suggestedWords the suggested words list
- * @return Non-negative integer of the position in the suggestion strip.
- * Negative integer if the word of the index shouldn't be shown on the suggestion strip.
- */
- private int getPositionInSuggestionStrip(final int indexInSuggestedWords,
- final SuggestedWords suggestedWords) {
- final SettingsValues settingsValues = Settings.getInstance().getCurrent();
- final boolean shouldOmitTypedWord = shouldOmitTypedWord(suggestedWords.mInputStyle,
- settingsValues.mGestureFloatingPreviewTextEnabled,
- settingsValues.mShouldShowLxxSuggestionUi);
- return getPositionInSuggestionStrip(indexInSuggestedWords, suggestedWords.mWillAutoCorrect,
- settingsValues.mShouldShowLxxSuggestionUi && shouldOmitTypedWord,
- mCenterPositionInStrip, mTypedWordPositionWhenAutocorrect);
- }
-
- @UsedForTesting
- static boolean shouldOmitTypedWord(final int inputStyle,
- final boolean gestureFloatingPreviewTextEnabled,
- final boolean shouldShowUiToAcceptTypedWord) {
- final boolean omitTypedWord = (inputStyle == SuggestedWords.INPUT_STYLE_TYPING)
- || (inputStyle == SuggestedWords.INPUT_STYLE_TAIL_BATCH)
- || (inputStyle == SuggestedWords.INPUT_STYLE_UPDATE_BATCH
- && gestureFloatingPreviewTextEnabled);
- return shouldShowUiToAcceptTypedWord && omitTypedWord;
- }
-
- @UsedForTesting
- static int getPositionInSuggestionStrip(final int indexInSuggestedWords,
- final boolean willAutoCorrect, final boolean omitTypedWord,
- final int centerPositionInStrip, final int typedWordPositionWhenAutoCorrect) {
- if (omitTypedWord) {
- if (indexInSuggestedWords == SuggestedWords.INDEX_OF_TYPED_WORD) {
- // Ignore.
- return -1;
- }
- if (indexInSuggestedWords == SuggestedWords.INDEX_OF_AUTO_CORRECTION) {
- // Center in the suggestion strip.
- return centerPositionInStrip;
- }
- // If neither of those, the order in the suggestion strip is left of the center first
- // then right of the center, to both edges of the suggestion strip.
- // For example, center-1, center+1, center-2, center+2, and so on.
- final int n = indexInSuggestedWords;
- final int offsetFromCenter = (n % 2) == 0 ? -(n / 2) : (n / 2);
- final int positionInSuggestionStrip = centerPositionInStrip + offsetFromCenter;
- return positionInSuggestionStrip;
- }
- final int indexToDisplayMostImportantSuggestion;
- final int indexToDisplaySecondMostImportantSuggestion;
- if (willAutoCorrect) {
- indexToDisplayMostImportantSuggestion = SuggestedWords.INDEX_OF_AUTO_CORRECTION;
- indexToDisplaySecondMostImportantSuggestion = SuggestedWords.INDEX_OF_TYPED_WORD;
- } else {
- indexToDisplayMostImportantSuggestion = SuggestedWords.INDEX_OF_TYPED_WORD;
- indexToDisplaySecondMostImportantSuggestion = SuggestedWords.INDEX_OF_AUTO_CORRECTION;
- }
- if (indexInSuggestedWords == indexToDisplayMostImportantSuggestion) {
- // Center in the suggestion strip.
- return centerPositionInStrip;
- }
- if (indexInSuggestedWords == indexToDisplaySecondMostImportantSuggestion) {
- // Center-1.
- return typedWordPositionWhenAutoCorrect;
- }
- // If neither of those, the order in the suggestion strip is right of the center first
- // then left of the center, to both edges of the suggestion strip.
- // For example, Center+1, center-2, center+2, center-3, and so on.
- final int n = indexInSuggestedWords + 1;
- final int offsetFromCenter = (n % 2) == 0 ? -(n / 2) : (n / 2);
- final int positionInSuggestionStrip = centerPositionInStrip + offsetFromCenter;
- return positionInSuggestionStrip;
- }
-
- private int getSuggestionTextColor(final SuggestedWords suggestedWords,
- final int indexInSuggestedWords) {
- // Use identity for strings, not #equals : it's the typed word if it's the same object
- final boolean isTypedWord = suggestedWords.getInfo(indexInSuggestedWords).isKindOf(
- SuggestedWordInfo.KIND_TYPED);
-
- final int color;
- if (indexInSuggestedWords == SuggestedWords.INDEX_OF_AUTO_CORRECTION
- && suggestedWords.mWillAutoCorrect) {
- color = mColorAutoCorrect;
- } else if (isTypedWord && suggestedWords.mTypedWordValid) {
- color = mColorValidTypedWord;
- } else if (isTypedWord) {
- color = mColorTypedWord;
- } else {
- color = mColorSuggested;
- }
- if (suggestedWords.mIsObsoleteSuggestions && !isTypedWord) {
- return applyAlpha(color, mAlphaObsoleted);
- }
- return color;
- }
-
- private static int applyAlpha(final int color, final float alpha) {
- final int newAlpha = (int)(Color.alpha(color) * alpha);
- return Color.argb(newAlpha, Color.red(color), Color.green(color), Color.blue(color));
- }
-
- private static void addDivider(final ViewGroup stripView, final View dividerView) {
- stripView.addView(dividerView);
- final LinearLayout.LayoutParams params =
- (LinearLayout.LayoutParams)dividerView.getLayoutParams();
- params.gravity = Gravity.CENTER;
- }
-
- /**
- * Layout suggestions to the suggestions strip. And returns the start index of more
- * suggestions.
- *
- * @param suggestedWords suggestions to be shown in the suggestions strip.
- * @param stripView the suggestions strip view.
- * @param placerView the view where the debug info will be placed.
- * @return the start index of more suggestions.
- */
- public int layoutAndReturnStartIndexOfMoreSuggestions(
- final Context context,
- final SuggestedWords suggestedWords,
- final ViewGroup stripView,
- final ViewGroup placerView) {
- if (suggestedWords.isPunctuationSuggestions()) {
- return layoutPunctuationsAndReturnStartIndexOfMoreSuggestions(
- (PunctuationSuggestions)suggestedWords, stripView);
- }
-
- final int wordCountToShow = suggestedWords.getWordCountToShow(
- Settings.getInstance().getCurrent().mShouldShowLxxSuggestionUi);
- final int startIndexOfMoreSuggestions = setupWordViewsAndReturnStartIndexOfMoreSuggestions(
- suggestedWords, mSuggestionsCountInStrip);
- final TextView centerWordView = mWordViews.get(mCenterPositionInStrip);
- final int stripWidth = stripView.getWidth();
- final int centerWidth = getSuggestionWidth(mCenterPositionInStrip, stripWidth);
- if (wordCountToShow == 1 || getTextScaleX(centerWordView.getText(), centerWidth,
- centerWordView.getPaint()) < MIN_TEXT_XSCALE) {
- // Layout only the most relevant suggested word at the center of the suggestion strip
- // by consolidating all slots in the strip.
- final int countInStrip = 1;
- mMoreSuggestionsAvailable = (wordCountToShow > countInStrip);
- layoutWord(context, mCenterPositionInStrip, stripWidth - mPadding);
- stripView.addView(centerWordView);
- setLayoutWeight(centerWordView, 1.0f, ViewGroup.LayoutParams.MATCH_PARENT);
- if (SuggestionStripView.DBG) {
- layoutDebugInfo(mCenterPositionInStrip, placerView, stripWidth);
- }
- final Integer lastIndex = (Integer)centerWordView.getTag();
- return (lastIndex == null ? 0 : lastIndex) + 1;
- }
-
- final int countInStrip = mSuggestionsCountInStrip;
- mMoreSuggestionsAvailable = (wordCountToShow > countInStrip);
- @SuppressWarnings("unused")
- int x = 0;
- for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) {
- if (positionInStrip != 0) {
- final View divider = mDividerViews.get(positionInStrip);
- // Add divider if this isn't the left most suggestion in suggestions strip.
- addDivider(stripView, divider);
- x += divider.getMeasuredWidth();
- }
-
- final int width = getSuggestionWidth(positionInStrip, stripWidth);
- final TextView wordView = layoutWord(context, positionInStrip, width);
- stripView.addView(wordView);
- setLayoutWeight(wordView, getSuggestionWeight(positionInStrip),
- ViewGroup.LayoutParams.MATCH_PARENT);
- x += wordView.getMeasuredWidth();
-
- if (SuggestionStripView.DBG) {
- layoutDebugInfo(positionInStrip, placerView, x);
- }
- }
- return startIndexOfMoreSuggestions;
- }
-
- /**
- * Format appropriately the suggested word in {@link #mWordViews} specified by
- * <code>positionInStrip</code>. When the suggested word doesn't exist, the corresponding
- * {@link TextView} will be disabled and never respond to user interaction. The suggested word
- * may be shrunk or ellipsized to fit in the specified width.
- *
- * The <code>positionInStrip</code> argument is the index in the suggestion strip. The indices
- * increase towards the right for LTR scripts and the left for RTL scripts, starting with 0.
- * The position of the most important suggestion is in {@link #mCenterPositionInStrip}. This
- * usually doesn't match the index in <code>suggedtedWords</code> -- see
- * {@link #getPositionInSuggestionStrip(int,SuggestedWords)}.
- *
- * @param positionInStrip the position in the suggestion strip.
- * @param width the maximum width for layout in pixels.
- * @return the {@link TextView} containing the suggested word appropriately formatted.
- */
- private TextView layoutWord(final Context context, final int positionInStrip, final int width) {
- final TextView wordView = mWordViews.get(positionInStrip);
- final CharSequence word = wordView.getText();
- if (positionInStrip == mCenterPositionInStrip && mMoreSuggestionsAvailable) {
- // TODO: This "more suggestions hint" should have a nicely designed icon.
- wordView.setCompoundDrawablesWithIntrinsicBounds(
- null, null, null, mMoreSuggestionsHint);
- // HACK: Align with other TextViews that have no compound drawables.
- wordView.setCompoundDrawablePadding(-mMoreSuggestionsHint.getIntrinsicHeight());
- } else {
- wordView.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
- }
- // {@link StyleSpan} in a content description may cause an issue of TTS/TalkBack.
- // Use a simple {@link String} to avoid the issue.
- wordView.setContentDescription(
- TextUtils.isEmpty(word)
- ? context.getResources().getString(R.string.spoken_empty_suggestion)
- : word.toString());
- final CharSequence text = getEllipsizedTextWithSettingScaleX(
- word, width, wordView.getPaint());
- final float scaleX = wordView.getTextScaleX();
- wordView.setText(text); // TextView.setText() resets text scale x to 1.0.
- wordView.setTextScaleX(scaleX);
- // A <code>wordView</code> should be disabled when <code>word</code> is empty in order to
- // make it unclickable.
- // With accessibility touch exploration on, <code>wordView</code> should be enabled even
- // when it is empty to avoid announcing as "disabled".
- wordView.setEnabled(!TextUtils.isEmpty(word)
- || AccessibilityUtils.getInstance().isTouchExplorationEnabled());
- return wordView;
- }
-
- private void layoutDebugInfo(final int positionInStrip, final ViewGroup placerView,
- final int x) {
- final TextView debugInfoView = mDebugInfoViews.get(positionInStrip);
- final CharSequence debugInfo = debugInfoView.getText();
- if (debugInfo == null) {
- return;
- }
- placerView.addView(debugInfoView);
- debugInfoView.measure(
- ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- final int infoWidth = debugInfoView.getMeasuredWidth();
- final int y = debugInfoView.getMeasuredHeight();
- ViewLayoutUtils.placeViewAt(
- debugInfoView, x - infoWidth, y, infoWidth, debugInfoView.getMeasuredHeight());
- }
-
- private int getSuggestionWidth(final int positionInStrip, final int maxWidth) {
- final int paddings = mPadding * mSuggestionsCountInStrip;
- final int dividers = mDividerWidth * (mSuggestionsCountInStrip - 1);
- final int availableWidth = maxWidth - paddings - dividers;
- return (int)(availableWidth * getSuggestionWeight(positionInStrip));
- }
-
- private float getSuggestionWeight(final int positionInStrip) {
- if (positionInStrip == mCenterPositionInStrip) {
- return mCenterSuggestionWeight;
- }
- // TODO: Revisit this for cases of 5 or more suggestions
- return (1.0f - mCenterSuggestionWeight) / (mSuggestionsCountInStrip - 1);
- }
-
- private int setupWordViewsAndReturnStartIndexOfMoreSuggestions(
- final SuggestedWords suggestedWords, final int maxSuggestionInStrip) {
- // Clear all suggestions first
- for (int positionInStrip = 0; positionInStrip < maxSuggestionInStrip; ++positionInStrip) {
- final TextView wordView = mWordViews.get(positionInStrip);
- wordView.setText(null);
- wordView.setTag(null);
- // Make this inactive for touches in {@link #layoutWord(int,int)}.
- if (SuggestionStripView.DBG) {
- mDebugInfoViews.get(positionInStrip).setText(null);
- }
- }
- int count = 0;
- int indexInSuggestedWords;
- for (indexInSuggestedWords = 0; indexInSuggestedWords < suggestedWords.size()
- && count < maxSuggestionInStrip; indexInSuggestedWords++) {
- final int positionInStrip =
- getPositionInSuggestionStrip(indexInSuggestedWords, suggestedWords);
- if (positionInStrip < 0) {
- continue;
- }
- final TextView wordView = mWordViews.get(positionInStrip);
- // {@link TextView#getTag()} is used to get the index in suggestedWords at
- // {@link SuggestionStripView#onClick(View)}.
- wordView.setTag(indexInSuggestedWords);
- wordView.setText(getStyledSuggestedWord(suggestedWords, indexInSuggestedWords));
- wordView.setTextColor(getSuggestionTextColor(suggestedWords, indexInSuggestedWords));
- if (SuggestionStripView.DBG) {
- mDebugInfoViews.get(positionInStrip).setText(
- suggestedWords.getDebugString(indexInSuggestedWords));
- }
- count++;
- }
- return indexInSuggestedWords;
- }
-
- private int layoutPunctuationsAndReturnStartIndexOfMoreSuggestions(
- final PunctuationSuggestions punctuationSuggestions, final ViewGroup stripView) {
- final int countInStrip = Math.min(punctuationSuggestions.size(), PUNCTUATIONS_IN_STRIP);
- for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) {
- if (positionInStrip != 0) {
- // Add divider if this isn't the left most suggestion in suggestions strip.
- addDivider(stripView, mDividerViews.get(positionInStrip));
- }
-
- final TextView wordView = mWordViews.get(positionInStrip);
- final String punctuation = punctuationSuggestions.getLabel(positionInStrip);
- // {@link TextView#getTag()} is used to get the index in suggestedWords at
- // {@link SuggestionStripView#onClick(View)}.
- wordView.setTag(positionInStrip);
- wordView.setText(punctuation);
- wordView.setContentDescription(punctuation);
- wordView.setTextScaleX(1.0f);
- wordView.setCompoundDrawables(null, null, null, null);
- wordView.setTextColor(mColorAutoCorrect);
- stripView.addView(wordView);
- setLayoutWeight(wordView, 1.0f, mSuggestionsStripHeight);
- }
- mMoreSuggestionsAvailable = (punctuationSuggestions.size() > countInStrip);
- return countInStrip;
- }
-
- public void layoutImportantNotice(final View importantNoticeStrip,
- final String importantNoticeTitle) {
- final TextView titleView = (TextView)importantNoticeStrip.findViewById(
- R.id.important_notice_title);
- final int width = titleView.getWidth() - titleView.getPaddingLeft()
- - titleView.getPaddingRight();
- titleView.setTextColor(mColorAutoCorrect);
- titleView.setText(importantNoticeTitle); // TextView.setText() resets text scale x to 1.0.
- final float titleScaleX = getTextScaleX(importantNoticeTitle, width, titleView.getPaint());
- titleView.setTextScaleX(titleScaleX);
- }
-
- static void setLayoutWeight(final View v, final float weight, final int height) {
- final ViewGroup.LayoutParams lp = v.getLayoutParams();
- if (lp instanceof LinearLayout.LayoutParams) {
- final LinearLayout.LayoutParams llp = (LinearLayout.LayoutParams)lp;
- llp.weight = weight;
- llp.width = 0;
- llp.height = height;
- }
- }
-
- private static float getTextScaleX(@Nullable final CharSequence text, final int maxWidth,
- final TextPaint paint) {
- paint.setTextScaleX(1.0f);
- final int width = getTextWidth(text, paint);
- if (width <= maxWidth || maxWidth <= 0) {
- return 1.0f;
- }
- return maxWidth / (float) width;
- }
-
- @Nullable
- private static CharSequence getEllipsizedTextWithSettingScaleX(
- @Nullable final CharSequence text, final int maxWidth, @Nonnull final TextPaint paint) {
- if (text == null) {
- return null;
- }
- final float scaleX = getTextScaleX(text, maxWidth, paint);
- if (scaleX >= MIN_TEXT_XSCALE) {
- paint.setTextScaleX(scaleX);
- return text;
- }
-
- // <code>text</code> must be ellipsized with minimum text scale x.
- paint.setTextScaleX(MIN_TEXT_XSCALE);
- final boolean hasBoldStyle = hasStyleSpan(text, BOLD_SPAN);
- final boolean hasUnderlineStyle = hasStyleSpan(text, UNDERLINE_SPAN);
- // TextUtils.ellipsize erases any span object existed after ellipsized point.
- // We have to restore these spans afterward.
- final CharSequence ellipsizedText = TextUtils.ellipsize(
- text, paint, maxWidth, TextUtils.TruncateAt.MIDDLE);
- if (!hasBoldStyle && !hasUnderlineStyle) {
- return ellipsizedText;
- }
- final Spannable spannableText = (ellipsizedText instanceof Spannable)
- ? (Spannable)ellipsizedText : new SpannableString(ellipsizedText);
- if (hasBoldStyle) {
- addStyleSpan(spannableText, BOLD_SPAN);
- }
- if (hasUnderlineStyle) {
- addStyleSpan(spannableText, UNDERLINE_SPAN);
- }
- return spannableText;
- }
-
- private static boolean hasStyleSpan(@Nullable final CharSequence text,
- final CharacterStyle style) {
- if (text instanceof Spanned) {
- return ((Spanned)text).getSpanStart(style) >= 0;
- }
- return false;
- }
-
- private static void addStyleSpan(@Nonnull final Spannable text, final CharacterStyle style) {
- text.removeSpan(style);
- text.setSpan(style, 0, text.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
- }
-
- private static int getTextWidth(@Nullable final CharSequence text, final TextPaint paint) {
- if (TextUtils.isEmpty(text)) {
- return 0;
- }
- final int length = text.length();
- final float[] widths = new float[length];
- final int count;
- final Typeface savedTypeface = paint.getTypeface();
- try {
- paint.setTypeface(getTextTypeface(text));
- count = paint.getTextWidths(text, 0, length, widths);
- } finally {
- paint.setTypeface(savedTypeface);
- }
- int width = 0;
- for (int i = 0; i < count; i++) {
- width += Math.round(widths[i] + 0.5f);
- }
- return width;
- }
-
- private static Typeface getTextTypeface(@Nullable final CharSequence text) {
- return hasStyleSpan(text, BOLD_SPAN) ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT;
- }
-}