Show word alternatives for spoken input
With this change, we show alternatives for a word that has been spoken.The user triggers the display of alternatives by tapping on the word. The alternatives are currently generated by a client-side algorithm, but will be improved when we move to a server-side generation of the alternatives Change-Id: I454ee28fef9bf97a1b026ce8c605ca4badb39e79
This commit is contained in:
parent
c9e24b80ab
commit
57691a3574
2 changed files with 57 additions and 30 deletions
|
@ -508,7 +508,6 @@ public class LatinIME extends InputMethodService
|
||||||
mShowingVoiceSuggestions = false;
|
mShowingVoiceSuggestions = false;
|
||||||
mImmediatelyAfterVoiceSuggestions = false;
|
mImmediatelyAfterVoiceSuggestions = false;
|
||||||
mVoiceInputHighlighted = false;
|
mVoiceInputHighlighted = false;
|
||||||
mWordToSuggestions.clear();
|
|
||||||
mInputTypeNoAutoCorrect = false;
|
mInputTypeNoAutoCorrect = false;
|
||||||
mPredictionOn = false;
|
mPredictionOn = false;
|
||||||
mCompletionOn = false;
|
mCompletionOn = false;
|
||||||
|
@ -702,29 +701,6 @@ public class LatinIME extends InputMethodService
|
||||||
postUpdateOldSuggestions();
|
postUpdateOldSuggestions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VOICE_INSTALLED) {
|
|
||||||
if (mShowingVoiceSuggestions) {
|
|
||||||
if (mImmediatelyAfterVoiceSuggestions) {
|
|
||||||
mImmediatelyAfterVoiceSuggestions = false;
|
|
||||||
} else {
|
|
||||||
updateSuggestions();
|
|
||||||
mShowingVoiceSuggestions = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (VoiceInput.ENABLE_WORD_CORRECTIONS) {
|
|
||||||
// If we have alternatives for the current word, then show them.
|
|
||||||
String word = EditingUtil.getWordAtCursor(
|
|
||||||
getCurrentInputConnection(), getWordSeparators());
|
|
||||||
if (word != null && mWordToSuggestions.containsKey(word.trim())) {
|
|
||||||
mSuggestionShouldReplaceCurrentWord = true;
|
|
||||||
final List<CharSequence> suggestions = mWordToSuggestions.get(word.trim());
|
|
||||||
|
|
||||||
setSuggestions(suggestions, false, true, true);
|
|
||||||
setCandidatesViewShown(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -745,6 +721,7 @@ public class LatinIME extends InputMethodService
|
||||||
mVoiceInput.cancel();
|
mVoiceInput.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mWordToSuggestions.clear();
|
||||||
mWordHistory.clear();
|
mWordHistory.clear();
|
||||||
super.hideWindow();
|
super.hideWindow();
|
||||||
TextEntryState.endSession();
|
TextEntryState.endSession();
|
||||||
|
@ -1512,9 +1489,6 @@ public class LatinIME extends InputMethodService
|
||||||
// Show N-Best alternates, if there is more than one choice.
|
// Show N-Best alternates, if there is more than one choice.
|
||||||
if (nBest.size() > 1) {
|
if (nBest.size() > 1) {
|
||||||
mImmediatelyAfterVoiceSuggestions = true;
|
mImmediatelyAfterVoiceSuggestions = true;
|
||||||
mShowingVoiceSuggestions = true;
|
|
||||||
setSuggestions(nBest.subList(1, nBest.size()), false, true, true);
|
|
||||||
setCandidatesViewShown(true);
|
|
||||||
}
|
}
|
||||||
mVoiceInputHighlighted = true;
|
mVoiceInputHighlighted = true;
|
||||||
mWordToSuggestions.putAll(mVoiceResults.alternatives);
|
mWordToSuggestions.putAll(mVoiceResults.alternatives);
|
||||||
|
@ -1682,6 +1656,29 @@ public class LatinIME extends InputMethodService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void rememberReplacedWord(CharSequence suggestion) {
|
||||||
|
if (mShowingVoiceSuggestions) {
|
||||||
|
// Retain the replaced word in the alternatives array.
|
||||||
|
InputConnection ic = getCurrentInputConnection();
|
||||||
|
EditingUtil.Range range = new EditingUtil.Range();
|
||||||
|
String wordToBeReplaced = EditingUtil.getWordAtCursor(getCurrentInputConnection(),
|
||||||
|
mWordSeparators, range).trim();
|
||||||
|
if (!mWordToSuggestions.containsKey(wordToBeReplaced)) {
|
||||||
|
wordToBeReplaced = wordToBeReplaced.toLowerCase();
|
||||||
|
}
|
||||||
|
if (mWordToSuggestions.containsKey(wordToBeReplaced)) {
|
||||||
|
List<CharSequence> suggestions = mWordToSuggestions.get(wordToBeReplaced);
|
||||||
|
if (suggestions.contains(suggestion)) {
|
||||||
|
suggestions.remove(suggestion);
|
||||||
|
}
|
||||||
|
suggestions.add(wordToBeReplaced);
|
||||||
|
mWordToSuggestions.remove(wordToBeReplaced);
|
||||||
|
mWordToSuggestions.put(suggestion.toString(), suggestions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: implement rememberReplacedWord for typed words
|
||||||
|
}
|
||||||
|
|
||||||
private void pickSuggestion(CharSequence suggestion) {
|
private void pickSuggestion(CharSequence suggestion) {
|
||||||
if (mCapsLock) {
|
if (mCapsLock) {
|
||||||
suggestion = suggestion.toString().toUpperCase();
|
suggestion = suggestion.toString().toUpperCase();
|
||||||
|
@ -1692,6 +1689,7 @@ public class LatinIME extends InputMethodService
|
||||||
}
|
}
|
||||||
InputConnection ic = getCurrentInputConnection();
|
InputConnection ic = getCurrentInputConnection();
|
||||||
if (ic != null) {
|
if (ic != null) {
|
||||||
|
rememberReplacedWord(suggestion);
|
||||||
if (mSuggestionShouldReplaceCurrentWord) {
|
if (mSuggestionShouldReplaceCurrentWord) {
|
||||||
EditingUtil.deleteWordAtCursor(ic, getWordSeparators());
|
EditingUtil.deleteWordAtCursor(ic, getWordSeparators());
|
||||||
}
|
}
|
||||||
|
@ -1710,6 +1708,7 @@ public class LatinIME extends InputMethodService
|
||||||
private void setOldSuggestions() {
|
private void setOldSuggestions() {
|
||||||
// TODO: Inefficient to check if touching word and then get the touching word. Do it
|
// TODO: Inefficient to check if touching word and then get the touching word. Do it
|
||||||
// in one go.
|
// in one go.
|
||||||
|
mShowingVoiceSuggestions = false;
|
||||||
InputConnection ic = getCurrentInputConnection();
|
InputConnection ic = getCurrentInputConnection();
|
||||||
if (ic == null) return;
|
if (ic == null) return;
|
||||||
ic.beginBatchEdit();
|
ic.beginBatchEdit();
|
||||||
|
@ -1727,7 +1726,35 @@ public class LatinIME extends InputMethodService
|
||||||
if (mWordSeparators.indexOf(touching.charAt(touching.length() - 1)) > 0) {
|
if (mWordSeparators.indexOf(touching.charAt(touching.length() - 1)) > 0) {
|
||||||
touching = touching.toString().substring(0, touching.length() - 1);
|
touching = touching.toString().substring(0, touching.length() - 1);
|
||||||
}
|
}
|
||||||
// Search for result in word history
|
|
||||||
|
// Search for result in spoken word alternatives
|
||||||
|
// TODO: possibly combine the spoken suggestions with the typed suggestions.
|
||||||
|
String selectedWord = touching.toString().trim();
|
||||||
|
if (!mWordToSuggestions.containsKey(selectedWord)){
|
||||||
|
selectedWord = selectedWord.toLowerCase();
|
||||||
|
}
|
||||||
|
if (mWordToSuggestions.containsKey(selectedWord)){
|
||||||
|
mShowingVoiceSuggestions = true;
|
||||||
|
mSuggestionShouldReplaceCurrentWord = true;
|
||||||
|
underlineWord(touching, range.charsBefore, range.charsAfter);
|
||||||
|
List<CharSequence> suggestions = mWordToSuggestions.get(selectedWord);
|
||||||
|
// If the first letter of touching is capitalized, make all the suggestions
|
||||||
|
// start with a capital letter.
|
||||||
|
if (Character.isUpperCase((char) touching.charAt(0))) {
|
||||||
|
for (int i=0; i< suggestions.size(); i++) {
|
||||||
|
String origSugg = (String) suggestions.get(i);
|
||||||
|
String capsSugg = origSugg.toUpperCase().charAt(0)
|
||||||
|
+ origSugg.subSequence(1, origSugg.length()).toString();
|
||||||
|
suggestions.set(i,capsSugg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setSuggestions(suggestions, false, true, true);
|
||||||
|
setCandidatesViewShown(true);
|
||||||
|
TextEntryState.selectedForCorrection();
|
||||||
|
ic.endBatchEdit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If we didn't find a match, search for result in word history
|
||||||
WordComposer foundWord = null;
|
WordComposer foundWord = null;
|
||||||
WordAlternatives alternatives = null;
|
WordAlternatives alternatives = null;
|
||||||
for (WordAlternatives entry : mWordHistory) {
|
for (WordAlternatives entry : mWordHistory) {
|
||||||
|
|
|
@ -63,7 +63,7 @@ public class VoiceInput implements OnClickListener {
|
||||||
|
|
||||||
// WARNING! Before enabling this, fix the problem with calling getExtractedText() in
|
// WARNING! Before enabling this, fix the problem with calling getExtractedText() in
|
||||||
// landscape view. It causes Extracted text updates to be rejected due to a token mismatch
|
// landscape view. It causes Extracted text updates to be rejected due to a token mismatch
|
||||||
public static boolean ENABLE_WORD_CORRECTIONS = false;
|
public static boolean ENABLE_WORD_CORRECTIONS = true;
|
||||||
|
|
||||||
// Dummy word suggestion which means "delete current word"
|
// Dummy word suggestion which means "delete current word"
|
||||||
public static final String DELETE_SYMBOL = " \u00D7 "; // times symbol
|
public static final String DELETE_SYMBOL = " \u00D7 "; // times symbol
|
||||||
|
@ -308,7 +308,7 @@ public class VoiceInput implements OnClickListener {
|
||||||
SettingsUtil.getSettingsInt(
|
SettingsUtil.getSettingsInt(
|
||||||
mContext.getContentResolver(),
|
mContext.getContentResolver(),
|
||||||
SettingsUtil.LATIN_IME_MAX_VOICE_RESULTS,
|
SettingsUtil.LATIN_IME_MAX_VOICE_RESULTS,
|
||||||
1));
|
10));
|
||||||
|
|
||||||
// Get endpointer params from Gservices.
|
// Get endpointer params from Gservices.
|
||||||
// TODO: Consider caching these values for improved performance on slower devices.
|
// TODO: Consider caching these values for improved performance on slower devices.
|
||||||
|
|
Loading…
Reference in a new issue