Show auto correction feedback

Bug: 3230726
Change-Id: Iecf6fc837952c4721f6b726edcf16179254179ca
main
Tadashi G. Takaoka 2010-12-09 16:36:45 +09:00
parent 8ec36be4f5
commit 55b9d333c5
2 changed files with 106 additions and 26 deletions

View File

@ -24,7 +24,9 @@ import android.os.Message;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.style.BackgroundColorSpan;
import android.text.style.CharacterStyle; import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.text.style.UnderlineSpan; import android.text.style.UnderlineSpan;
import android.util.AttributeSet; import android.util.AttributeSet;
@ -57,22 +59,76 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
private final int mColorOther; private final int mColorOther;
private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD); private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan(); private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
private final CharacterStyle mInvertedForegroundColorSpan;
private final CharacterStyle mInvertedBackgroundColorSpan;
private boolean mShowingCompletions; private boolean mShowingCompletions;
private boolean mShowingAutoCorrectionInverted;
private boolean mShowingAddToDictionary; private boolean mShowingAddToDictionary;
private static final long DELAY_HIDE_PREVIEW = 1000; private final UiHandler mHandler = new UiHandler();
private static class UpdateSuggestionsArgs {
public final List<CharSequence> mSuggestions;
public final boolean mCompletions;
public final boolean mTypedWordValid;
public final boolean mHaveMinimalSuggestion;
public UpdateSuggestionsArgs(List<CharSequence> suggestions, boolean completions,
boolean typedWordValid, boolean haveMinimalSuggestion) {
mSuggestions = suggestions;
mCompletions = completions;
mTypedWordValid = typedWordValid;
mHaveMinimalSuggestion = haveMinimalSuggestion;
}
}
private class UiHandler extends Handler {
private static final int MSG_HIDE_PREVIEW = 0; private static final int MSG_HIDE_PREVIEW = 0;
private final Handler mHandler = new Handler() { private static final int MSG_UPDATE_SUGGESTION = 1;
private static final long DELAY_HIDE_PREVIEW = 1000;
private static final long DELAY_UPDATE_SUGGESTION = 300;
@Override @Override
public void dispatchMessage(Message msg) { public void dispatchMessage(Message msg) {
switch (msg.what) { switch (msg.what) {
case MSG_HIDE_PREVIEW: case MSG_HIDE_PREVIEW:
hidePreview(); hidePreview();
break; break;
case MSG_UPDATE_SUGGESTION:
UpdateSuggestionsArgs args = (UpdateSuggestionsArgs)msg.obj;
updateSuggestions(args.mSuggestions, args.mCompletions, args.mTypedWordValid,
args.mHaveMinimalSuggestion);
break;
} }
} }
public void postHidePreview() {
cancelHidePreview();
sendMessageDelayed(obtainMessage(MSG_HIDE_PREVIEW), DELAY_HIDE_PREVIEW);
}
public void cancelHidePreview() {
removeMessages(MSG_HIDE_PREVIEW);
}
public void postUpdateSuggestions(List<CharSequence> suggestions, boolean completions,
boolean typedWordValid, boolean haveMinimalSuggestion) {
cancelUpdateSuggestions();
sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTION, new UpdateSuggestionsArgs(
suggestions, completions, typedWordValid, haveMinimalSuggestion)),
DELAY_UPDATE_SUGGESTION);
}
public void cancelUpdateSuggestions() {
removeMessages(MSG_UPDATE_SUGGESTION);
}
public void cancelAllMessages() {
cancelHidePreview();
cancelUpdateSuggestions();
}
}; };
/** /**
@ -96,6 +152,8 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
mColorNormal = res.getColor(R.color.candidate_normal); mColorNormal = res.getColor(R.color.candidate_normal);
mColorRecommended = res.getColor(R.color.candidate_recommended); mColorRecommended = res.getColor(R.color.candidate_recommended);
mColorOther = res.getColor(R.color.candidate_other); mColorOther = res.getColor(R.color.candidate_other);
mInvertedForegroundColorSpan = new ForegroundColorSpan(mColorNormal ^ 0x00ffffff);
mInvertedBackgroundColorSpan = new BackgroundColorSpan(mColorNormal);
for (int i = 0; i < MAX_SUGGESTIONS; i++) { for (int i = 0; i < MAX_SUGGESTIONS; i++) {
View v = inflater.inflate(R.layout.candidate, null); View v = inflater.inflate(R.layout.candidate, null);
@ -123,6 +181,16 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
public void setSuggestions(List<CharSequence> suggestions, boolean completions, public void setSuggestions(List<CharSequence> suggestions, boolean completions,
boolean typedWordValid, boolean haveMinimalSuggestion) { boolean typedWordValid, boolean haveMinimalSuggestion) {
if (mShowingAutoCorrectionInverted) {
mHandler.postUpdateSuggestions(suggestions, completions, typedWordValid,
haveMinimalSuggestion);
} else {
updateSuggestions(suggestions, completions, typedWordValid, haveMinimalSuggestion);
}
}
private void updateSuggestions(List<CharSequence> suggestions, boolean completions,
boolean typedWordValid, boolean haveMinimalSuggestion) {
clear(); clear();
if (suggestions != null) { if (suggestions != null) {
int insertCount = Math.min(suggestions.size(), MAX_SUGGESTIONS); int insertCount = Math.min(suggestions.size(), MAX_SUGGESTIONS);
@ -141,8 +209,8 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
if (suggestion == null) continue; if (suggestion == null) continue;
final int wordLength = suggestion.length(); final int wordLength = suggestion.length();
View v = mWords.get(i); final View v = mWords.get(i);
TextView tv = (TextView)v.findViewById(R.id.candidate_word); final TextView tv = (TextView)v.findViewById(R.id.candidate_word);
tv.setTextColor(mColorNormal); tv.setTextColor(mColorNormal);
if (haveMinimalSuggestion if (haveMinimalSuggestion
&& ((i == 1 && !typedWordValid) || (i == 0 && typedWordValid))) { && ((i == 1 && !typedWordValid) || (i == 0 && typedWordValid))) {
@ -179,6 +247,22 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
requestLayout(); requestLayout();
} }
public void onAutoCorrectionInverted(CharSequence autoCorrectedWord) {
// Displaying auto corrected word as inverted is enabled only when highlighting candidate
// with color is disabled.
if (mConfigCandidateHighlightFontColorEnabled)
return;
final TextView tv = (TextView)mWords.get(1).findViewById(R.id.candidate_word);
final Spannable word = new SpannableString(autoCorrectedWord);
final int wordLength = word.length();
word.setSpan(mInvertedBackgroundColorSpan, 0, wordLength,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
word.setSpan(mInvertedForegroundColorSpan, 0, wordLength,
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
tv.setText(word);
mShowingAutoCorrectionInverted = true;
}
public boolean isShowingAddToDictionaryHint() { public boolean isShowingAddToDictionaryHint() {
return mShowingAddToDictionary; return mShowingAddToDictionary;
} }
@ -209,6 +293,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
// in LatinIME.pickSuggestionManually(). // in LatinIME.pickSuggestionManually().
mSuggestions.clear(); mSuggestions.clear();
mShowingAddToDictionary = false; mShowingAddToDictionary = false;
mShowingAutoCorrectionInverted = false;
removeAllViews(); removeAllViews();
} }
@ -236,8 +321,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
previewPopup.showAtLocation(this, Gravity.NO_GRAVITY, posX, posY); previewPopup.showAtLocation(this, Gravity.NO_GRAVITY, posX, posY);
} }
previewText.setVisibility(VISIBLE); previewText.setVisibility(VISIBLE);
mHandler.sendMessageDelayed( mHandler.postHidePreview();
mHandler.obtainMessage(MSG_HIDE_PREVIEW), DELAY_HIDE_PREVIEW);
} }
private void addToDictionary(CharSequence word) { private void addToDictionary(CharSequence word) {
@ -273,7 +357,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
@Override @Override
public void onDetachedFromWindow() { public void onDetachedFromWindow() {
super.onDetachedFromWindow(); super.onDetachedFromWindow();
mHandler.removeMessages(MSG_HIDE_PREVIEW); mHandler.cancelAllMessages();
hidePreview(); hidePreview();
} }
} }

View File

@ -81,10 +81,8 @@ import java.util.Locale;
/** /**
* Input method implementation for Qwerty'ish keyboard. * Input method implementation for Qwerty'ish keyboard.
*/ */
public class LatinIME extends InputMethodService public class LatinIME extends InputMethodService implements KeyboardActionListener,
implements KeyboardActionListener, SharedPreferences.OnSharedPreferenceChangeListener, Tutorial.TutorialListener {
SharedPreferences.OnSharedPreferenceChangeListener,
Tutorial.TutorialListener {
private static final String TAG = "LatinIME"; private static final String TAG = "LatinIME";
private static final boolean PERF_DEBUG = false; private static final boolean PERF_DEBUG = false;
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
@ -1167,9 +1165,7 @@ public class LatinIME extends InputMethodService
if (ic == null) return; if (ic == null) return;
abortCorrection(false); abortCorrection(false);
ic.beginBatchEdit(); ic.beginBatchEdit();
if (mPredicting) {
commitTyped(ic); commitTyped(ic);
}
maybeRemovePreviousPeriod(text); maybeRemovePreviousPeriod(text);
ic.commitText(text, 1); ic.commitText(text, 1);
ic.endBatchEdit(); ic.endBatchEdit();
@ -1382,7 +1378,14 @@ public class LatinIME extends InputMethodService
doubleSpace(); doubleSpace();
} }
if (pickedDefault) { if (pickedDefault) {
TextEntryState.backToAcceptedDefault(mWord.getTypedWord()); CharSequence typedWord = mWord.getTypedWord();
TextEntryState.backToAcceptedDefault(typedWord);
if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) {
// TODO: Will call InputConnection.commitCorrection() here.
if (mCandidateView != null)
mCandidateView.onAutoCorrectionInverted(mBestWord);
}
setPunctuationSuggestions();
} }
mKeyboardSwitcher.updateShiftState(); mKeyboardSwitcher.updateShiftState();
if (ic != null) { if (ic != null) {
@ -1564,7 +1567,7 @@ public class LatinIME extends InputMethodService
if (mBestWord != null && mBestWord.length() > 0) { if (mBestWord != null && mBestWord.length() > 0) {
TextEntryState.acceptedDefault(mWord.getTypedWord(), mBestWord); TextEntryState.acceptedDefault(mWord.getTypedWord(), mBestWord);
mJustAccepted = true; mJustAccepted = true;
pickSuggestion(mBestWord, false); pickSuggestion(mBestWord);
// Add the word to the auto dictionary if it's not a known word // Add the word to the auto dictionary if it's not a known word
addToDictionaries(mBestWord, AutoDictionary.FREQUENCY_FOR_TYPED); addToDictionaries(mBestWord, AutoDictionary.FREQUENCY_FOR_TYPED);
return true; return true;
@ -1615,7 +1618,7 @@ public class LatinIME extends InputMethodService
return; return;
} }
mJustAccepted = true; mJustAccepted = true;
pickSuggestion(suggestion, correcting); pickSuggestion(suggestion);
// Add the word to the auto dictionary if it's not a known word // Add the word to the auto dictionary if it's not a known word
if (index == 0) { if (index == 0) {
addToDictionaries(suggestion, AutoDictionary.FREQUENCY_FOR_PICKED); addToDictionaries(suggestion, AutoDictionary.FREQUENCY_FOR_PICKED);
@ -1660,10 +1663,8 @@ public class LatinIME extends InputMethodService
* retrieval. * retrieval.
* @param suggestion the suggestion picked by the user to be committed to * @param suggestion the suggestion picked by the user to be committed to
* the text field * the text field
* @param correcting whether this is due to a correction of an existing
* word.
*/ */
private void pickSuggestion(CharSequence suggestion, boolean correcting) { private void pickSuggestion(CharSequence suggestion) {
KeyboardSwitcher switcher = mKeyboardSwitcher; KeyboardSwitcher switcher = mKeyboardSwitcher;
if (!switcher.isKeyboardAvailable()) if (!switcher.isKeyboardAvailable())
return; return;
@ -1676,11 +1677,6 @@ public class LatinIME extends InputMethodService
mPredicting = false; mPredicting = false;
mCommittedLength = suggestion.length(); mCommittedLength = suggestion.length();
switcher.setPreferredLetters(null); switcher.setPreferredLetters(null);
// If we just corrected a word, then don't show punctuations
if (!correcting) {
setPunctuationSuggestions();
}
switcher.updateShiftState();
} }
/** /**