diff options
author | 2011-06-14 16:28:57 +0900 | |
---|---|---|
committer | 2011-06-14 20:40:56 +0900 | |
commit | 86e815a142c8aa13213151e381a8a24ef23073d3 (patch) | |
tree | 10d9b1f4c1293f58f1d1a5ef14ab08be71232867 /java/src | |
parent | 90cb2e6296726960b12e622ffa2b30c5ff92a079 (diff) | |
download | latinime-86e815a142c8aa13213151e381a8a24ef23073d3.tar.gz latinime-86e815a142c8aa13213151e381a8a24ef23073d3.tar.xz latinime-86e815a142c8aa13213151e381a8a24ef23073d3.zip |
Implement expandable candidates pane
This change removes horizontal scroll from candidates strip. Instead
of that this change introduces "fixed 3 items candidates strip" and
"expandable candidates pane".
Bug: 4175031
Change-Id: Ia367d9074436fdea76d3b653d81798ce2749170e
Diffstat (limited to 'java/src')
4 files changed, 160 insertions, 26 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index 7c68c93f2..8e9c7ef7e 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -57,6 +57,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha private SubtypeSwitcher mSubtypeSwitcher; private SharedPreferences mPrefs; + private View mCurrentInputView; private LatinKeyboardView mKeyboardView; private LatinIME mInputMethodService; @@ -294,7 +295,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha } public boolean isInputViewShown() { - return mKeyboardView != null && mKeyboardView.isShown(); + return mCurrentInputView != null && mCurrentInputView.isShown(); } public boolean isKeyboardAvailable() { @@ -714,9 +715,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha return createInputView(mThemeIndex, true); } - // Instance variable only for {@link #createInputView(int, boolean)}. - private View mCurrentInputView; - private View createInputView(final int newThemeIndex, final boolean forceRecreate) { if (mCurrentInputView != null && mThemeIndex == newThemeIndex && !forceRecreate) return mCurrentInputView; diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java index b4f6b2c91..5ef1d7503 100644 --- a/java/src/com/android/inputmethod/latin/CandidateView.java +++ b/java/src/com/android/inputmethod/latin/CandidateView.java @@ -56,13 +56,23 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD); private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan(); - private static final int MAX_SUGGESTIONS = 16; + // The maximum number of suggestions available. See {@link Suggest#mPrefMaxSuggestions}. + private static final int MAX_SUGGESTIONS = 18; + private static final int UNSPECIFIED_MEASURESPEC = MeasureSpec.makeMeasureSpec( + 0, MeasureSpec.UNSPECIFIED); private static final boolean DBG = LatinImeLogger.sDBG; + private static final int NUM_CANDIDATES_IN_STRIP = 3; + private final View mExpandCandidatesPane; + private final View mCloseCandidatesPane; + private ViewGroup mCandidatesPane; + private ViewGroup mCandidatesPaneContainer; + private View mKeyboardView; private final ArrayList<TextView> mWords = new ArrayList<TextView>(); private final ArrayList<View> mDividers = new ArrayList<View>(); private final int mCandidatePadding; + private final int mCandidateStripHeight; private final boolean mConfigCandidateHighlightFontColorEnabled; private final CharacterStyle mInvertedForegroundColorSpan; private final CharacterStyle mInvertedBackgroundColorSpan; @@ -132,8 +142,10 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo super(context, attrs); Resources res = context.getResources(); - mPreviewPopup = new PopupWindow(context); LayoutInflater inflater = LayoutInflater.from(context); + inflater.inflate(R.layout.candidates_strip, this); + + mPreviewPopup = new PopupWindow(context); mPreviewText = (TextView) inflater.inflate(R.layout.candidate_preview, null); mPreviewPopup.setWindowLayoutMode(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); @@ -148,8 +160,26 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo mInvertedBackgroundColorSpan = new BackgroundColorSpan(mColorTypedWord); mCandidatePadding = res.getDimensionPixelOffset(R.dimen.candidate_padding); + mCandidateStripHeight = res.getDimensionPixelOffset(R.dimen.candidate_strip_height); for (int i = 0; i < MAX_SUGGESTIONS; i++) { - final TextView tv = (TextView)inflater.inflate(R.layout.candidate, null); + final TextView tv; + switch (i) { + case 0: + tv = (TextView)findViewById(R.id.candidate_left); + tv.setPadding(mCandidatePadding, 0, 0, 0); + break; + case 1: + tv = (TextView)findViewById(R.id.candidate_center); + break; + case 2: + tv = (TextView)findViewById(R.id.candidate_right); + break; + default: + tv = (TextView)inflater.inflate(R.layout.candidate, null); + break; + } + if (i < NUM_CANDIDATES_IN_STRIP) + setLayoutWeight(tv, 1.0f); tv.setTag(i); tv.setOnClickListener(this); if (i == 0) @@ -157,19 +187,38 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo mWords.add(tv); if (i > 0) { final View divider = inflater.inflate(R.layout.candidate_divider, null); + divider.measure(UNSPECIFIED_MEASURESPEC, UNSPECIFIED_MEASURESPEC); mDividers.add(divider); } } - scrollTo(0, getScrollY()); + mExpandCandidatesPane = findViewById(R.id.expand_candidates_pane); + mExpandCandidatesPane.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + expandCandidatesPane(); + } + }); + mCloseCandidatesPane = findViewById(R.id.close_candidates_pane); + mCloseCandidatesPane.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + closeCandidatesPane(); + } + }); } /** * A connection back to the input method. * @param listener */ - public void setListener(Listener listener) { + public void setListener(Listener listener, View inputView) { mListener = listener; + mKeyboardView = inputView.findViewById(R.id.keyboard_view); + mCandidatesPane = (ViewGroup)inputView.findViewById(R.id.candidates_pane); + mCandidatesPane.setOnClickListener(this); + mCandidatesPaneContainer = (ViewGroup)inputView.findViewById( + R.id.candidates_pane_container); } public void setSuggestions(SuggestedWords suggestions) { @@ -183,6 +232,15 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo } } + private static void setLayoutWeight(View v, float weight) { + ViewGroup.LayoutParams lp = v.getLayoutParams(); + if (lp instanceof LinearLayout.LayoutParams) { + LinearLayout.LayoutParams llp = (LinearLayout.LayoutParams)lp; + llp.width = 0; + llp.weight = weight; + } + } + private CharSequence getStyledCandidateWord(CharSequence word, boolean isAutoCorrect) { if (!isAutoCorrect) return word; @@ -216,7 +274,14 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo final List<SuggestedWordInfo> suggestedWordInfoList = suggestions.mSuggestedWordInfoList; clear(); + final int paneWidth = getWidth(); + final int dividerWidth = mDividers.get(0).getMeasuredWidth(); + int x = 0; + int y = 0; + int fromIndex = NUM_CANDIDATES_IN_STRIP; final int count = Math.min(mWords.size(), suggestions.size()); + closeCandidatesPane(); + mExpandCandidatesPane.setEnabled(count >= NUM_CANDIDATES_IN_STRIP); for (int i = 0; i < count; i++) { final CharSequence word = suggestions.getWord(i); if (word == null) continue; @@ -233,33 +298,91 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo final boolean isPunctuationSuggestions = (word.length() == 1 && count > 1); final TextView tv = mWords.get(i); + // TODO: Reorder candidates in strip as appropriate. The center candidate should hold + // the word when space is typed (valid typed word or auto corrected word). tv.setTextColor(getCandidateTextColor(isAutoCorrect, isSuggestedCandidate || isPunctuationSuggestions, info)); tv.setText(getStyledCandidateWord(word, isAutoCorrect)); - if (i == 0) { - tv.setPadding(mCandidatePadding, 0, 0, 0); - } else if (i == count - 1) { - tv.setPadding(0, 0, mCandidatePadding, 0); - } else { - tv.setPadding(0, 0, 0, 0); + // TODO: call TextView.setTextScaleX() to fit the candidate in single line. + if (i >= NUM_CANDIDATES_IN_STRIP) { + tv.measure(UNSPECIFIED_MEASURESPEC, UNSPECIFIED_MEASURESPEC); + final int width = tv.getMeasuredWidth(); + // TODO: Handle overflow case. + if (dividerWidth + x + width >= paneWidth) { + centeringCandidates(fromIndex, i - 1, x, paneWidth); + x = 0; + y += mCandidateStripHeight; + fromIndex = i; + } + if (x != 0) { + final View divider = mDividers.get(i - NUM_CANDIDATES_IN_STRIP); + mCandidatesPane.addView(divider); + placeCandidateAt(divider, x, y); + x += dividerWidth; + } + mCandidatesPane.addView(tv); + placeCandidateAt(tv, x, y); + x += width; } - if (i > 0) - addView(mDividers.get(i - 1)); - addView(tv); if (DBG && info != null) { final TextView dv = new TextView(getContext(), null); dv.setTextSize(10.0f); dv.setTextColor(0xff808080); dv.setText(info.getDebugString()); - addView(dv); + // TODO: debug view for candidate strip needed. + mCandidatesPane.addView(dv); LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)dv.getLayoutParams(); lp.gravity = Gravity.BOTTOM; } } + if (x != 0) { + // Centering last candidates row. + centeringCandidates(fromIndex, count - 1, x, paneWidth); + } + } + + private void placeCandidateAt(View v, int x, int y) { + ViewGroup.LayoutParams lp = v.getLayoutParams(); + if (lp instanceof ViewGroup.MarginLayoutParams) { + ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)lp; + mlp.width = v.getMeasuredWidth(); + mlp.height = v.getMeasuredHeight(); + mlp.setMargins(x, y + (mCandidateStripHeight - mlp.height) / 2, 0, 0); + } + } + + private void centeringCandidates(int from, int to, int width, int paneWidth) { + final ViewGroup pane = mCandidatesPane; + final int fromIndex = pane.indexOfChild(mWords.get(from)); + final int toIndex = pane.indexOfChild(mWords.get(to)); + final int offset = (paneWidth - width) / 2; + for (int index = fromIndex; index <= toIndex; index++) { + offsetMargin(pane.getChildAt(index), offset, 0); + } + } + + private static void offsetMargin(View v, int dx, int dy) { + ViewGroup.LayoutParams lp = v.getLayoutParams(); + if (lp instanceof ViewGroup.MarginLayoutParams) { + ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)lp; + mlp.setMargins(mlp.leftMargin + dx, mlp.topMargin + dy, 0, 0); + } + } + + private void expandCandidatesPane() { + mExpandCandidatesPane.setVisibility(View.GONE); + mCloseCandidatesPane.setVisibility(View.VISIBLE); + mCandidatesPaneContainer.setMinimumHeight(mKeyboardView.getMeasuredHeight()); + mCandidatesPaneContainer.setVisibility(View.VISIBLE); + mKeyboardView.setVisibility(View.GONE); + } - scrollTo(0, getScrollY()); - requestLayout(); + private void closeCandidatesPane() { + mExpandCandidatesPane.setVisibility(View.VISIBLE); + mCloseCandidatesPane.setVisibility(View.GONE); + mCandidatesPaneContainer.setVisibility(View.GONE); + mKeyboardView.setVisibility(View.VISIBLE); } public void onAutoCorrectionInverted(CharSequence autoCorrectedWord) { @@ -310,7 +433,9 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo public void clear() { mShowingAddToDictionary = false; mShowingAutoCorrectionInverted = false; - removeAllViews(); + for (int i = 0; i < NUM_CANDIDATES_IN_STRIP; i++) + mWords.get(i).setText(null); + mCandidatesPane.removeAllViews(); } private void hidePreview() { @@ -349,9 +474,13 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo @Override public boolean onLongClick(View view) { - final int index = (Integer) view.getTag(); + final Object tag = view.getTag(); + if (!(tag instanceof Integer)) + return true; + final int index = (Integer) tag; if (index >= mSuggestions.size()) return true; + final CharSequence word = mSuggestions.getWord(index); if (word.length() < 2) return false; @@ -361,15 +490,22 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo @Override public void onClick(View view) { - final int index = (Integer) view.getTag(); + final Object tag = view.getTag(); + if (!(tag instanceof Integer)) + return; + final int index = (Integer) tag; if (index >= mSuggestions.size()) return; + final CharSequence word = mSuggestions.getWord(index); if (mShowingAddToDictionary && index == 0) { addToDictionary(word); } else { 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 diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 940f6b835..75bca9937 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -502,7 +502,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar super.setInputView(view); mCandidateViewContainer = view.findViewById(R.id.candidates_container); mCandidateView = (CandidateView) view.findViewById(R.id.candidates); - mCandidateView.setListener(this); + mCandidateView.setListener(this, view); mCandidateStripHeight = (int)mResources.getDimension(R.dimen.candidate_strip_height); } diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 33f9820cc..62788fb9e 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -84,7 +84,7 @@ public class Suggest implements Dictionary.WordCallback { private final Map<String, Dictionary> mUnigramDictionaries = new HashMap<String, Dictionary>(); private final Map<String, Dictionary> mBigramDictionaries = new HashMap<String, Dictionary>(); - private int mPrefMaxSuggestions = 12; + private int mPrefMaxSuggestions = 18; private static final int PREF_MAX_BIGRAMS = 60; |