Merge "Using ListView for Suggestion popup window"

This commit is contained in:
Gilles Debunne
2011-09-01 11:42:23 -07:00
committed by Android (Google) Code Review
17 changed files with 162 additions and 152 deletions

View File

@@ -20702,7 +20702,6 @@ package android.text.style {
public class EasyEditSpan implements android.text.ParcelableSpan { public class EasyEditSpan implements android.text.ParcelableSpan {
ctor public EasyEditSpan(); ctor public EasyEditSpan();
ctor public EasyEditSpan(android.os.Parcel);
method public int describeContents(); method public int describeContents();
method public int getSpanTypeId(); method public int getSpanTypeId();
method public void writeToParcel(android.os.Parcel, int); method public void writeToParcel(android.os.Parcel, int);

View File

@@ -24,8 +24,8 @@ import android.text.style.AlignmentSpan;
import android.text.style.BackgroundColorSpan; import android.text.style.BackgroundColorSpan;
import android.text.style.BulletSpan; import android.text.style.BulletSpan;
import android.text.style.CharacterStyle; import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.text.style.EasyEditSpan; import android.text.style.EasyEditSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.LeadingMarginSpan; import android.text.style.LeadingMarginSpan;
import android.text.style.MetricAffectingSpan; import android.text.style.MetricAffectingSpan;
import android.text.style.QuoteSpan; import android.text.style.QuoteSpan;
@@ -748,11 +748,11 @@ public class TextUtils {
break; break;
case SUGGESTION_RANGE_SPAN: case SUGGESTION_RANGE_SPAN:
readSpan(p, sp, new SuggestionRangeSpan()); readSpan(p, sp, new SuggestionRangeSpan(p));
break; break;
case EASY_EDIT_SPAN: case EASY_EDIT_SPAN:
readSpan(p, sp, new EasyEditSpan(p)); readSpan(p, sp, new EasyEditSpan());
break; break;
default: default:

View File

@@ -33,10 +33,6 @@ public class EasyEditSpan implements ParcelableSpan {
// Empty // Empty
} }
public EasyEditSpan(Parcel src) {
this();
}
@Override @Override
public int describeContents() { public int describeContents() {
return 0; return 0;

View File

@@ -16,7 +16,6 @@
package android.text.style; package android.text.style;
import android.graphics.Color;
import android.os.Parcel; import android.os.Parcel;
import android.text.ParcelableSpan; import android.text.ParcelableSpan;
import android.text.TextPaint; import android.text.TextPaint;
@@ -29,12 +28,20 @@ import android.text.TextUtils;
* @hide * @hide
*/ */
public class SuggestionRangeSpan extends CharacterStyle implements ParcelableSpan { public class SuggestionRangeSpan extends CharacterStyle implements ParcelableSpan {
private final int mBackgroundColor;
@Override @Override
public void updateDrawState(TextPaint tp) { public void updateDrawState(TextPaint tp) {
tp.setColor(Color.GREEN); tp.bgColor = mBackgroundColor;
} }
public SuggestionRangeSpan() { /* Nothing to do*/ } public SuggestionRangeSpan(int color) {
mBackgroundColor = color;
}
public SuggestionRangeSpan(Parcel src) {
mBackgroundColor = src.readInt();
}
@Override @Override
public int describeContents() { public int describeContents() {
@@ -42,7 +49,9 @@ public class SuggestionRangeSpan extends CharacterStyle implements ParcelableSpa
} }
@Override @Override
public void writeToParcel(Parcel dest, int flags) { /* Nothing to do*/ } public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mBackgroundColor);
}
@Override @Override
public int getSpanTypeId() { public int getSpanTypeId() {

View File

@@ -1,4 +1,18 @@
// Copyright 2011 Google Inc. All Rights Reserved. /*
* Copyright (C) 2011 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 android.widget; package android.widget;
@@ -32,7 +46,7 @@ public class SpellChecker implements SpellCheckerSessionListener {
private final TextView mTextView; private final TextView mTextView;
final SpellCheckerSession spellCheckerSession; final SpellCheckerSession mSpellCheckerSession;
final int mCookie; final int mCookie;
// Paired arrays for the (id, spellCheckSpan) pair. mIndex is the next available position // Paired arrays for the (id, spellCheckSpan) pair. mIndex is the next available position
@@ -49,7 +63,7 @@ public class SpellChecker implements SpellCheckerSessionListener {
final TextServicesManager textServicesManager = (TextServicesManager) textView.getContext(). final TextServicesManager textServicesManager = (TextServicesManager) textView.getContext().
getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE); getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
spellCheckerSession = textServicesManager.newSpellCheckerSession( mSpellCheckerSession = textServicesManager.newSpellCheckerSession(
null /* not currently used by the textServicesManager */, Locale.getDefault(), null /* not currently used by the textServicesManager */, Locale.getDefault(),
this, true /* means use the languages defined in Settings */); this, true /* means use the languages defined in Settings */);
mCookie = hashCode(); mCookie = hashCode();
@@ -112,7 +126,7 @@ public class SpellChecker implements SpellCheckerSessionListener {
private void scheduleSpellCheck() { private void scheduleSpellCheck() {
if (mLength == 0) return; if (mLength == 0) return;
if (spellCheckerSession == null) return; if (mSpellCheckerSession == null) return;
if (mChecker != null) { if (mChecker != null) {
mTextView.removeCallbacks(mChecker); mTextView.removeCallbacks(mChecker);
@@ -157,7 +171,7 @@ public class SpellChecker implements SpellCheckerSessionListener {
System.arraycopy(textInfos, 0, textInfosCopy, 0, textInfosCount); System.arraycopy(textInfos, 0, textInfosCopy, 0, textInfosCount);
textInfos = textInfosCopy; textInfos = textInfosCopy;
} }
spellCheckerSession.getSuggestions(textInfos, SuggestionSpan.SUGGESTIONS_MAX_SIZE, mSpellCheckerSession.getSuggestions(textInfos, SuggestionSpan.SUGGESTIONS_MAX_SIZE,
false /* TODO Set sequentialWords to true for initial spell check */); false /* TODO Set sequentialWords to true for initial spell check */);
} }
} }

View File

@@ -63,8 +63,8 @@ import android.text.TextDirectionHeuristic;
import android.text.TextDirectionHeuristics; import android.text.TextDirectionHeuristics;
import android.text.TextPaint; import android.text.TextPaint;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.TextUtils.TruncateAt; import android.text.TextUtils.TruncateAt;
import android.text.TextWatcher;
import android.text.method.AllCapsTransformationMethod; import android.text.method.AllCapsTransformationMethod;
import android.text.method.ArrowKeyMovementMethod; import android.text.method.ArrowKeyMovementMethod;
import android.text.method.DateKeyListener; import android.text.method.DateKeyListener;
@@ -82,7 +82,6 @@ import android.text.method.TimeKeyListener;
import android.text.method.TransformationMethod; import android.text.method.TransformationMethod;
import android.text.method.TransformationMethod2; import android.text.method.TransformationMethod2;
import android.text.method.WordIterator; import android.text.method.WordIterator;
import android.text.style.CharacterStyle;
import android.text.style.ClickableSpan; import android.text.style.ClickableSpan;
import android.text.style.EasyEditSpan; import android.text.style.EasyEditSpan;
import android.text.style.ParagraphStyle; import android.text.style.ParagraphStyle;
@@ -131,6 +130,7 @@ import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.RemoteViews.RemoteView; import android.widget.RemoteViews.RemoteView;
import com.android.internal.util.FastMath; import com.android.internal.util.FastMath;
@@ -7868,7 +7868,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override @Override
protected void initContentView() { protected void initContentView() {
mContentView.setOrientation(LinearLayout.HORIZONTAL); LinearLayout linearLayout = new LinearLayout(TextView.this.getContext());
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
mContentView = linearLayout;
mContentView.setBackgroundResource( mContentView.setBackgroundResource(
com.android.internal.R.drawable.text_edit_side_paste_window); com.android.internal.R.drawable.text_edit_side_paste_window);
@@ -8177,17 +8179,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
startStopMarquee(hasWindowFocus); startStopMarquee(hasWindowFocus);
} }
private void removeSpans(int start, int end, Class<?> type) {
if (mText instanceof Editable) {
Editable editable = ((Editable) mText);
Object[] spans = editable.getSpans(start, end, type);
final int length = spans.length;
for (int i = 0; i < length; i++) {
editable.removeSpan(spans[i]);
}
}
}
@Override @Override
protected void onVisibilityChanged(View changedView, int visibility) { protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility); super.onVisibilityChanged(changedView, visibility);
@@ -9326,7 +9317,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private abstract class PinnedPopupWindow implements TextViewPositionListener { private abstract class PinnedPopupWindow implements TextViewPositionListener {
protected PopupWindow mPopupWindow; protected PopupWindow mPopupWindow;
protected LinearLayout mContentView; protected ViewGroup mContentView;
int mPositionX, mPositionY; int mPositionX, mPositionY;
protected abstract void createPopupWindow(); protected abstract void createPopupWindow();
@@ -9342,23 +9333,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mPopupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT); mPopupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
mPopupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); mPopupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
mContentView = new LinearLayout(TextView.this.getContext()); initContentView();
LayoutParams wrapContent = new LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); LayoutParams wrapContent = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
mContentView.setLayoutParams(wrapContent); mContentView.setLayoutParams(wrapContent);
initContentView();
mPopupWindow.setContentView(mContentView); mPopupWindow.setContentView(mContentView);
} }
public void show() { public void show() {
final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
mContentView.measure(
View.MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels,
View.MeasureSpec.AT_MOST),
View.MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels,
View.MeasureSpec.AT_MOST));
TextView.this.getPositionListener().addSubscriber(this, false); TextView.this.getPositionListener().addSubscriber(this, false);
computeLocalPosition(); computeLocalPosition();
@@ -9366,11 +9350,24 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final PositionListener positionListener = TextView.this.getPositionListener(); final PositionListener positionListener = TextView.this.getPositionListener();
updatePosition(positionListener.getPositionX(), positionListener.getPositionY()); updatePosition(positionListener.getPositionX(), positionListener.getPositionY());
} }
protected void measureContent() {
final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
mContentView.measure(
View.MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels,
View.MeasureSpec.AT_MOST),
View.MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels,
View.MeasureSpec.AT_MOST));
}
/* The popup window will be horizontally centered on the getTextOffset() and vertically
* positioned according to viewportToContentHorizontalOffset.
*
* This method assumes that mContentView has properly been measured from its content. */
private void computeLocalPosition() { private void computeLocalPosition() {
final int offset = getTextOffset(); measureContent();
final int width = mContentView.getMeasuredWidth(); final int width = mContentView.getMeasuredWidth();
final int offset = getTextOffset();
mPositionX = (int) (mLayout.getPrimaryHorizontal(offset) - width / 2.0f); mPositionX = (int) (mLayout.getPrimaryHorizontal(offset) - width / 2.0f);
mPositionX += viewportToContentHorizontalOffset(); mPositionX += viewportToContentHorizontalOffset();
@@ -9418,42 +9415,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
} }
} }
private static class SuggestionRangeSpan extends CharacterStyle { private class SuggestionsPopupWindow extends PinnedPopupWindow implements OnItemClickListener {
private final int mTextColor;
private final int mBackgroundColor;
public SuggestionRangeSpan(Context context) {
TypedArray typedArray = context.obtainStyledAttributes(null,
com.android.internal.R.styleable.SuggestionRangeSpan,
com.android.internal.R.attr.textAppearanceSuggestionRange, 0);
mTextColor = typedArray.getColor(
com.android.internal.R.styleable.SuggestionRangeSpan_textColor, 0);
mBackgroundColor = typedArray.getColor(
com.android.internal.R.styleable.SuggestionRangeSpan_colorBackground, 0);
}
@Override
public void updateDrawState(TextPaint tp) {
if (mTextColor != 0) {
tp.setColor(mTextColor);
}
if (mBackgroundColor != 0) {
tp.bgColor = mBackgroundColor;
}
}
}
private class SuggestionsPopupWindow extends PinnedPopupWindow implements OnClickListener {
private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE; private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE;
private static final int NO_SUGGESTIONS = -1; private static final int NO_SUGGESTIONS = -1;
private static final float AVERAGE_HIGHLIGHTS_PER_SUGGESTION = 1.4f; private static final float AVERAGE_HIGHLIGHTS_PER_SUGGESTION = 1.4f;
private WordIterator mSuggestionWordIterator; private WordIterator mSuggestionWordIterator;
private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan
[(int) (AVERAGE_HIGHLIGHTS_PER_SUGGESTION * MAX_NUMBER_SUGGESTIONS)]; [(int) (AVERAGE_HIGHLIGHTS_PER_SUGGESTION * MAX_NUMBER_SUGGESTIONS)];
private SuggestionInfo[] mSuggestionInfos;
private int mNumberOfSuggestions;
private boolean mCursorWasVisibleBeforeSuggestions; private boolean mCursorWasVisibleBeforeSuggestions;
private SuggestionAdapter mSuggestionsAdapter;
private class CustomPopupWindow extends PopupWindow { private class CustomPopupWindow extends PopupWindow {
public CustomPopupWindow(Context context, int defStyle) { public CustomPopupWindow(Context context, int defStyle) {
@@ -9494,29 +9466,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override @Override
protected void initContentView() { protected void initContentView() {
mContentView.setOrientation(LinearLayout.VERTICAL); ListView listView = new ListView(TextView.this.getContext());
mSuggestionsAdapter = new SuggestionAdapter();
LayoutInflater inflater = (LayoutInflater) TextView.this.mContext. listView.setAdapter(mSuggestionsAdapter);
getSystemService(Context.LAYOUT_INFLATER_SERVICE); listView.setOnItemClickListener(this);
mContentView = listView;
if (inflater == null) {
throw new IllegalArgumentException(
"Unable to create inflater for TextEdit suggestions");
}
// Inflate the suggestion items once and for all. // Inflate the suggestion items once and for all.
mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS];
for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) { for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) {
View childView = inflater.inflate(mTextEditSuggestionItemLayout, mSuggestionInfos[i] = new SuggestionInfo();
mContentView, false);
if (! (childView instanceof TextView)) {
throw new IllegalArgumentException(
"Inflated TextEdit suggestion item is not a TextView: " + childView);
}
childView.setTag(new SuggestionInfo());
mContentView.addView(childView);
childView.setOnClickListener(this);
} }
} }
@@ -9525,6 +9484,40 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
int spanStart, spanEnd; // range in TextView where text should be inserted int spanStart, spanEnd; // range in TextView where text should be inserted
SuggestionSpan suggestionSpan; // the SuggestionSpan that this TextView represents SuggestionSpan suggestionSpan; // the SuggestionSpan that this TextView represents
int suggestionIndex; // the index of the suggestion inside suggestionSpan int suggestionIndex; // the index of the suggestion inside suggestionSpan
SpannableStringBuilder text = new SpannableStringBuilder();
}
private class SuggestionAdapter extends BaseAdapter {
private LayoutInflater mInflater = (LayoutInflater) TextView.this.mContext.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@Override
public int getCount() {
return mNumberOfSuggestions;
}
@Override
public Object getItem(int position) {
return mSuggestionInfos[position];
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textView = (TextView) convertView;
if (textView == null) {
textView = (TextView) mInflater.inflate(mTextEditSuggestionItemLayout, parent,
false);
}
textView.setText(mSuggestionInfos[position].text);
return textView;
}
} }
/** /**
@@ -9568,6 +9561,36 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
} }
} }
@Override
protected void measureContent() {
final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
final int horizontalMeasure = View.MeasureSpec.makeMeasureSpec(
displayMetrics.widthPixels, View.MeasureSpec.AT_MOST);
final int verticalMeasure = View.MeasureSpec.makeMeasureSpec(
displayMetrics.heightPixels, View.MeasureSpec.AT_MOST);
int width = 0;
View view = null;
for (int i = 0; i < mNumberOfSuggestions; i++) {
view = mSuggestionsAdapter.getView(i, view, mContentView);
view.measure(horizontalMeasure, verticalMeasure);
width = Math.max(width, view.getMeasuredWidth());
}
// Enforce the width based on actual text widths
mContentView.measure(
View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
verticalMeasure);
Drawable popupBackground = mPopupWindow.getBackground();
if (popupBackground != null) {
if (mTempRect == null) mTempRect = new Rect();
popupBackground.getPadding(mTempRect);
width += mTempRect.left + mTempRect.right;
}
mPopupWindow.setWidth(width);
}
@Override @Override
protected int getTextOffset() { protected int getTextOffset() {
return getSelectionStart(); return getSelectionStart();
@@ -9596,7 +9619,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final int nbSpans = suggestionSpans.length; final int nbSpans = suggestionSpans.length;
int totalNbSuggestions = 0; mNumberOfSuggestions = 0;
int spanUnionStart = mText.length(); int spanUnionStart = mText.length();
int spanUnionEnd = 0; int spanUnionEnd = 0;
@@ -9610,17 +9633,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
String[] suggestions = suggestionSpan.getSuggestions(); String[] suggestions = suggestionSpan.getSuggestions();
int nbSuggestions = suggestions.length; int nbSuggestions = suggestions.length;
for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) { for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) {
TextView textView = (TextView) mContentView.getChildAt( SuggestionInfo suggestionInfo = mSuggestionInfos[mNumberOfSuggestions];
totalNbSuggestions);
textView.setText(suggestions[suggestionIndex]);
SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
suggestionInfo.spanStart = spanStart; suggestionInfo.spanStart = spanStart;
suggestionInfo.spanEnd = spanEnd; suggestionInfo.spanEnd = spanEnd;
suggestionInfo.suggestionSpan = suggestionSpan; suggestionInfo.suggestionSpan = suggestionSpan;
suggestionInfo.suggestionIndex = suggestionIndex; suggestionInfo.suggestionIndex = suggestionIndex;
suggestionInfo.text = new SpannableStringBuilder(suggestions[suggestionIndex]);
totalNbSuggestions++; mNumberOfSuggestions++;
if (totalNbSuggestions == MAX_NUMBER_SUGGESTIONS) { if (mNumberOfSuggestions == MAX_NUMBER_SUGGESTIONS) {
// Also end outer for loop // Also end outer for loop
spanIndex = nbSpans; spanIndex = nbSpans;
break; break;
@@ -9628,31 +9649,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
} }
} }
if (totalNbSuggestions == 0) return false; if (mNumberOfSuggestions == 0) return false;
if (mSuggestionRangeSpan == null) { if (mSuggestionRangeSpan == null) mSuggestionRangeSpan =
mSuggestionRangeSpan = new SuggestionRangeSpan(getContext()); new SuggestionRangeSpan(mHighlightColor);
}
((Editable) mText).setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
if (mSuggestionRangeSpan == null) mSuggestionRangeSpan =
new SuggestionRangeSpan(getContext());
((Editable) mText).setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd, ((Editable) mText).setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
for (int i = 0; i < totalNbSuggestions; i++) { for (int i = 0; i < mNumberOfSuggestions; i++) {
final TextView textView = (TextView) mContentView.getChildAt(i); highlightTextDifferences(mSuggestionInfos[i], spanUnionStart, spanUnionEnd);
highlightTextDifferences(textView, spanUnionStart, spanUnionEnd);
}
for (int i = 0; i < totalNbSuggestions; i++) {
mContentView.getChildAt(i).setVisibility(VISIBLE);
}
for (int i = totalNbSuggestions; i < MAX_NUMBER_SUGGESTIONS; i++) {
mContentView.getChildAt(i).setVisibility(GONE);
} }
mSuggestionsAdapter.notifyDataSetChanged();
return true; return true;
} }
@@ -9719,13 +9727,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return highlightSpan; return highlightSpan;
} }
private void highlightTextDifferences(TextView textView, int unionStart, int unionEnd) { private void highlightTextDifferences(SuggestionInfo suggestionInfo,
SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag(); int unionStart, int unionEnd) {
final int spanStart = suggestionInfo.spanStart; final int spanStart = suggestionInfo.spanStart;
final int spanEnd = suggestionInfo.spanEnd; final int spanEnd = suggestionInfo.spanEnd;
// Remove all text formating by converting to Strings // Remove all text formating by converting to Strings
final String text = textView.getText().toString(); final String text = suggestionInfo.text.toString();
final String sourceText = mText.subSequence(spanStart, spanEnd).toString(); final String sourceText = mText.subSequence(spanStart, spanEnd).toString();
long[] sourceWordLimits = getWordLimits(sourceText); long[] sourceWordLimits = getWordLimits(sourceText);
@@ -9800,7 +9808,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (previousCommonWordIndex < words.length - 1) { if (previousCommonWordIndex < words.length - 1) {
int firstDifferentPosition = previousCommonWordIndex < 0 ? 0 : int firstDifferentPosition = previousCommonWordIndex < 0 ? 0 :
extractRangeEndFromLong(wordLimits[previousCommonWordIndex]); extractRangeEndFromLong(wordLimits[previousCommonWordIndex]);
int lastDifferentPosition = textView.length(); int lastDifferentPosition = text.length();
ssb.setSpan(highlightSpan(nbHighlightSpans++), ssb.setSpan(highlightSpan(nbHighlightSpans++),
shift + firstDifferentPosition, shift + lastDifferentPosition, shift + firstDifferentPosition, shift + lastDifferentPosition,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -9811,25 +9819,24 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
int lastCommonTextWordEnd = previousCommonWordIndex < 0 ? 0 : int lastCommonTextWordEnd = previousCommonWordIndex < 0 ? 0 :
extractRangeEndFromLong(wordLimits[previousCommonWordIndex]); extractRangeEndFromLong(wordLimits[previousCommonWordIndex]);
String textSpaces = text.substring(lastCommonTextWordEnd, textView.length()); String textSpaces = text.substring(lastCommonTextWordEnd, text.length());
if (!sourceSpaces.equals(textSpaces) && textSpaces.length() > 0) { if (!sourceSpaces.equals(textSpaces) && textSpaces.length() > 0) {
ssb.setSpan(highlightSpan(nbHighlightSpans++), ssb.setSpan(highlightSpan(nbHighlightSpans++),
shift + lastCommonTextWordEnd, shift + textView.length(), shift + lastCommonTextWordEnd, shift + text.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} }
} }
// Final part, text after the current suggestion range. // Final part, text after the current suggestion range.
ssb.append(mText.subSequence(spanEnd, unionEnd).toString()); ssb.append(mText.subSequence(spanEnd, unionEnd).toString());
textView.setText(ssb);
} }
@Override @Override
public void onClick(View view) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (view instanceof TextView) { if (view instanceof TextView) {
TextView textView = (TextView) view; TextView textView = (TextView) view;
SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag(); SuggestionInfo suggestionInfo = mSuggestionInfos[position];
final int spanStart = suggestionInfo.spanStart; final int spanStart = suggestionInfo.spanStart;
final int spanEnd = suggestionInfo.spanEnd; final int spanEnd = suggestionInfo.spanEnd;
if (spanStart != NO_SUGGESTIONS) { if (spanStart != NO_SUGGESTIONS) {
@@ -10190,9 +10197,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override @Override
protected void initContentView() { protected void initContentView() {
mContentView.setOrientation(LinearLayout.HORIZONTAL); LinearLayout linearLayout = new LinearLayout(TextView.this.getContext());
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
mContentView = linearLayout;
mContentView.setBackgroundResource( mContentView.setBackgroundResource(
com.android.internal.R.drawable.text_edit_side_paste_window); com.android.internal.R.drawable.text_edit_paste_window);
LayoutInflater inflater = (LayoutInflater)TextView.this.mContext. LayoutInflater inflater = (LayoutInflater)TextView.this.mContext.
getSystemService(Context.LAYOUT_INFLATER_SERVICE); getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -11282,7 +11291,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private final TextPaint mTextPaint; private final TextPaint mTextPaint;
private boolean mUserSetTextScaleX; private boolean mUserSetTextScaleX;
private final Paint mHighlightPaint; private final Paint mHighlightPaint;
private int mHighlightColor = 0xCC475925; private int mHighlightColor = 0x4C33B5E5;
/** /**
* This is temporarily visible to fix bug 3085564 in webView. Do not rely on * This is temporarily visible to fix bug 3085564 in webView. Do not rely on
* this field being protected. Will be restored as private when lineHeight * this field being protected. Will be restored as private when lineHeight

Binary file not shown.

Before

Width:  |  Height:  |  Size: 865 B

After

Width:  |  Height:  |  Size: 917 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 929 B

After

Width:  |  Height:  |  Size: 917 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 585 B

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 605 B

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -25,4 +25,5 @@
android:textAppearance="?android:attr/textAppearanceSmallInverse" android:textAppearance="?android:attr/textAppearanceSmallInverse"
android:textColor="@android:color/black" android:textColor="@android:color/black"
android:textAllCaps="true" android:textAllCaps="true"
android:textStyle="bold"
/> />

View File

@@ -158,10 +158,6 @@
<!-- The underline color and thickness for misspelled suggestion --> <!-- The underline color and thickness for misspelled suggestion -->
<attr name="textAppearanceMisspelledSuggestion" format="reference" /> <attr name="textAppearanceMisspelledSuggestion" format="reference" />
<!-- The text color and the background for suggestion range span. This span identifies the
portion of text the suggestions refer to). -->
<attr name="textAppearanceSuggestionRange" format="reference" />
<!-- The underline color --> <!-- The underline color -->
<attr name="textUnderlineColor" format="reference|color" /> <attr name="textUnderlineColor" format="reference|color" />
<!-- The underline thickness --> <!-- The underline thickness -->
@@ -3154,10 +3150,6 @@
<attr name="textUnderlineColor" /> <attr name="textUnderlineColor" />
<attr name="textUnderlineThickness" /> <attr name="textUnderlineThickness" />
</declare-styleable> </declare-styleable>
<declare-styleable name="SuggestionRangeSpan">
<attr name="textColor" />
<attr name="colorBackground" />
</declare-styleable>
<!-- An <code>input-extras</code> is a container for extra data to supply to <!-- An <code>input-extras</code> is a container for extra data to supply to
an input method. Contains an input method. Contains
one more more {@link #Extra <extra>} tags. --> one more more {@link #Extra <extra>} tags. -->

View File

@@ -54,8 +54,6 @@
<color name="dim_foreground_light_inverse">#bebebe</color> <color name="dim_foreground_light_inverse">#bebebe</color>
<color name="dim_foreground_light_inverse_disabled">#80bebebe</color> <color name="dim_foreground_light_inverse_disabled">#80bebebe</color>
<color name="hint_foreground_light">#808080</color> <color name="hint_foreground_light">#808080</color>
<color name="highlight_background">#cc475925</color>
<color name="highlight_background_inverse">#ccd2e461</color>
<color name="highlighted_text_dark">#9983CC39</color> <color name="highlighted_text_dark">#9983CC39</color>
<color name="highlighted_text_light">#9983CC39</color> <color name="highlighted_text_light">#9983CC39</color>
<color name="link_text_dark">#5c5cff</color> <color name="link_text_dark">#5c5cff</color>
@@ -135,10 +133,8 @@
<color name="dim_foreground_inverse_holo_light">#bebebe</color> <color name="dim_foreground_inverse_holo_light">#bebebe</color>
<color name="dim_foreground_inverse_disabled_holo_light">#80bebebe</color> <color name="dim_foreground_inverse_disabled_holo_light">#80bebebe</color>
<color name="hint_foreground_holo_light">#808080</color> <color name="hint_foreground_holo_light">#808080</color>
<color name="highlight_background_holo">#cc475925</color> <color name="highlighted_text_holo_dark">#4c33b5e5</color>
<color name="highlight_background_inverse_holo">#ccd2e461</color> <color name="highlighted_text_holo_light">#4c33b5e5</color>
<color name="highlighted_text_holo_dark">#9983CC39</color>
<color name="highlighted_text_holo_light">#9983CC39</color>
<color name="link_text_holo_dark">#5c5cff</color> <color name="link_text_holo_dark">#5c5cff</color>
<color name="link_text_holo_light">#0000ee</color> <color name="link_text_holo_light">#0000ee</color>

View File

@@ -255,11 +255,6 @@ please see styles_device_defaults.xml.
<item name="android:textUnderlineColor">@color/holo_red_light</item> <item name="android:textUnderlineColor">@color/holo_red_light</item>
</style> </style>
<style name="TextAppearance.SuggestionRange">
<item name="android:textColor">@color/white</item>
<item name="android:colorBackground">@color/holo_blue_dark</item>
</style>
<!-- Widget Styles --> <!-- Widget Styles -->
<style name="Widget"> <style name="Widget">

View File

@@ -91,7 +91,6 @@ please see themes_device_defaults.xml.
<item name="textAppearanceEasyCorrectSuggestion">@android:style/TextAppearance.EasyCorrectSuggestion</item> <item name="textAppearanceEasyCorrectSuggestion">@android:style/TextAppearance.EasyCorrectSuggestion</item>
<item name="textAppearanceMisspelledSuggestion">@android:style/TextAppearance.MisspelledSuggestion</item> <item name="textAppearanceMisspelledSuggestion">@android:style/TextAppearance.MisspelledSuggestion</item>
<item name="textAppearanceSuggestionRange">@android:style/TextAppearance.SuggestionRange</item>
<item name="textAppearanceButton">@android:style/TextAppearance.Widget.Button</item> <item name="textAppearanceButton">@android:style/TextAppearance.Widget.Button</item>