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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java

Issue 2885973002: Refactor autocomplete-specific logic into a separate class (Closed)
Patch Set: address tedchoc's comments Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.omnibox;
6
7 import android.content.Context;
8 import android.graphics.Rect;
9 import android.os.StrictMode;
10 import android.text.Editable;
11 import android.text.Selection;
12 import android.text.Spanned;
13 import android.text.TextUtils;
14 import android.util.AttributeSet;
15 import android.view.accessibility.AccessibilityEvent;
16 import android.view.accessibility.AccessibilityManager;
17 import android.view.accessibility.AccessibilityNodeInfo;
18 import android.view.inputmethod.BaseInputConnection;
19 import android.view.inputmethod.EditorInfo;
20 import android.view.inputmethod.InputConnection;
21 import android.view.inputmethod.InputConnectionWrapper;
22 import android.widget.EditText;
23
24 import org.chromium.base.Log;
25 import org.chromium.base.VisibleForTesting;
26 import org.chromium.chrome.browser.widget.VerticallyFixedEditText;
27
28 /**
29 * An {@link EditText} that shows autocomplete text at the end.
30 */
31 public class AutocompleteEditText extends VerticallyFixedEditText {
32 private static final String TAG = "cr_AutocompleteEdit";
33
34 private static final boolean DEBUG = false;
35
36 private final AutocompleteSpan mAutocompleteSpan;
37 private final AccessibilityManager mAccessibilityManager;
38
39 /**
40 * Whether default TextView scrolling should be disabled because autocomplet e has been added.
41 * This allows the user entered text to be shown instead of the end of the a utocomplete.
42 */
43 private boolean mDisableTextScrollingFromAutocomplete;
44
45 private boolean mInBatchEditMode;
46 private int mBeforeBatchEditAutocompleteIndex = -1;
47 private String mBeforeBatchEditFullText;
48 private boolean mSelectionChangedInBatchMode;
49 private boolean mTextDeletedInBatchMode;
50
51 // Set to true when the text is modified programmatically. Initially set to true until the old
52 // state has been loaded.
53 private boolean mIgnoreTextChangeFromAutocomplete = true;
54 private boolean mLastEditWasDelete;
55
56 public AutocompleteEditText(Context context, AttributeSet attrs) {
57 super(context, attrs);
58 mAutocompleteSpan = new AutocompleteSpan();
59 mAccessibilityManager =
60 (AccessibilityManager) context.getSystemService(Context.ACCESSIB ILITY_SERVICE);
61 }
62
63 /**
64 * Sets whether text changes should trigger autocomplete.
65 *
66 * @param ignoreAutocomplete Whether text changes should be ignored and no a uto complete
67 * triggered.
68 */
69 public void setIgnoreTextChangesForAutocomplete(boolean ignoreAutocomplete) {
70 if (DEBUG) Log.i(TAG, "setIgnoreTextChangesForAutocomplete: " + ignoreAu tocomplete);
71 mIgnoreTextChangeFromAutocomplete = ignoreAutocomplete;
72 }
73
74 /** @return Text that includes autocomplete. */
75 public String getTextWithAutocomplete() {
76 return getEditableText() != null ? getEditableText().toString() : "";
77 }
78
79 /**
80 * @return Whether the current cursor position is at the end of the user typ ed text (i.e.
81 * at the beginning of the inline autocomplete text if present other wise the very
82 * end of the current text).
83 */
84 private boolean isCursorAtEndOfTypedText() {
85 final int selectionStart = getSelectionStart();
86 final int selectionEnd = getSelectionEnd();
87
88 int expectedSelectionStart = getText().getSpanStart(mAutocompleteSpan);
89 int expectedSelectionEnd = getText().length();
90 if (expectedSelectionStart < 0) {
91 expectedSelectionStart = expectedSelectionEnd;
92 }
93
94 return selectionStart == expectedSelectionStart && selectionEnd == expec tedSelectionEnd;
95 }
96
97 /**
98 * @return Whether the URL is currently in batch edit mode triggered by an I ME. No external
99 * text changes should be triggered while this is true.
100 */
101 // isInBatchEditMode is a package protected method on TextView, so we intent ionally chose
102 // a different name.
103 private boolean isHandlingBatchInput() {
104 return mInBatchEditMode;
105 }
106
107 /**
108 * @return The user text without the autocomplete text.
109 */
110 public String getTextWithoutAutocomplete() {
111 int autoCompleteIndex = getText().getSpanStart(mAutocompleteSpan);
112 if (autoCompleteIndex < 0) {
113 return getTextWithAutocomplete();
114 } else {
115 return getTextWithAutocomplete().substring(0, autoCompleteIndex);
116 }
117 }
118
119 /** @return Whether any autocomplete information is specified on the current text. */
120 @VisibleForTesting
121 public boolean hasAutocomplete() {
122 return getText().getSpanStart(mAutocompleteSpan) >= 0
123 || mAutocompleteSpan.mAutocompleteText != null
124 || mAutocompleteSpan.mUserText != null;
125 }
126
127 /**
128 * Whether we want to be showing inline autocomplete results. We don't want to show them as the
129 * user deletes input. Also if there is a composition (e.g. while using the Japanese IME),
130 * we must not autocomplete or we'll destroy the composition.
131 * @return Whether we want to be showing inline autocomplete results.
132 */
133 public boolean shouldAutocomplete() {
134 if (mLastEditWasDelete) return false;
135 Editable text = getText();
136
137 return isCursorAtEndOfTypedText() && !isHandlingBatchInput()
138 && BaseInputConnection.getComposingSpanEnd(text)
139 == BaseInputConnection.getComposingSpanStart(text);
140 }
141
142 @Override
143 public void onBeginBatchEdit() {
144 if (DEBUG) Log.i(TAG, "onBeginBatchEdit");
145 mBeforeBatchEditAutocompleteIndex = getText().getSpanStart(mAutocomplete Span);
146 mBeforeBatchEditFullText = getText().toString();
147
148 super.onBeginBatchEdit();
149 mInBatchEditMode = true;
150 mTextDeletedInBatchMode = false;
151 }
152
153 @Override
154 public void onEndBatchEdit() {
155 if (DEBUG) Log.i(TAG, "onEndBatchEdit");
156 super.onEndBatchEdit();
157 mInBatchEditMode = false;
158 if (mSelectionChangedInBatchMode) {
159 validateSelection(getSelectionStart(), getSelectionEnd());
160 mSelectionChangedInBatchMode = false;
161 }
162
163 String newText = getText().toString();
164 if (!TextUtils.equals(mBeforeBatchEditFullText, newText)
165 || getText().getSpanStart(mAutocompleteSpan) != mBeforeBatchEdit AutocompleteIndex) {
166 // If the text being typed is a single character that matches the ne xt character in the
167 // previously visible autocomplete text, we reapply the autocomplete text to prevent
168 // a visual flickering when the autocomplete text is cleared and the n quickly reapplied
169 // when the next round of suggestions is received.
170 if (shouldAutocomplete() && mBeforeBatchEditAutocompleteIndex != -1
171 && mBeforeBatchEditFullText != null
172 && mBeforeBatchEditFullText.startsWith(newText) && !mTextDel etedInBatchMode
173 && newText.length() - mBeforeBatchEditAutocompleteIndex == 1 ) {
174 setAutocompleteText(newText, mBeforeBatchEditFullText.substring( newText.length()));
175 }
176 notifyAutocompleteTextStateChanged(mTextDeletedInBatchMode, true);
177 }
178
179 mTextDeletedInBatchMode = false;
180 mBeforeBatchEditAutocompleteIndex = -1;
181 mBeforeBatchEditFullText = null;
182 }
183
184 @Override
185 protected void onSelectionChanged(int selStart, int selEnd) {
186 if (DEBUG) Log.i(TAG, "onSelectionChanged -- selStart: %d, selEnd: %d", selStart, selEnd);
187 if (!mInBatchEditMode) {
188 int beforeTextLength = getText().length();
189 if (validateSelection(selStart, selEnd)) {
190 boolean textDeleted = getText().length() < beforeTextLength;
191 notifyAutocompleteTextStateChanged(textDeleted, false);
192 }
193 } else {
194 mSelectionChangedInBatchMode = true;
195 }
196 super.onSelectionChanged(selStart, selEnd);
197 }
198
199 /**
200 * Validates the selection and clears the autocomplete span if needed. The autocomplete text
201 * will be deleted if the selection occurs entirely before the autocomplete region.
202 *
203 * @param selStart The start of the selection.
204 * @param selEnd The end of the selection.
205 * @return Whether the autocomplete span was removed as a result of this val idation.
206 */
207 private boolean validateSelection(int selStart, int selEnd) {
208 int spanStart = getText().getSpanStart(mAutocompleteSpan);
209 int spanEnd = getText().getSpanEnd(mAutocompleteSpan);
210
211 if (DEBUG) {
212 Log.i(TAG, "validateSelection -- selStart: %d, selEnd: %d, spanStart : %d, spanEnd: %d",
213 selStart, selEnd, spanStart, spanEnd);
214 }
215
216 if (spanStart >= 0 && (spanStart != selStart || spanEnd != selEnd)) {
217 CharSequence previousAutocompleteText = mAutocompleteSpan.mAutocompl eteText;
218
219 // On selection changes, the autocomplete text has been accepted by the user or needs
220 // to be deleted below.
221 mAutocompleteSpan.clearSpan();
222
223 // The autocomplete text will be deleted any time the selection occu rs entirely before
224 // the start of the autocomplete text. This is required because cer tain keyboards will
225 // insert characters temporarily when starting a key entry gesture ( whether it be
226 // swyping a word or long pressing to get a special character). Whe n this temporary
227 // character appears, Chrome may decide to append some autocomplete, but the keyboard
228 // will then remove this temporary character only while leaving the autocomplete text
229 // alone. See crbug/273763 for more details.
230 if (selEnd <= spanStart
231 && TextUtils.equals(previousAutocompleteText,
232 getText().subSequence(spanStart, getText().length ()))) {
233 getText().delete(spanStart, getText().length());
234 }
235 return true;
236 }
237 return false;
238 }
239
240 @Override
241 protected void onFocusChanged(boolean focused, int direction, Rect previousl yFocusedRect) {
242 if (!focused) mAutocompleteSpan.clearSpan();
243 super.onFocusChanged(focused, direction, previouslyFocusedRect);
244 }
245
246 @Override
247 public boolean bringPointIntoView(int offset) {
248 if (mDisableTextScrollingFromAutocomplete) return false;
249 return super.bringPointIntoView(offset);
250 }
251
252 @Override
253 public boolean onPreDraw() {
254 boolean retVal = super.onPreDraw();
255 if (mDisableTextScrollingFromAutocomplete) {
256 // super.onPreDraw will put the selection at the end of the text sel ection, but
257 // in the case of autocomplete we want the last typed character to b e shown, which
258 // is the start of selection.
259 mDisableTextScrollingFromAutocomplete = false;
260 bringPointIntoView(getSelectionStart());
261 retVal = true;
262 }
263 return retVal;
264 }
265
266 /**
267 * Autocompletes the text on the url bar and selects the text that was not e ntered by the
268 * user. Using append() instead of setText() to preserve the soft-keyboard l ayout.
269 * @param userText user The text entered by the user.
270 * @param inlineAutocompleteText The suggested autocompletion for the user's text.
271 */
272 public void setAutocompleteText(CharSequence userText, CharSequence inlineAu tocompleteText) {
273 if (DEBUG) {
274 Log.i(TAG, "setAutocompleteText -- userText: %s, inlineAutocompleteT ext: %s", userText,
275 inlineAutocompleteText);
276 }
277 boolean emptyAutocomplete = TextUtils.isEmpty(inlineAutocompleteText);
278
279 if (!emptyAutocomplete) mDisableTextScrollingFromAutocomplete = true;
280
281 int autocompleteIndex = userText.length();
282
283 String previousText = getTextWithAutocomplete();
284 CharSequence newText = TextUtils.concat(userText, inlineAutocompleteText );
285
286 setIgnoreTextChangesForAutocomplete(true);
287
288 if (!TextUtils.equals(previousText, newText)) {
289 // The previous text may also have included autocomplete text, so we only
290 // append the new autocomplete text that has changed.
291 if (TextUtils.indexOf(newText, previousText) == 0) {
292 append(newText.subSequence(previousText.length(), newText.length ()));
293 } else {
294 replaceAllTextFromAutocomplete(newText.toString());
295 }
296 }
297
298 if (getSelectionStart() != autocompleteIndex || getSelectionEnd() != get Text().length()) {
299 setSelection(autocompleteIndex, getText().length());
300
301 if (inlineAutocompleteText.length() != 0) {
302 // Sending a TYPE_VIEW_TEXT_SELECTION_CHANGED accessibility even t causes the
303 // previous TYPE_VIEW_TEXT_CHANGED event to be swallowed. As a r esult the user
304 // hears the autocomplete text but *not* the text they typed. In stead we send a
305 // TYPE_ANNOUNCEMENT event, which doesn't swallow the text-chang ed event.
306 announceForAccessibility(inlineAutocompleteText);
307 }
308 }
309
310 if (emptyAutocomplete) {
311 mAutocompleteSpan.clearSpan();
312 } else {
313 mAutocompleteSpan.setSpan(userText, inlineAutocompleteText);
314 }
315
316 setIgnoreTextChangesForAutocomplete(false);
317 }
318
319 /**
320 * Returns the length of the autocomplete text currently displayed, zero if none is
321 * currently displayed.
322 */
323 public int getAutocompleteLength() {
324 int autoCompleteIndex = getText().getSpanStart(mAutocompleteSpan);
325 if (autoCompleteIndex < 0) return 0;
326 return getText().length() - autoCompleteIndex;
327 }
328
329 @Override
330 protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
331 if (DEBUG) {
332 Log.i(TAG, "onTextChanged -- text: %s, start: %d, lengthBefore: %d, lengthAfter: %d",
333 text, start, lengthBefore, lengthAfter);
334 }
335
336 super.onTextChanged(text, start, lengthBefore, lengthAfter);
337 boolean textDeleted = lengthAfter == 0;
338 if (!mInBatchEditMode) {
339 notifyAutocompleteTextStateChanged(textDeleted, true);
340 } else {
341 mTextDeletedInBatchMode = textDeleted;
342 }
343 }
344
345 @Override
346 public void setText(CharSequence text, BufferType type) {
347 if (DEBUG) Log.i(TAG, "setText -- text: %s", text);
348
349 mDisableTextScrollingFromAutocomplete = false;
350
351 // Avoid setting the same text to the URL bar as it will mess up the scr oll/cursor
352 // position.
353 // Setting the text is also quite expensive, so only do it when the text has changed
354 // (since we apply spans when the URL is not focused, we only optimize t his when the
355 // URL is being edited).
356 if (!TextUtils.equals(getEditableText(), text)) {
357 // Certain OEM implementations of setText trigger disk reads. crbug. com/633298
358 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads( );
359 try {
360 super.setText(text, type);
361 } finally {
362 StrictMode.setThreadPolicy(oldPolicy);
363 }
364 }
365
366 // Verify the autocomplete is still valid after the text change.
367 // Note: mAutocompleteSpan may be still null here if setText() is called in View
368 // constructor.
369 if (mAutocompleteSpan != null && mAutocompleteSpan.mUserText != null
370 && mAutocompleteSpan.mAutocompleteText != null) {
371 if (getText().getSpanStart(mAutocompleteSpan) < 0) {
372 mAutocompleteSpan.clearSpan();
373 } else {
374 clearAutocompleteSpanIfInvalid();
375 }
376 }
377 }
378
379 private void clearAutocompleteSpanIfInvalid() {
380 Editable editableText = getEditableText();
381 CharSequence previousUserText = mAutocompleteSpan.mUserText;
382 CharSequence previousAutocompleteText = mAutocompleteSpan.mAutocompleteT ext;
383 if (editableText.length()
384 != (previousUserText.length() + previousAutocompleteText.length( ))) {
385 mAutocompleteSpan.clearSpan();
386 } else if (TextUtils.indexOf(getText(), previousUserText) != 0
387 || TextUtils.indexOf(getText(), previousAutocompleteText, previo usUserText.length())
388 != 0) {
389 mAutocompleteSpan.clearSpan();
390 }
391 }
392
393 @Override
394 public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
395 if (mIgnoreTextChangeFromAutocomplete) {
396 if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_SELECT ION_CHANGED
397 || event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT _CHANGED) {
398 return;
399 }
400 }
401 super.sendAccessibilityEventUnchecked(event);
402 }
403
404 @Override
405 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
406 // Certain OEM implementations of onInitializeAccessibilityNodeInfo trig ger disk reads
407 // to access the clipboard. crbug.com/640993
408 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
409 try {
410 super.onInitializeAccessibilityNodeInfo(info);
411 } finally {
412 StrictMode.setThreadPolicy(oldPolicy);
413 }
414 }
415
416 @VisibleForTesting
417 public InputConnectionWrapper getInputConnection() {
418 return mInputConnection;
419 }
420
421 private InputConnectionWrapper mInputConnection = new InputConnectionWrapper (null, true) {
422 private final char[] mTempSelectionChar = new char[1];
423
424 @Override
425 public boolean commitText(CharSequence text, int newCursorPosition) {
426 if (DEBUG) Log.i(TAG, "commitText: [%s]", text);
427 Editable currentText = getText();
428 if (currentText == null) return super.commitText(text, newCursorPosi tion);
429
430 int selectionStart = Selection.getSelectionStart(currentText);
431 int selectionEnd = Selection.getSelectionEnd(currentText);
432 int autocompleteIndex = currentText.getSpanStart(mAutocompleteSpan);
433 // If the text being committed is a single character that matches th e next character
434 // in the selection (assumed to be the autocomplete text), we only m ove the text
435 // selection instead clearing the autocomplete text causing flickeri ng as the
436 // autocomplete text will appear once the next suggestions are recei ved.
437 //
438 // To be confident that the selection is an autocomplete, we ensure the selection
439 // is at least one character and the end of the selection is the end of the
440 // currently entered text.
441 if (newCursorPosition == 1 && selectionStart > 0 && selectionStart ! = selectionEnd
442 && selectionEnd >= currentText.length() && autocompleteIndex == selectionStart
443 && text.length() == 1) {
444 currentText.getChars(selectionStart, selectionStart + 1, mTempSe lectionChar, 0);
445 if (mTempSelectionChar[0] == text.charAt(0)) {
446 // Since the text isn't changing, TalkBack won't read out th e typed characters.
447 // To work around this, explicitly send an accessibility eve nt. crbug.com/416595
448 if (mAccessibilityManager != null && mAccessibilityManager.i sEnabled()) {
449 AccessibilityEvent event = AccessibilityEvent.obtain(
450 AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
451 event.setFromIndex(selectionStart);
452 event.setRemovedCount(0);
453 event.setAddedCount(1);
454 event.setBeforeText(currentText.toString().substring(0, selectionStart));
455 sendAccessibilityEventUnchecked(event);
456 }
457
458 setAutocompleteText(currentText.subSequence(0, selectionStar t + 1),
459 currentText.subSequence(selectionStart + 1, selectio nEnd));
460 if (!mInBatchEditMode) {
461 notifyAutocompleteTextStateChanged(false, false);
462 }
463 return true;
464 }
465 }
466
467 boolean retVal = super.commitText(text, newCursorPosition);
468
469 // Ensure the autocomplete span is removed if it is no longer valid after committing the
470 // text.
471 if (getText().getSpanStart(mAutocompleteSpan) >= 0) clearAutocomplet eSpanIfInvalid();
472
473 return retVal;
474 }
475
476 @Override
477 public boolean setComposingText(CharSequence text, int newCursorPosition ) {
478 if (DEBUG) Log.i(TAG, "setComposingText: [%s]", text);
479 Editable currentText = getText();
480 int autoCompleteSpanStart = currentText.getSpanStart(mAutocompleteSp an);
481 if (autoCompleteSpanStart >= 0) {
482 int composingEnd = BaseInputConnection.getComposingSpanEnd(curre ntText);
483
484 // On certain device/keyboard combinations, the composing region s are specified
485 // with a noticeable delay after the initial character is typed, and in certain
486 // circumstances it does not check that the current state of the text matches the
487 // expectations of it's composing region.
488 // For example, you can be typing:
489 // chrome://f
490 // Chrome will autocomplete to:
491 // chrome://f[lags]
492 // And after the autocomplete has been set, the keyboard will se t the composing
493 // region to the last character and it assumes it is 'f' as it w as the last
494 // character the keyboard sent. If we commit this composition, the text will
495 // look like:
496 // chrome://flag[f]
497 // And if we use the autocomplete clearing logic below, it will look like:
498 // chrome://f[f]
499 // To work around this, we see if the composition matches all th e characters prior
500 // to the autocomplete and just readjust the composing region to be that subset.
501 //
502 // See crbug.com/366732
503 if (composingEnd == currentText.length() && autoCompleteSpanStar t >= text.length()
504 && TextUtils.equals(
505 currentText.subSequence(autoCompleteSpanStart - text.length(),
506 autoCompleteSpanStart),
507 text)) {
508 setComposingRegion(
509 autoCompleteSpanStart - text.length(), autoCompleteS panStart);
510 }
511
512 // Once composing text is being modified, the autocomplete text has been accepted
513 // or has to be deleted.
514 mAutocompleteSpan.clearSpan();
515 Selection.setSelection(currentText, autoCompleteSpanStart);
516 currentText.delete(autoCompleteSpanStart, currentText.length());
517 }
518 return super.setComposingText(text, newCursorPosition);
519 }
520 };
521
522 @Override
523 public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
524 if (DEBUG) Log.i(TAG, "onCreateInputConnection");
525 return createInputConnection(super.onCreateInputConnection(outAttrs));
526 }
527
528 @VisibleForTesting
529 public InputConnection createInputConnection(InputConnection target) {
530 mInputConnection.setTarget(target);
531 return mInputConnection;
532 }
533
534 private void notifyAutocompleteTextStateChanged(boolean textDeleted, boolean updateDisplay) {
535 if (DEBUG) {
536 Log.i(TAG, "notifyAutocompleteTextStateChanged: DEL[%b] DIS[%b] IGN[ %b]", textDeleted,
537 updateDisplay, mIgnoreTextChangeFromAutocomplete);
538 }
539 if (mIgnoreTextChangeFromAutocomplete) return;
540 if (!hasFocus()) return;
541 mLastEditWasDelete = textDeleted;
542 onAutocompleteTextStateChanged(textDeleted, updateDisplay);
543 }
544
545 /**
546 * This is called when autocomplete replaces the whole text.
547 *
548 * @param text The text.
549 */
550 protected void replaceAllTextFromAutocomplete(String text) {
551 setText(text);
552 }
553
554 /**
555 * This is called when autocomplete text state changes.
556 * @param textDeleted True if text is just deleted.
557 * @param updateDisplay True if string is changed.
558 */
559 public void onAutocompleteTextStateChanged(boolean textDeleted, boolean upda teDisplay) {}
560
561 /**
562 * Simple span used for tracking the current autocomplete state.
563 */
564 private class AutocompleteSpan {
565 private CharSequence mUserText;
566 private CharSequence mAutocompleteText;
567
568 /**
569 * Adds the span to the current text.
570 * @param userText The user entered text.
571 * @param autocompleteText The autocomplete text being appended.
572 */
573 public void setSpan(CharSequence userText, CharSequence autocompleteText ) {
574 Editable text = getText();
575 text.removeSpan(this);
576 mAutocompleteText = autocompleteText;
577 mUserText = userText;
578 text.setSpan(this, userText.length(), text.length(), Spanned.SPAN_EX CLUSIVE_EXCLUSIVE);
579 }
580
581 /** Removes this span from the current text and clears the internal stat e. */
582 public void clearSpan() {
583 getText().removeSpan(this);
584 mAutocompleteText = null;
585 mUserText = null;
586 }
587 }
588 }
OLDNEW
« no previous file with comments | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698