diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin/CandidateView.java')
-rw-r--r-- | java/src/com/android/inputmethod/latin/CandidateView.java | 285 |
1 files changed, 118 insertions, 167 deletions
diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java index b9ded31cb..fe48f0bc1 100644 --- a/java/src/com/android/inputmethod/latin/CandidateView.java +++ b/java/src/com/android/inputmethod/latin/CandidateView.java @@ -23,6 +23,7 @@ import android.graphics.Color; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Message; +import android.os.SystemClock; import android.text.Spannable; import android.text.SpannableString; import android.text.Spanned; @@ -34,8 +35,10 @@ import android.text.style.ForegroundColorSpan; import android.text.style.StyleSpan; import android.text.style.UnderlineSpan; import android.util.AttributeSet; +import android.util.DisplayMetrics; import android.view.Gravity; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; @@ -46,6 +49,9 @@ import android.widget.TextView; import com.android.inputmethod.compat.FrameLayoutCompatUtils; import com.android.inputmethod.compat.LinearLayoutCompatUtils; +import com.android.inputmethod.keyboard.KeyboardActionListener; +import com.android.inputmethod.keyboard.MoreKeysPanel; +import com.android.inputmethod.keyboard.PointerTracker; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import java.util.ArrayList; @@ -58,16 +64,19 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo } // The maximum number of suggestions available. See {@link Suggest#mPrefMaxSuggestions}. - private static final int MAX_SUGGESTIONS = 18; + public static final int MAX_SUGGESTIONS = 18; private static final boolean DBG = LatinImeLogger.sDBG; private final ViewGroup mCandidatesPlacer; private final ViewGroup mCandidatesStrip; - private ViewGroup mCandidatesPane; - private ViewGroup mCandidatesPaneContainer; private View mKeyboardView; + private final View mMoreSuggestionsContainer; + private final MoreSuggestionsView mMoreSuggestionsView; + private final MoreSuggestions.Builder mMoreSuggestionsBuilder; + private final PopupWindow mMoreSuggestionsWindow; + private final ArrayList<TextView> mWords = new ArrayList<TextView>(); private final ArrayList<TextView> mInfos = new ArrayList<TextView>(); private final ArrayList<View> mDividers = new ArrayList<View>(); @@ -80,7 +89,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo private boolean mShowingAutoCorrectionInverted; private final SuggestionsStripParams mStripParams; - private final SuggestionsPaneParams mPaneParams; private static final float MIN_TEXT_XSCALE = 0.70f; private final UiHandler mHandler = new UiHandler(this); @@ -137,7 +145,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo private static class CandidateViewParams { public final int mPadding; public final int mDividerWidth; - public final int mDividerHeight; public final int mCandidateStripHeight; protected final List<TextView> mWords; @@ -156,96 +163,9 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo divider.measure( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); mDividerWidth = divider.getMeasuredWidth(); - mDividerHeight = divider.getMeasuredHeight(); final Resources res = word.getResources(); - mCandidateStripHeight = res.getDimensionPixelOffset(R.dimen.candidate_strip_height); - } - } - - private static class SuggestionsPaneParams extends CandidateViewParams { - public SuggestionsPaneParams(List<TextView> words, List<View> dividers, - List<TextView> infos) { - super(words, dividers, infos); - } - - public int layout(SuggestedWords suggestions, ViewGroup paneView, int from, int textColor, - int paneWidth) { - final int count = Math.min(mWords.size(), suggestions.size()); - View centeringFrom = null, lastView = null; - int x = 0, y = 0; - for (int index = from; index < count; index++) { - final int pos = index; - final TextView word = mWords.get(pos); - final View divider = mDividers.get(pos); - final TextPaint paint = word.getPaint(); - word.setTextColor(textColor); - final CharSequence styled = suggestions.getWord(pos); - - final TextView info; - if (DBG) { - final CharSequence debugInfo = getDebugInfo(suggestions, index); - if (debugInfo != null) { - info = mInfos.get(index); - info.setText(debugInfo); - } else { - info = null; - } - } else { - info = null; - } - - final CharSequence text; - final float scaleX; - paint.setTextScaleX(1.0f); - final int textWidth = getTextWidth(styled, paint); - int available = paneWidth - x - mPadding; - if (textWidth >= available) { - // Needs new row, centering previous row. - centeringCandidates(paneView, centeringFrom, lastView, x, paneWidth); - x = 0; - y += mCandidateStripHeight; - } - if (x != 0) { - // Add divider if this isn't the left most suggestion in current row. - paneView.addView(divider); - FrameLayoutCompatUtils.placeViewAt(divider, x, y - + (mCandidateStripHeight - mDividerHeight) / 2, mDividerWidth, - mDividerHeight); - x += mDividerWidth; - } - available = paneWidth - x - mPadding; - text = getEllipsizedText(styled, available, paint); - scaleX = paint.getTextScaleX(); - word.setText(text); - word.setTextScaleX(scaleX); - paneView.addView(word); - lastView = word; - if (x == 0) - centeringFrom = word; - word.measure(ViewGroup.LayoutParams.WRAP_CONTENT, - MeasureSpec.makeMeasureSpec(mCandidateStripHeight, MeasureSpec.EXACTLY)); - final int width = word.getMeasuredWidth(); - final int height = word.getMeasuredHeight(); - FrameLayoutCompatUtils.placeViewAt(word, x, y + (mCandidateStripHeight - height) - / 2, width, height); - x += width; - if (info != null) { - paneView.addView(info); - lastView = info; - info.measure(ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT); - final int infoWidth = info.getMeasuredWidth(); - FrameLayoutCompatUtils.placeViewAt( - info, x - infoWidth, y, infoWidth, info.getMeasuredHeight()); - } - } - if (x != 0) { - // Centering last candidates row. - centeringCandidates(paneView, centeringFrom, lastView, x, paneWidth); - } - - return count - from; + mCandidateStripHeight = res.getDimensionPixelSize(R.dimen.candidate_strip_height); } } @@ -257,7 +177,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo private final int mColorTypedWord; private final int mColorAutoCorrect; private final int mColorSuggestedCandidate; - private final int mCandidateCountInStrip; + public final int mCandidateCountInStrip; private final float mCenterCandidateWeight; private final int mCenterCandidateIndex; private final Drawable mMoreCandidateHint; @@ -311,10 +231,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo mHintToSaveText = context.getText(R.string.hint_add_to_dictionary); } - public int getTextColor() { - return mColorTypedWord; - } - private CharSequence getStyledCandidateWord(SuggestedWords suggestions, int pos) { final CharSequence word = suggestions.getWord(pos); final boolean isAutoCorrect = pos == 1 && willAutoCorrect(suggestions); @@ -389,10 +305,11 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo return word; } - public int layout(SuggestedWords suggestions, ViewGroup stripView, ViewGroup placer, + public void layout(SuggestedWords suggestions, ViewGroup stripView, ViewGroup placer, int stripWidth) { if (suggestions.isPunctuationSuggestions()) { - return layoutPunctuationSuggestions(suggestions, stripView); + layoutPunctuationSuggestions(suggestions, stripView); + return; } final int countInStrip = mCandidateCountInStrip; @@ -449,8 +366,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo } } } - - return countInStrip; } private int getCandidateWidth(int index, int maxWidth) { @@ -482,7 +397,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo } } - private int layoutPunctuationSuggestions(SuggestedWords suggestions, ViewGroup stripView) { + private void layoutPunctuationSuggestions(SuggestedWords suggestions, ViewGroup stripView) { final int countInStrip = Math.min(suggestions.size(), PUNCTUATIONS_IN_STRIP); for (int index = 0; index < countInStrip; index++) { if (index != 0) { @@ -501,7 +416,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo setLayoutWeight(word, 1.0f, mCandidateStripHeight); } mMoreSuggestionsAvailable = false; - return countInStrip; } public void layoutAddToDictionaryHint(CharSequence word, ViewGroup stripView, @@ -583,8 +497,16 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo mStripParams = new SuggestionsStripParams(context, attrs, defStyle, mWords, mDividers, mInfos); - mPaneParams = new SuggestionsPaneParams(mWords, mDividers, mInfos); mStripParams.mWordToSaveView.setOnClickListener(this); + + mMoreSuggestionsContainer = inflater.inflate(R.layout.more_suggestions, null); + mMoreSuggestionsView = (MoreSuggestionsView)mMoreSuggestionsContainer + .findViewById(R.id.more_suggestions_view); + mMoreSuggestionsBuilder = new MoreSuggestions.Builder(mMoreSuggestionsView); + mMoreSuggestionsWindow = new PopupWindow(context); + mMoreSuggestionsWindow.setWindowLayoutMode( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + mMoreSuggestionsWindow.setBackgroundDrawable(null); } /** @@ -594,11 +516,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo public void setListener(Listener listener, View inputView) { mListener = listener; mKeyboardView = inputView.findViewById(R.id.keyboard_view); - mCandidatesPane = FrameLayoutCompatUtils.getPlacer( - (ViewGroup)inputView.findViewById(R.id.candidates_pane)); - mCandidatesPane.setOnClickListener(this); - mCandidatesPaneContainer = (ViewGroup)inputView.findViewById( - R.id.candidates_pane_container); } public void setSuggestions(SuggestedWords suggestions) { @@ -614,15 +531,10 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo private void updateSuggestions() { clear(); - closeCandidatesPane(); if (mSuggestions.size() == 0) return; - final int width = getWidth(); - final int countInStrip = mStripParams.layout( - mSuggestions, mCandidatesStrip, mCandidatesPlacer, width); - mPaneParams.layout( - mSuggestions, mCandidatesPane, countInStrip, mStripParams.getTextColor(), width); + mStripParams.layout(mSuggestions, mCandidatesStrip, mCandidatesPlacer, getWidth()); } private static CharSequence getDebugInfo(SuggestedWords suggestions, int pos) { @@ -648,26 +560,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo } } - private static void centeringCandidates(ViewGroup parent, View from, View to, int width, - int parentWidth) { - final int fromIndex = parent.indexOfChild(from); - final int toIndex = parent.indexOfChild(to); - final int offset = (parentWidth - width) / 2; - for (int index = fromIndex; index <= toIndex; index++) { - offsetMargin(parent.getChildAt(index), offset, 0); - } - } - - private static void offsetMargin(View v, int dx, int dy) { - if (v == null) - return; - final ViewGroup.LayoutParams lp = v.getLayoutParams(); - if (lp instanceof ViewGroup.MarginLayoutParams) { - final ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)lp; - mlp.setMargins(mlp.leftMargin + dx, mlp.topMargin + dy, 0, 0); - } - } - private static float getTextScaleX(CharSequence text, int maxWidth, TextPaint paint) { paint.setTextScaleX(1.0f); final int width = getTextWidth(text, paint); @@ -730,25 +622,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo } } - private void expandCandidatesPane() { - mCandidatesPaneContainer.setMinimumHeight(mKeyboardView.getMeasuredHeight()); - mCandidatesPaneContainer.setVisibility(VISIBLE); - mKeyboardView.setVisibility(GONE); - } - - private void closeCandidatesPane() { - mCandidatesPaneContainer.setVisibility(GONE); - mKeyboardView.setVisibility(VISIBLE); - } - - private void toggleCandidatesPane() { - if (mCandidatesPaneContainer.getVisibility() == VISIBLE) { - closeCandidatesPane(); - } else { - expandCandidatesPane(); - } - } - public void onAutoCorrectionInverted(CharSequence autoCorrectedWord) { final CharSequence inverted = mStripParams.getInvertedText(autoCorrectedWord); if (inverted == null) @@ -785,8 +658,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo mCandidatesPlacer.removeAllViews(); mCandidatesPlacer.addView(mCandidatesStrip); mCandidatesStrip.removeAllViews(); - mCandidatesPane.removeAllViews(); - closeCandidatesPane(); + mMoreSuggestionsWindow.dismiss(); } private void hidePreview() { @@ -823,16 +695,103 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo } } + private final KeyboardActionListener mMoreSuggestionsListener = + new KeyboardActionListener.Adapter() { + @Override + public boolean onCustomRequest(int requestCode) { + final int index = requestCode; + final CharSequence word = mSuggestions.getWord(index); + mListener.pickSuggestionManually(index, word); + mMoreSuggestionsView.dismissMoreKeysPanel(); + return true; + } + + @Override + public void onCancelInput() { + mMoreSuggestionsView.dismissMoreKeysPanel(); + } + }; + + private final MoreKeysPanel.Controller mMoreSuggestionsController = + new MoreKeysPanel.Controller() { + @Override + public boolean dismissMoreKeysPanel() { + if (mMoreSuggestionsWindow.isShowing()) { + mMoreSuggestionsWindow.dismiss(); + return true; + } + return false; + } + }; + @Override public boolean onLongClick(View view) { - if (mStripParams.mMoreSuggestionsAvailable) { - toggleCandidatesPane(); + final SuggestionsStripParams params = mStripParams; + if (params.mMoreSuggestionsAvailable) { + final int stripWidth = getWidth(); + final View container = mMoreSuggestionsContainer; + final int maxWidth = stripWidth - container.getPaddingLeft() + - container.getPaddingRight(); + final DisplayMetrics dm = getContext().getResources().getDisplayMetrics(); + // TODO: Revise how we determine the height + final int maxHeight = dm.heightPixels - mKeyboardView.getHeight() - getHeight() * 3; + final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder; + builder.layout(mSuggestions, params.mCandidateCountInStrip, maxWidth, maxHeight); + mMoreSuggestionsView.setKeyboard(builder.build()); + container.measure( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + + final MoreKeysPanel moreKeysPanel = mMoreSuggestionsView; + final int pointX = stripWidth / 2; + final int pointY = 0; + moreKeysPanel.showMoreKeysPanel( + this, mMoreSuggestionsController, pointX, pointY, + mMoreSuggestionsWindow, mMoreSuggestionsListener); + // TODO: Should figure out how to select the pointer tracker correctly. + final PointerTracker tracker = PointerTracker.getPointerTracker(0, moreKeysPanel); + final int translatedX = moreKeysPanel.translateX(tracker.getLastX()); + final int translatedY = moreKeysPanel.translateY(tracker.getLastY()); + tracker.onShowMoreKeysPanel( + translatedX, translatedY, SystemClock.uptimeMillis(), moreKeysPanel); + view.setPressed(false); + // TODO: Should gray out the keyboard here as well? return true; } return false; } @Override + public boolean dispatchTouchEvent(MotionEvent me) { + if (!mMoreSuggestionsWindow.isShowing()) { + return super.dispatchTouchEvent(me); + } + final int action = me.getAction(); + final long eventTime = me.getEventTime(); + final int index = me.getActionIndex(); + final int id = me.getPointerId(index); + final PointerTracker tracker = PointerTracker.getPointerTracker(id, mMoreSuggestionsView); + final int x = mMoreSuggestionsView.translateX((int)me.getX(index)); + final int y = mMoreSuggestionsView.translateY((int)me.getY(index)); + switch (action) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_POINTER_DOWN: + tracker.onDownEvent(x, y, eventTime, mMoreSuggestionsView); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_POINTER_UP: + tracker.onUpEvent(x, y, eventTime); + break; + case MotionEvent.ACTION_MOVE: + tracker.onMoveEvent(x, y, eventTime); + break; + case MotionEvent.ACTION_CANCEL: + tracker.onCancelEvent(x, y, eventTime); + break; + } + return true; + } + + @Override public void onClick(View view) { if (view == mStripParams.mWordToSaveView) { addToDictionary((CharSequence)view.getTag()); @@ -840,11 +799,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo return; } - if (view == mCandidatesPane) { - closeCandidatesPane(); - return; - } - final Object tag = view.getTag(); if (!(tag instanceof Integer)) return; @@ -854,9 +808,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo final CharSequence word = mSuggestions.getWord(index); mListener.pickSuggestionManually(index, word); - // Because some punctuation letters are not treated as word separator depending on locale, - // {@link #setSuggestions} might not be called and candidates pane left opened. - closeCandidatesPane(); } @Override |