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: Ia367d9074436fdea76d3b653d81798ce2749170emain
parent
90cb2e6296
commit
86e815a142
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 713 B |
Binary file not shown.
After Width: | Height: | Size: 681 B |
|
@ -0,0 +1,61 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/*
|
||||||
|
**
|
||||||
|
** Copyright 2011, 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 License for the specific language governing permissions and
|
||||||
|
** limitations under the License.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
|
||||||
|
<merge
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||||
|
>
|
||||||
|
<include
|
||||||
|
android:id="@+id/candidate_left"
|
||||||
|
layout="@layout/candidate" />
|
||||||
|
<include
|
||||||
|
layout="@layout/candidate_divider" />
|
||||||
|
<include
|
||||||
|
android:id="@+id/candidate_center"
|
||||||
|
layout="@layout/candidate" />
|
||||||
|
<include
|
||||||
|
layout="@layout/candidate_divider" />
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_weight="1.0"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
>
|
||||||
|
<include
|
||||||
|
android:id="@+id/candidate_right"
|
||||||
|
layout="@layout/candidate" />
|
||||||
|
<!-- TODO: These images' drawable must be determined depending on theme. -->
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/expand_candidates_pane"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/btn_expand_candidates_pane"
|
||||||
|
android:visibility="gone"
|
||||||
|
style="?attr/suggestionBackgroundStyle" />
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/close_candidates_pane"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/btn_close_candidates_pane"
|
||||||
|
android:visibility="gone"
|
||||||
|
style="?attr/suggestionBackgroundStyle" />
|
||||||
|
</LinearLayout>
|
||||||
|
</merge>
|
|
@ -32,32 +32,47 @@
|
||||||
android:id="@+id/candidates_container"
|
android:id="@+id/candidates_container"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="@dimen/candidate_strip_minimum_height"
|
||||||
style="?attr/suggestionsStripBackgroundStyle"
|
android:gravity="bottom"
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
android:layout_width="@dimen/candidate_strip_padding"
|
android:layout_width="@dimen/candidate_strip_padding"
|
||||||
android:layout_height="@dimen/candidate_strip_height"
|
android:layout_height="@dimen/candidate_strip_height"
|
||||||
style="?attr/suggestionsStripBackgroundStyle" />
|
style="?attr/suggestionsStripBackgroundStyle" />
|
||||||
<HorizontalScrollView
|
<com.android.inputmethod.latin.CandidateView
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/candidates"
|
||||||
android:layout_height="wrap_content"
|
android:layout_weight="1.0"
|
||||||
android:fadingEdge="horizontal"
|
android:layout_width="0dp"
|
||||||
android:fadingEdgeLength="@dimen/candidate_strip_fading_edge_length"
|
android:layout_height="@dimen/candidate_strip_height"
|
||||||
android:scrollbars="none"
|
android:gravity="center_vertical"
|
||||||
>
|
style="?attr/suggestionsStripBackgroundStyle" />
|
||||||
<com.android.inputmethod.latin.CandidateView
|
|
||||||
android:id="@+id/candidates"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="@dimen/candidate_strip_height"
|
|
||||||
android:gravity="center_vertical" />
|
|
||||||
</HorizontalScrollView>
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="@dimen/candidate_strip_padding"
|
android:layout_width="@dimen/candidate_strip_padding"
|
||||||
android:layout_height="@dimen/candidate_strip_height"
|
android:layout_height="@dimen/candidate_strip_height"
|
||||||
style="?attr/suggestionsStripBackgroundStyle" />
|
style="?attr/suggestionsStripBackgroundStyle" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/candidates_pane_container"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
|
style="?attr/suggestionsStripBackgroundStyle"
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
android:layout_width="@dimen/candidate_strip_padding"
|
||||||
|
android:layout_height="@dimen/candidate_strip_height" />
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/candidates_pane"
|
||||||
|
android:layout_weight="1.0"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
<View
|
||||||
|
android:layout_width="@dimen/candidate_strip_padding"
|
||||||
|
android:layout_height="@dimen/candidate_strip_height" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<com.android.inputmethod.keyboard.LatinKeyboardView
|
<com.android.inputmethod.keyboard.LatinKeyboardView
|
||||||
android:id="@+id/keyboard_view"
|
android:id="@+id/keyboard_view"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
|
|
|
@ -57,6 +57,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
private SubtypeSwitcher mSubtypeSwitcher;
|
private SubtypeSwitcher mSubtypeSwitcher;
|
||||||
private SharedPreferences mPrefs;
|
private SharedPreferences mPrefs;
|
||||||
|
|
||||||
|
private View mCurrentInputView;
|
||||||
private LatinKeyboardView mKeyboardView;
|
private LatinKeyboardView mKeyboardView;
|
||||||
private LatinIME mInputMethodService;
|
private LatinIME mInputMethodService;
|
||||||
|
|
||||||
|
@ -294,7 +295,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInputViewShown() {
|
public boolean isInputViewShown() {
|
||||||
return mKeyboardView != null && mKeyboardView.isShown();
|
return mCurrentInputView != null && mCurrentInputView.isShown();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isKeyboardAvailable() {
|
public boolean isKeyboardAvailable() {
|
||||||
|
@ -714,9 +715,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
return createInputView(mThemeIndex, true);
|
return createInputView(mThemeIndex, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instance variable only for {@link #createInputView(int, boolean)}.
|
|
||||||
private View mCurrentInputView;
|
|
||||||
|
|
||||||
private View createInputView(final int newThemeIndex, final boolean forceRecreate) {
|
private View createInputView(final int newThemeIndex, final boolean forceRecreate) {
|
||||||
if (mCurrentInputView != null && mThemeIndex == newThemeIndex && !forceRecreate)
|
if (mCurrentInputView != null && mThemeIndex == newThemeIndex && !forceRecreate)
|
||||||
return mCurrentInputView;
|
return mCurrentInputView;
|
||||||
|
|
|
@ -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 BOLD_SPAN = new StyleSpan(Typeface.BOLD);
|
||||||
private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
|
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 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<TextView> mWords = new ArrayList<TextView>();
|
||||||
private final ArrayList<View> mDividers = new ArrayList<View>();
|
private final ArrayList<View> mDividers = new ArrayList<View>();
|
||||||
private final int mCandidatePadding;
|
private final int mCandidatePadding;
|
||||||
|
private final int mCandidateStripHeight;
|
||||||
private final boolean mConfigCandidateHighlightFontColorEnabled;
|
private final boolean mConfigCandidateHighlightFontColorEnabled;
|
||||||
private final CharacterStyle mInvertedForegroundColorSpan;
|
private final CharacterStyle mInvertedForegroundColorSpan;
|
||||||
private final CharacterStyle mInvertedBackgroundColorSpan;
|
private final CharacterStyle mInvertedBackgroundColorSpan;
|
||||||
|
@ -132,8 +142,10 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
|
|
||||||
Resources res = context.getResources();
|
Resources res = context.getResources();
|
||||||
mPreviewPopup = new PopupWindow(context);
|
|
||||||
LayoutInflater inflater = LayoutInflater.from(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);
|
mPreviewText = (TextView) inflater.inflate(R.layout.candidate_preview, null);
|
||||||
mPreviewPopup.setWindowLayoutMode(ViewGroup.LayoutParams.WRAP_CONTENT,
|
mPreviewPopup.setWindowLayoutMode(ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT);
|
ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
@ -148,8 +160,26 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
|
||||||
mInvertedBackgroundColorSpan = new BackgroundColorSpan(mColorTypedWord);
|
mInvertedBackgroundColorSpan = new BackgroundColorSpan(mColorTypedWord);
|
||||||
|
|
||||||
mCandidatePadding = res.getDimensionPixelOffset(R.dimen.candidate_padding);
|
mCandidatePadding = res.getDimensionPixelOffset(R.dimen.candidate_padding);
|
||||||
|
mCandidateStripHeight = res.getDimensionPixelOffset(R.dimen.candidate_strip_height);
|
||||||
for (int i = 0; i < MAX_SUGGESTIONS; i++) {
|
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.setTag(i);
|
||||||
tv.setOnClickListener(this);
|
tv.setOnClickListener(this);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
|
@ -157,19 +187,38 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
|
||||||
mWords.add(tv);
|
mWords.add(tv);
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
final View divider = inflater.inflate(R.layout.candidate_divider, null);
|
final View divider = inflater.inflate(R.layout.candidate_divider, null);
|
||||||
|
divider.measure(UNSPECIFIED_MEASURESPEC, UNSPECIFIED_MEASURESPEC);
|
||||||
mDividers.add(divider);
|
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.
|
* A connection back to the input method.
|
||||||
* @param listener
|
* @param listener
|
||||||
*/
|
*/
|
||||||
public void setListener(Listener listener) {
|
public void setListener(Listener listener, View inputView) {
|
||||||
mListener = listener;
|
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) {
|
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) {
|
private CharSequence getStyledCandidateWord(CharSequence word, boolean isAutoCorrect) {
|
||||||
if (!isAutoCorrect)
|
if (!isAutoCorrect)
|
||||||
return word;
|
return word;
|
||||||
|
@ -216,7 +274,14 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
|
||||||
final List<SuggestedWordInfo> suggestedWordInfoList = suggestions.mSuggestedWordInfoList;
|
final List<SuggestedWordInfo> suggestedWordInfoList = suggestions.mSuggestedWordInfoList;
|
||||||
|
|
||||||
clear();
|
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());
|
final int count = Math.min(mWords.size(), suggestions.size());
|
||||||
|
closeCandidatesPane();
|
||||||
|
mExpandCandidatesPane.setEnabled(count >= NUM_CANDIDATES_IN_STRIP);
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
final CharSequence word = suggestions.getWord(i);
|
final CharSequence word = suggestions.getWord(i);
|
||||||
if (word == null) continue;
|
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 boolean isPunctuationSuggestions = (word.length() == 1 && count > 1);
|
||||||
|
|
||||||
final TextView tv = mWords.get(i);
|
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,
|
tv.setTextColor(getCandidateTextColor(isAutoCorrect,
|
||||||
isSuggestedCandidate || isPunctuationSuggestions, info));
|
isSuggestedCandidate || isPunctuationSuggestions, info));
|
||||||
tv.setText(getStyledCandidateWord(word, isAutoCorrect));
|
tv.setText(getStyledCandidateWord(word, isAutoCorrect));
|
||||||
if (i == 0) {
|
// TODO: call TextView.setTextScaleX() to fit the candidate in single line.
|
||||||
tv.setPadding(mCandidatePadding, 0, 0, 0);
|
if (i >= NUM_CANDIDATES_IN_STRIP) {
|
||||||
} else if (i == count - 1) {
|
tv.measure(UNSPECIFIED_MEASURESPEC, UNSPECIFIED_MEASURESPEC);
|
||||||
tv.setPadding(0, 0, mCandidatePadding, 0);
|
final int width = tv.getMeasuredWidth();
|
||||||
} else {
|
// TODO: Handle overflow case.
|
||||||
tv.setPadding(0, 0, 0, 0);
|
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) {
|
if (DBG && info != null) {
|
||||||
final TextView dv = new TextView(getContext(), null);
|
final TextView dv = new TextView(getContext(), null);
|
||||||
dv.setTextSize(10.0f);
|
dv.setTextSize(10.0f);
|
||||||
dv.setTextColor(0xff808080);
|
dv.setTextColor(0xff808080);
|
||||||
dv.setText(info.getDebugString());
|
dv.setText(info.getDebugString());
|
||||||
addView(dv);
|
// TODO: debug view for candidate strip needed.
|
||||||
|
mCandidatesPane.addView(dv);
|
||||||
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)dv.getLayoutParams();
|
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)dv.getLayoutParams();
|
||||||
lp.gravity = Gravity.BOTTOM;
|
lp.gravity = Gravity.BOTTOM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (x != 0) {
|
||||||
|
// Centering last candidates row.
|
||||||
|
centeringCandidates(fromIndex, count - 1, x, paneWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
scrollTo(0, getScrollY());
|
private void placeCandidateAt(View v, int x, int y) {
|
||||||
requestLayout();
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void closeCandidatesPane() {
|
||||||
|
mExpandCandidatesPane.setVisibility(View.VISIBLE);
|
||||||
|
mCloseCandidatesPane.setVisibility(View.GONE);
|
||||||
|
mCandidatesPaneContainer.setVisibility(View.GONE);
|
||||||
|
mKeyboardView.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onAutoCorrectionInverted(CharSequence autoCorrectedWord) {
|
public void onAutoCorrectionInverted(CharSequence autoCorrectedWord) {
|
||||||
|
@ -310,7 +433,9 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
|
||||||
public void clear() {
|
public void clear() {
|
||||||
mShowingAddToDictionary = false;
|
mShowingAddToDictionary = false;
|
||||||
mShowingAutoCorrectionInverted = false;
|
mShowingAutoCorrectionInverted = false;
|
||||||
removeAllViews();
|
for (int i = 0; i < NUM_CANDIDATES_IN_STRIP; i++)
|
||||||
|
mWords.get(i).setText(null);
|
||||||
|
mCandidatesPane.removeAllViews();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void hidePreview() {
|
private void hidePreview() {
|
||||||
|
@ -349,9 +474,13 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onLongClick(View view) {
|
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())
|
if (index >= mSuggestions.size())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
final CharSequence word = mSuggestions.getWord(index);
|
final CharSequence word = mSuggestions.getWord(index);
|
||||||
if (word.length() < 2)
|
if (word.length() < 2)
|
||||||
return false;
|
return false;
|
||||||
|
@ -361,15 +490,22 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
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())
|
if (index >= mSuggestions.size())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
final CharSequence word = mSuggestions.getWord(index);
|
final CharSequence word = mSuggestions.getWord(index);
|
||||||
if (mShowingAddToDictionary && index == 0) {
|
if (mShowingAddToDictionary && index == 0) {
|
||||||
addToDictionary(word);
|
addToDictionary(word);
|
||||||
} else {
|
} else {
|
||||||
mListener.pickSuggestionManually(index, word);
|
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
|
@Override
|
||||||
|
|
|
@ -502,7 +502,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|
||||||
super.setInputView(view);
|
super.setInputView(view);
|
||||||
mCandidateViewContainer = view.findViewById(R.id.candidates_container);
|
mCandidateViewContainer = view.findViewById(R.id.candidates_container);
|
||||||
mCandidateView = (CandidateView) view.findViewById(R.id.candidates);
|
mCandidateView = (CandidateView) view.findViewById(R.id.candidates);
|
||||||
mCandidateView.setListener(this);
|
mCandidateView.setListener(this, view);
|
||||||
mCandidateStripHeight = (int)mResources.getDimension(R.dimen.candidate_strip_height);
|
mCandidateStripHeight = (int)mResources.getDimension(R.dimen.candidate_strip_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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> mUnigramDictionaries = new HashMap<String, Dictionary>();
|
||||||
private final Map<String, Dictionary> mBigramDictionaries = 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;
|
private static final int PREF_MAX_BIGRAMS = 60;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue