aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/CandidateView.java
diff options
context:
space:
mode:
authorsatok <satok@google.com>2010-12-27 20:13:16 +0900
committersatok <satok@google.com>2010-12-27 20:13:16 +0900
commitd12def6dc8ba3a2f47b90e6d5d442f315152c6d4 (patch)
tree7274b29f518f94d31cd5c995d1b46bfc323de818 /java/src/com/android/inputmethod/latin/CandidateView.java
parentb80f171623a11bceb99b563594162d0034b9bde8 (diff)
parentbfe2b534457d946645d483e311249787ba4fc3ae (diff)
downloadlatinime-d12def6dc8ba3a2f47b90e6d5d442f315152c6d4.tar.gz
latinime-d12def6dc8ba3a2f47b90e6d5d442f315152c6d4.tar.xz
latinime-d12def6dc8ba3a2f47b90e6d5d442f315152c6d4.zip
Merge remote branch 'goog/master' into merge
Conflicts: java/res/values-cs/strings.xml java/res/values-da/strings.xml java/res/values-de/strings.xml java/res/values-el/strings.xml java/res/values-es-rUS/strings.xml java/res/values-es/strings.xml java/res/values-fr/strings.xml java/res/values-it/strings.xml java/res/values-ja/strings.xml java/res/values-ko/strings.xml java/res/values-nb/strings.xml java/res/values-nl/strings.xml java/res/values-pl/strings.xml java/res/values-pt-rPT/strings.xml java/res/values-pt/strings.xml java/res/values-ru/strings.xml java/res/values-sv/strings.xml java/res/values-tr/strings.xml java/res/values-xlarge/dimens.xml java/res/values-zh-rCN/strings.xml java/res/values-zh-rTW/strings.xml java/res/values/bools.xml java/res/xml/kbd_qwerty_rows.xml java/res/xml/method.xml java/res/xml/prefs.xml Change-Id: I8768d16965e6e82c14ee742b9ada56438497eb86
Diffstat (limited to 'java/src/com/android/inputmethod/latin/CandidateView.java')
-rw-r--r--[-rwxr-xr-x]java/src/com/android/inputmethod/latin/CandidateView.java653
1 files changed, 223 insertions, 430 deletions
diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java
index 0f5b43009..30f4a59f9 100755..100644
--- a/java/src/com/android/inputmethod/latin/CandidateView.java
+++ b/java/src/com/android/inputmethod/latin/CandidateView.java
@@ -1,12 +1,12 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
- *
+ * Copyright (C) 2010 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
@@ -16,99 +16,101 @@
package com.android.inputmethod.latin;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
import android.graphics.Typeface;
-import android.graphics.Paint.Align;
-import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.text.style.BackgroundColorSpan;
+import android.text.style.CharacterStyle;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.StyleSpan;
+import android.text.style.UnderlineSpan;
import android.util.AttributeSet;
-import android.view.GestureDetector;
import android.view.Gravity;
import android.view.LayoutInflater;
-import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewGroup.LayoutParams;
+import android.view.View.OnClickListener;
+import android.view.View.OnLongClickListener;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.TextView;
-public class CandidateView extends View {
-
- private static final int OUT_OF_BOUNDS = -1;
- private static final List<CharSequence> EMPTY_LIST = new ArrayList<CharSequence>();
+import java.util.ArrayList;
+public class CandidateView extends LinearLayout implements OnClickListener, OnLongClickListener {
private LatinIME mService;
- private List<CharSequence> mSuggestions = EMPTY_LIST;
- private boolean mShowingCompletions;
- private CharSequence mSelectedString;
- private int mSelectedIndex;
- private int mTouchX = OUT_OF_BOUNDS;
- private Drawable mSelectionHighlight;
- private boolean mTypedWordValid;
-
- private boolean mHaveMinimalSuggestion;
-
- private Rect mBgPadding;
+ private final ArrayList<View> mWords = new ArrayList<View>();
- private TextView mPreviewText;
- private PopupWindow mPreviewPopup;
- private int mCurrentWordIndex;
- private Drawable mDivider;
-
- private static final int MAX_SUGGESTIONS = 32;
- private static final int SCROLL_PIXELS = 20;
-
- private static final int MSG_REMOVE_PREVIEW = 1;
- private static final int MSG_REMOVE_THROUGH_PREVIEW = 2;
+ private final TextView mPreviewText;
+ private final PopupWindow mPreviewPopup;
- private int[] mWordWidth = new int[MAX_SUGGESTIONS];
- private int[] mWordX = new int[MAX_SUGGESTIONS];
- private int mPopupPreviewX;
- private int mPopupPreviewY;
-
- private static final int X_GAP = 10;
-
- private int mColorNormal;
- private int mColorRecommended;
- private int mColorOther;
- private Paint mPaint;
- private int mDescent;
- private boolean mScrolled;
+ private static final int MAX_SUGGESTIONS = 16;
+
+ private final boolean mConfigCandidateHighlightFontColorEnabled;
+ private final int mColorNormal;
+ private final int mColorRecommended;
+ private final int mColorOther;
+ private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
+ private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
+ private final CharacterStyle mInvertedForegroundColorSpan;
+ private final CharacterStyle mInvertedBackgroundColorSpan;
+
+ private SuggestedWords mSuggestions = SuggestedWords.EMPTY;
+ private boolean mShowingAutoCorrectionInverted;
private boolean mShowingAddToDictionary;
- private CharSequence mAddToDictionaryHint;
- private int mTargetScrollX;
+ private final UiHandler mHandler = new UiHandler();
- private int mMinTouchableWidth;
+ private class UiHandler extends Handler {
+ private static final int MSG_HIDE_PREVIEW = 0;
+ private static final int MSG_UPDATE_SUGGESTION = 1;
- private int mTotalWidth;
-
- private GestureDetector mGestureDetector;
+ private static final long DELAY_HIDE_PREVIEW = 1000;
+ private static final long DELAY_UPDATE_SUGGESTION = 300;
- Handler mHandler = new Handler() {
@Override
- public void handleMessage(Message msg) {
+ public void dispatchMessage(Message msg) {
switch (msg.what) {
- case MSG_REMOVE_PREVIEW:
- mPreviewText.setVisibility(GONE);
- break;
- case MSG_REMOVE_THROUGH_PREVIEW:
- mPreviewText.setVisibility(GONE);
- if (mTouchX != OUT_OF_BOUNDS) {
- removeHighlight();
- }
- break;
+ case MSG_HIDE_PREVIEW:
+ hidePreview();
+ break;
+ case MSG_UPDATE_SUGGESTION:
+ updateSuggestions();
+ break;
}
}
- };
+
+ public void postHidePreview() {
+ cancelHidePreview();
+ sendMessageDelayed(obtainMessage(MSG_HIDE_PREVIEW), DELAY_HIDE_PREVIEW);
+ }
+
+ public void cancelHidePreview() {
+ removeMessages(MSG_HIDE_PREVIEW);
+ }
+
+ public void postUpdateSuggestions() {
+ cancelUpdateSuggestions();
+ sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTION),
+ DELAY_UPDATE_SUGGESTION);
+ }
+
+ public void cancelUpdateSuggestions() {
+ removeMessages(MSG_UPDATE_SUGGESTION);
+ }
+
+ public void cancelAllMessages() {
+ cancelHidePreview();
+ cancelUpdateSuggestions();
+ }
+ }
/**
* Construct a CandidateView for showing suggested words for completion.
@@ -117,81 +119,40 @@ public class CandidateView extends View {
*/
public CandidateView(Context context, AttributeSet attrs) {
super(context, attrs);
- mSelectionHighlight = context.getResources().getDrawable(
- R.drawable.list_selector_background_pressed);
- LayoutInflater inflate =
- (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Resources res = context.getResources();
mPreviewPopup = new PopupWindow(context);
- mPreviewText = (TextView) inflate.inflate(R.layout.candidate_preview, null);
- mPreviewPopup.setWindowLayoutMode(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ LayoutInflater inflater = LayoutInflater.from(context);
+ mPreviewText = (TextView) inflater.inflate(R.layout.candidate_preview, null);
+ mPreviewPopup.setWindowLayoutMode(ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
mPreviewPopup.setContentView(mPreviewText);
mPreviewPopup.setBackgroundDrawable(null);
+ mPreviewPopup.setAnimationStyle(R.style.KeyPreviewAnimation);
+ mConfigCandidateHighlightFontColorEnabled =
+ res.getBoolean(R.bool.config_candidate_highlight_font_color_enabled);
mColorNormal = res.getColor(R.color.candidate_normal);
mColorRecommended = res.getColor(R.color.candidate_recommended);
mColorOther = res.getColor(R.color.candidate_other);
- mDivider = res.getDrawable(R.drawable.keyboard_suggest_strip_divider);
- mAddToDictionaryHint = res.getString(R.string.hint_add_to_dictionary);
-
- mPaint = new Paint();
- mPaint.setColor(mColorNormal);
- mPaint.setAntiAlias(true);
- mPaint.setTextSize(mPreviewText.getTextSize());
- mPaint.setStrokeWidth(0);
- mPaint.setTextAlign(Align.CENTER);
- mDescent = (int) mPaint.descent();
- // 50 pixels for a 160dpi device would mean about 0.3 inch
- mMinTouchableWidth = (int) (getResources().getDisplayMetrics().density * 50);
-
- // Slightly reluctant to scroll to be able to easily choose the suggestion
- // 50 pixels for a 160dpi device would mean about 0.3 inch
- final int touchSlop = (int) (getResources().getDisplayMetrics().density * 50);
- final int touchSlopSquare = touchSlop * touchSlop;
- mGestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
- @Override
- public void onLongPress(MotionEvent me) {
- if (mSuggestions.size() > 0) {
- if (me.getX() + getScrollX() < mWordWidth[0] && getScrollX() < 10) {
- longPressFirstWord();
- }
- }
- }
-
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2,
- float distanceX, float distanceY) {
- final int deltaX = (int) (e2.getX() - e1.getX());
- final int deltaY = (int) (e2.getY() - e1.getY());
- final int distance = (deltaX * deltaX) + (deltaY * deltaY);
- if (distance < touchSlopSquare) {
- return false;
- }
+ mInvertedForegroundColorSpan = new ForegroundColorSpan(mColorNormal ^ 0x00ffffff);
+ mInvertedBackgroundColorSpan = new BackgroundColorSpan(mColorNormal);
+
+ for (int i = 0; i < MAX_SUGGESTIONS; i++) {
+ View v = inflater.inflate(R.layout.candidate, null);
+ TextView tv = (TextView)v.findViewById(R.id.candidate_word);
+ tv.setTag(i);
+ tv.setOnClickListener(this);
+ if (i == 0)
+ tv.setOnLongClickListener(this);
+ ImageView divider = (ImageView)v.findViewById(R.id.candidate_divider);
+ // Do not display divider of first candidate.
+ divider.setVisibility(i == 0 ? GONE : VISIBLE);
+ mWords.add(v);
+ }
- final int width = getWidth();
- mScrolled = true;
- int scrollX = getScrollX();
- scrollX += (int) distanceX;
- if (scrollX < 0) {
- scrollX = 0;
- }
- if (distanceX > 0 && scrollX + width > mTotalWidth) {
- scrollX -= (int) distanceX;
- }
- mTargetScrollX = scrollX;
- scrollTo(scrollX, getScrollY());
- hidePreview();
- invalidate();
- return true;
- }
- });
- setWillNotDraw(false);
- setHorizontalScrollBarEnabled(false);
- setVerticalScrollBarEnabled(false);
scrollTo(0, getScrollY());
}
-
+
/**
* A connection back to the service to communicate with the text field
* @param listener
@@ -199,154 +160,100 @@ public class CandidateView extends View {
public void setService(LatinIME listener) {
mService = listener;
}
-
- @Override
- public int computeHorizontalScrollRange() {
- return mTotalWidth;
- }
- /**
- * If the canvas is null, then only touch calculations are performed to pick the target
- * candidate.
- */
- @Override
- protected void onDraw(Canvas canvas) {
- if (canvas != null) {
- super.onDraw(canvas);
- }
- mTotalWidth = 0;
- if (mSuggestions == null) return;
-
- final int height = getHeight();
- if (mBgPadding == null) {
- mBgPadding = new Rect(0, 0, 0, 0);
- if (getBackground() != null) {
- getBackground().getPadding(mBgPadding);
- }
- mDivider.setBounds(0, 0, mDivider.getIntrinsicWidth(),
- mDivider.getIntrinsicHeight());
+ public void setSuggestions(SuggestedWords suggestions) {
+ if (suggestions == null)
+ return;
+ mSuggestions = suggestions;
+ if (mShowingAutoCorrectionInverted) {
+ mHandler.postUpdateSuggestions();
+ } else {
+ updateSuggestions();
}
- int x = 0;
- final int count = Math.min(mSuggestions.size(), MAX_SUGGESTIONS);
- final Rect bgPadding = mBgPadding;
- final Paint paint = mPaint;
- final int touchX = mTouchX;
- final int scrollX = getScrollX();
- final boolean scrolled = mScrolled;
- final boolean typedWordValid = mTypedWordValid;
- final int y = (int) (height + mPaint.getTextSize() - mDescent) / 2;
-
- boolean existsAutoCompletion = false;
+ }
+ private void updateSuggestions() {
+ final SuggestedWords suggestions = mSuggestions;
+ clear();
+ final int count = suggestions.size();
+ final Object[] debugInfo = suggestions.mDebugInfo;
for (int i = 0; i < count; i++) {
- CharSequence suggestion = mSuggestions.get(i);
- if (suggestion == null) continue;
- paint.setColor(mColorNormal);
- if (mHaveMinimalSuggestion
- && ((i == 1 && !typedWordValid) || (i == 0 && typedWordValid))) {
- paint.setTypeface(Typeface.DEFAULT_BOLD);
- paint.setColor(mColorRecommended);
- existsAutoCompletion = true;
- } else if (i != 0 || (suggestion.length() == 1 && count > 1)) {
- // HACK: even if i == 0, we use mColorOther when this suggestion's length is 1 and
- // there are multiple suggestions, such as the default punctuation list.
- paint.setColor(mColorOther);
- }
- final int wordWidth;
- if (mWordWidth[i] != 0) {
- wordWidth = mWordWidth[i];
- } else {
- float textWidth = paint.measureText(suggestion, 0, suggestion.length());
- wordWidth = Math.max(mMinTouchableWidth, (int) textWidth + X_GAP * 2);
- mWordWidth[i] = wordWidth;
- }
-
- mWordX[i] = x;
-
- if (touchX + scrollX >= x && touchX + scrollX < x + wordWidth && !scrolled &&
- touchX != OUT_OF_BOUNDS) {
- if (canvas != null && !mShowingAddToDictionary) {
- canvas.translate(x, 0);
- mSelectionHighlight.setBounds(0, bgPadding.top, wordWidth, height);
- mSelectionHighlight.draw(canvas);
- canvas.translate(-x, 0);
- showPreview(i, null);
- }
- mSelectedString = suggestion;
- mSelectedIndex = i;
- }
-
- if (canvas != null) {
- canvas.drawText(suggestion, 0, suggestion.length(), x + wordWidth / 2, y, paint);
- paint.setColor(mColorOther);
- canvas.translate(x + wordWidth, 0);
- // Draw a divider unless it's after the hint
- if (!(mShowingAddToDictionary && i == 1)) {
- mDivider.draw(canvas);
+ CharSequence word = suggestions.getWord(i);
+ if (word == null) continue;
+ final int wordLength = word.length();
+
+ final View v = mWords.get(i);
+ final TextView tv = (TextView)v.findViewById(R.id.candidate_word);
+ final TextView dv = (TextView)v.findViewById(R.id.candidate_debug_info);
+ tv.setTextColor(mColorNormal);
+ if (suggestions.mHasMinimalSuggestion
+ && ((i == 1 && !suggestions.mTypedWordValid) ||
+ (i == 0 && suggestions.mTypedWordValid))) {
+ final CharacterStyle style;
+ if (mConfigCandidateHighlightFontColorEnabled) {
+ style = BOLD_SPAN;
+ tv.setTextColor(mColorRecommended);
+ } else {
+ style = UNDERLINE_SPAN;
}
- canvas.translate(-x - wordWidth, 0);
- }
- paint.setTypeface(Typeface.DEFAULT);
- x += wordWidth;
- }
- mService.onAutoCompletionStateChanged(existsAutoCompletion);
- mTotalWidth = x;
- if (mTargetScrollX != scrollX) {
- scrollToTarget();
- }
- }
-
- private void scrollToTarget() {
- int scrollX = getScrollX();
- if (mTargetScrollX > scrollX) {
- scrollX += SCROLL_PIXELS;
- if (scrollX >= mTargetScrollX) {
- scrollX = mTargetScrollX;
- scrollTo(scrollX, getScrollY());
- requestLayout();
- } else {
- scrollTo(scrollX, getScrollY());
+ final Spannable spannedWord = new SpannableString(word);
+ spannedWord.setSpan(style, 0, wordLength, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+ word = spannedWord;
+ } else if (i != 0 || (wordLength == 1 && count > 1)) {
+ // HACK: even if i == 0, we use mColorOther when this
+ // suggestion's length is 1
+ // and there are multiple suggestions, such as the default
+ // punctuation list.
+ if (mConfigCandidateHighlightFontColorEnabled)
+ tv.setTextColor(mColorOther);
}
- } else {
- scrollX -= SCROLL_PIXELS;
- if (scrollX <= mTargetScrollX) {
- scrollX = mTargetScrollX;
- scrollTo(scrollX, getScrollY());
- requestLayout();
+ tv.setText(word);
+ tv.setClickable(true);
+ if (debugInfo != null && i < debugInfo.length && debugInfo[i] != null
+ && !TextUtils.isEmpty(debugInfo[i].toString())) {
+ dv.setText(debugInfo[i].toString());
+ dv.setVisibility(VISIBLE);
} else {
- scrollTo(scrollX, getScrollY());
+ dv.setVisibility(GONE);
}
+ addView(v);
}
- invalidate();
- }
-
- public void setSuggestions(List<CharSequence> suggestions, boolean completions,
- boolean typedWordValid, boolean haveMinimalSuggestion) {
- clear();
- if (suggestions != null) {
- mSuggestions = new ArrayList<CharSequence>(suggestions);
- }
- mShowingCompletions = completions;
- mTypedWordValid = typedWordValid;
+
scrollTo(0, getScrollY());
- mTargetScrollX = 0;
- mHaveMinimalSuggestion = haveMinimalSuggestion;
- // Compute the total width
- onDraw(null);
- invalidate();
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, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+ word.setSpan(mInvertedForegroundColorSpan, 0, wordLength, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+ tv.setText(word);
+ mShowingAutoCorrectionInverted = true;
+ }
+
+ public boolean isConfigCandidateHighlightFontColorEnabled() {
+ return mConfigCandidateHighlightFontColorEnabled;
+ }
+
public boolean isShowingAddToDictionaryHint() {
return mShowingAddToDictionary;
}
public void showAddToDictionaryHint(CharSequence word) {
- ArrayList<CharSequence> suggestions = new ArrayList<CharSequence>();
- suggestions.add(word);
- suggestions.add(mAddToDictionaryHint);
- setSuggestions(suggestions, false, false, false);
+ SuggestedWords.Builder builder = new SuggestedWords.Builder()
+ .addWord(word)
+ .addWord(getContext().getText(R.string.hint_add_to_dictionary));
+ setSuggestions(builder.build());
mShowingAddToDictionary = true;
+ // Disable R.string.hint_add_to_dictionary button
+ TextView tv = (TextView)getChildAt(1).findViewById(R.id.candidate_word);
+ tv.setClickable(false);
}
public boolean dismissAddToDictionaryHint() {
@@ -355,192 +262,78 @@ public class CandidateView extends View {
return true;
}
- public void scrollPrev() {
- int i = 0;
- final int count = Math.min(mSuggestions.size(), MAX_SUGGESTIONS);
- int firstItem = 0; // Actually just before the first item, if at the boundary
- while (i < count) {
- if (mWordX[i] < getScrollX()
- && mWordX[i] + mWordWidth[i] >= getScrollX() - 1) {
- firstItem = i;
- break;
- }
- i++;
- }
- int leftEdge = mWordX[firstItem] + mWordWidth[firstItem] - getWidth();
- if (leftEdge < 0) leftEdge = 0;
- updateScrollPosition(leftEdge);
- }
-
- public void scrollNext() {
- int i = 0;
- int scrollX = getScrollX();
- int targetX = scrollX;
- final int count = Math.min(mSuggestions.size(), MAX_SUGGESTIONS);
- int rightEdge = scrollX + getWidth();
- while (i < count) {
- if (mWordX[i] <= rightEdge &&
- mWordX[i] + mWordWidth[i] >= rightEdge) {
- targetX = Math.min(mWordX[i], mTotalWidth - getWidth());
- break;
- }
- i++;
- }
- updateScrollPosition(targetX);
+ public SuggestedWords getSuggestions() {
+ return mSuggestions;
}
- private void updateScrollPosition(int targetX) {
- if (targetX != getScrollX()) {
- // TODO: Animate
- mTargetScrollX = targetX;
- requestLayout();
- invalidate();
- mScrolled = true;
- }
+ public void clear() {
+ mShowingAddToDictionary = false;
+ mShowingAutoCorrectionInverted = false;
+ removeAllViews();
}
- /* package */ List<CharSequence> getSuggestions() {
- return mSuggestions;
+ private void hidePreview() {
+ mPreviewPopup.dismiss();
}
- public void clear() {
- // Don't call mSuggestions.clear() because it's being used for logging
- // in LatinIME.pickSuggestionManually().
- mSuggestions = EMPTY_LIST;
- mTouchX = OUT_OF_BOUNDS;
- mSelectedString = null;
- mSelectedIndex = -1;
- mShowingAddToDictionary = false;
- invalidate();
- Arrays.fill(mWordWidth, 0);
- Arrays.fill(mWordX, 0);
- if (mPreviewPopup.isShowing()) {
- mPreviewPopup.dismiss();
+ private void showPreview(int index, CharSequence word) {
+ if (TextUtils.isEmpty(word))
+ return;
+
+ final TextView previewText = mPreviewText;
+ previewText.setTextColor(mColorNormal);
+ previewText.setText(word);
+ previewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
+ MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+ View v = getChildAt(index);
+ final int[] offsetInWindow = new int[2];
+ v.getLocationInWindow(offsetInWindow);
+ final int posX = offsetInWindow[0];
+ final int posY = offsetInWindow[1] - previewText.getMeasuredHeight();
+ final PopupWindow previewPopup = mPreviewPopup;
+ if (previewPopup.isShowing()) {
+ previewPopup.update(posX, posY, previewPopup.getWidth(), previewPopup.getHeight());
+ } else {
+ previewPopup.showAtLocation(this, Gravity.NO_GRAVITY, posX, posY);
}
+ previewText.setVisibility(VISIBLE);
+ mHandler.postHidePreview();
}
-
- @Override
- public boolean onTouchEvent(MotionEvent me) {
- if (mGestureDetector.onTouchEvent(me)) {
- return true;
+ private void addToDictionary(CharSequence word) {
+ if (mService.addWordToDictionary(word.toString())) {
+ showPreview(0, getContext().getString(R.string.added_word, word));
}
+ }
- int action = me.getAction();
- int x = (int) me.getX();
- int y = (int) me.getY();
- mTouchX = x;
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- mScrolled = false;
- invalidate();
- break;
- case MotionEvent.ACTION_MOVE:
- if (y <= 0) {
- // Fling up!?
- if (mSelectedString != null) {
- // If there are completions from the application, we don't change the state to
- // STATE_PICKED_SUGGESTION
- if (!mShowingCompletions) {
- // This "acceptedSuggestion" will not be counted as a word because
- // it will be counted in pickSuggestion instead.
- TextEntryState.acceptedSuggestion(mSuggestions.get(0),
- mSelectedString);
- }
- mService.pickSuggestionManually(mSelectedIndex, mSelectedString);
- mSelectedString = null;
- mSelectedIndex = -1;
- }
- }
- invalidate();
- break;
- case MotionEvent.ACTION_UP:
- if (!mScrolled) {
- if (mSelectedString != null) {
- if (mShowingAddToDictionary) {
- longPressFirstWord();
- clear();
- } else {
- if (!mShowingCompletions) {
- TextEntryState.acceptedSuggestion(mSuggestions.get(0),
- mSelectedString);
- }
- mService.pickSuggestionManually(mSelectedIndex, mSelectedString);
- }
- }
- }
- mSelectedString = null;
- mSelectedIndex = -1;
- removeHighlight();
- hidePreview();
- requestLayout();
- break;
- }
+ @Override
+ public boolean onLongClick(View view) {
+ int index = (Integer) view.getTag();
+ CharSequence word = mSuggestions.getWord(index);
+ if (word.length() < 2)
+ return false;
+ addToDictionary(word);
return true;
}
- private void hidePreview() {
- mCurrentWordIndex = OUT_OF_BOUNDS;
- if (mPreviewPopup.isShowing()) {
- mHandler.sendMessageDelayed(mHandler
- .obtainMessage(MSG_REMOVE_PREVIEW), 60);
- }
- }
-
- private void showPreview(int wordIndex, String altText) {
- int oldWordIndex = mCurrentWordIndex;
- mCurrentWordIndex = wordIndex;
- // If index changed or changing text
- if (oldWordIndex != mCurrentWordIndex || altText != null) {
- if (wordIndex == OUT_OF_BOUNDS) {
- hidePreview();
- } else {
- CharSequence word = altText != null? altText : mSuggestions.get(wordIndex);
- mPreviewText.setText(word);
- mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- int wordWidth = (int) (mPaint.measureText(word, 0, word.length()) + X_GAP * 2);
- final int popupWidth = wordWidth
- + mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight();
- final int popupHeight = mPreviewText.getMeasuredHeight();
- //mPreviewText.setVisibility(INVISIBLE);
- mPopupPreviewX = mWordX[wordIndex] - mPreviewText.getPaddingLeft() - getScrollX()
- + (mWordWidth[wordIndex] - wordWidth) / 2;
- mPopupPreviewY = - popupHeight;
- mHandler.removeMessages(MSG_REMOVE_PREVIEW);
- int [] offsetInWindow = new int[2];
- getLocationInWindow(offsetInWindow);
- if (mPreviewPopup.isShowing()) {
- mPreviewPopup.update(mPopupPreviewX, mPopupPreviewY + offsetInWindow[1],
- popupWidth, popupHeight);
- } else {
- mPreviewPopup.setWidth(popupWidth);
- mPreviewPopup.setHeight(popupHeight);
- mPreviewPopup.showAtLocation(this, Gravity.NO_GRAVITY, mPopupPreviewX,
- mPopupPreviewY + offsetInWindow[1]);
- }
- mPreviewText.setVisibility(VISIBLE);
+ @Override
+ public void onClick(View view) {
+ int index = (Integer) view.getTag();
+ CharSequence word = mSuggestions.getWord(index);
+ if (mShowingAddToDictionary && index == 0) {
+ addToDictionary(word);
+ } else {
+ if (!mSuggestions.mIsApplicationSpecifiedCompletions) {
+ TextEntryState.acceptedSuggestion(mSuggestions.getWord(0), word);
}
- }
- }
-
- private void removeHighlight() {
- mTouchX = OUT_OF_BOUNDS;
- invalidate();
- }
-
- private void longPressFirstWord() {
- CharSequence word = mSuggestions.get(0);
- if (word.length() < 2) return;
- if (mService.addWordToDictionary(word.toString())) {
- showPreview(0, getContext().getResources().getString(R.string.added_word, word));
+ mService.pickSuggestionManually(index, word);
}
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
+ mHandler.cancelAllMessages();
hidePreview();
}
}