From 9d2f606aa8df37de7c38c26b37afb4496ee0e2fc Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Fri, 19 Sep 2014 17:48:50 +0900 Subject: [PATCH] Avoid the add-to-dictionary indicator from being clipped With this CL, the display bounds is taken into consideration when the location of add-to-dictionary indicator is determined. BUG: 17578360 Change-Id: I31e458fa7bbc33e539578b331fe1c51ff7f8668e --- .../inputmethod/keyboard/TextDecorator.java | 22 +++------- .../inputmethod/keyboard/TextDecoratorUi.java | 42 +++++++++++++++---- .../keyboard/TextDecoratorUiOperator.java | 6 +-- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/java/src/com/android/inputmethod/keyboard/TextDecorator.java b/java/src/com/android/inputmethod/keyboard/TextDecorator.java index 315d36313..6e4e3281e 100644 --- a/java/src/com/android/inputmethod/keyboard/TextDecorator.java +++ b/java/src/com/android/inputmethod/keyboard/TextDecorator.java @@ -49,7 +49,7 @@ public class TextDecorator { private int mMode = MODE_MONITOR; private String mLastComposingText = null; - private RectF mIndicatorBoundsForLastComposingText = new RectF(); + private boolean mHasRtlCharsInLastComposingText = false; private RectF mComposingTextBoundsForLastComposingText = new RectF(); private boolean mIsFullScreenMode = false; @@ -241,20 +241,8 @@ public class TextDecorator { right = Math.max(characterBounds.right, right); } mLastComposingText = composingTextString; + mHasRtlCharsInLastComposingText = useRtlLayout; mComposingTextBoundsForLastComposingText.set(left, top, right, bottom); - // The height and width of the indicator is the same as the height of the composing - // text. - final float indicatorSize = bottom - top; - mIndicatorBoundsForLastComposingText.set(0.0f, 0.0f, indicatorSize, indicatorSize); - // The horizontal position of the indicator depends on the text direction. - final float indicatorTop = top; - final float indicatorLeft; - if (useRtlLayout) { - indicatorLeft = left - indicatorSize; - } else { - indicatorLeft = right; - } - mIndicatorBoundsForLastComposingText.offset(indicatorLeft, indicatorTop); } final int selectionStart = info.getSelectionStart(); @@ -295,8 +283,8 @@ public class TextDecorator { return; } - mUiOperator.layoutUi(matrix, mIndicatorBoundsForLastComposingText, - mComposingTextBoundsForLastComposingText); + mUiOperator.layoutUi(matrix, mComposingTextBoundsForLastComposingText, + mHasRtlCharsInLastComposingText); } private void onClickIndicator() { @@ -374,7 +362,7 @@ public class TextDecorator { public void setOnClickListener(Runnable listener) { } @Override - public void layoutUi(Matrix matrix, RectF indicatorBounds, RectF composingTextBounds) { + public void layoutUi(Matrix matrix, RectF composingTextBounds, boolean useRtlLayout) { } }; } diff --git a/java/src/com/android/inputmethod/keyboard/TextDecoratorUi.java b/java/src/com/android/inputmethod/keyboard/TextDecoratorUi.java index b67d17789..d87dc1bfa 100644 --- a/java/src/com/android/inputmethod/keyboard/TextDecoratorUi.java +++ b/java/src/com/android/inputmethod/keyboard/TextDecoratorUi.java @@ -26,6 +26,7 @@ import android.graphics.Path; import android.graphics.RectF; import android.graphics.drawable.ColorDrawable; import android.inputmethodservice.InputMethodService; +import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.Gravity; import android.view.View; @@ -50,6 +51,7 @@ public final class TextDecoratorUi implements TextDecoratorUiOperator { private final PopupWindow mTouchEventWindow; private final View mTouchEventWindowClickListenerView; private final float mHitAreaMarginInPixels; + private final RectF mDisplayRect; /** * This constructor is designed to be called from {@link InputMethodService#setInputView(View)}. @@ -64,6 +66,9 @@ public final class TextDecoratorUi implements TextDecoratorUiOperator { R.integer.text_decorator_hit_area_margin_in_dp); mHitAreaMarginInPixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, hitAreaMarginInDP, resources.getDisplayMetrics()); + final DisplayMetrics displayMetrics = resources.getDisplayMetrics(); + mDisplayRect = new RectF(0.0f, 0.0f, displayMetrics.widthPixels, + displayMetrics.heightPixels); mLocalRootView = new RelativeLayout(context); mLocalRootView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, @@ -111,17 +116,40 @@ public final class TextDecoratorUi implements TextDecoratorUiOperator { mTouchEventWindow.dismiss(); } + private static final RectF getIndicatorBoundsInScreenCoordinates(final Matrix matrix, + final RectF composingTextBounds, final boolean showAtLeftSide) { + final float indicatorSize = composingTextBounds.height(); + final RectF indicatorBounds; + if (showAtLeftSide) { + indicatorBounds = new RectF(composingTextBounds.left - indicatorSize, + composingTextBounds.top, composingTextBounds.left, + composingTextBounds.top + indicatorSize); + } else { + indicatorBounds = new RectF(composingTextBounds.right, composingTextBounds.top, + composingTextBounds.right + indicatorSize, + composingTextBounds.top + indicatorSize); + } + matrix.mapRect(indicatorBounds); + return indicatorBounds; + } + @Override - public void layoutUi(final Matrix matrix, final RectF indicatorBounds, - final RectF composingTextBounds) { - final RectF indicatorBoundsInScreenCoordinates = new RectF(); - matrix.mapRect(indicatorBoundsInScreenCoordinates, indicatorBounds); + public void layoutUi(final Matrix matrix, final RectF composingTextBounds, + final boolean useRtlLayout) { + RectF indicatorBoundsInScreenCoordinates = getIndicatorBoundsInScreenCoordinates(matrix, + composingTextBounds, useRtlLayout /* showAtLeftSide */); + if (indicatorBoundsInScreenCoordinates.left < mDisplayRect.left || + mDisplayRect.right < indicatorBoundsInScreenCoordinates.right) { + // The indicator is clipped by the screen. Show the indicator at the opposite side. + indicatorBoundsInScreenCoordinates = getIndicatorBoundsInScreenCoordinates(matrix, + composingTextBounds, !useRtlLayout /* showAtLeftSide */); + } + mAddToDictionaryIndicatorView.setBounds(indicatorBoundsInScreenCoordinates); - final RectF hitAreaBounds = new RectF(composingTextBounds); - hitAreaBounds.union(indicatorBounds); final RectF hitAreaBoundsInScreenCoordinates = new RectF(); - matrix.mapRect(hitAreaBoundsInScreenCoordinates, hitAreaBounds); + matrix.mapRect(hitAreaBoundsInScreenCoordinates, composingTextBounds); + hitAreaBoundsInScreenCoordinates.union(indicatorBoundsInScreenCoordinates); hitAreaBoundsInScreenCoordinates.inset(-mHitAreaMarginInPixels, -mHitAreaMarginInPixels); final int[] originScreen = new int[2]; diff --git a/java/src/com/android/inputmethod/keyboard/TextDecoratorUiOperator.java b/java/src/com/android/inputmethod/keyboard/TextDecoratorUiOperator.java index 9c0b64ad4..9e30e417e 100644 --- a/java/src/com/android/inputmethod/keyboard/TextDecoratorUiOperator.java +++ b/java/src/com/android/inputmethod/keyboard/TextDecoratorUiOperator.java @@ -17,7 +17,6 @@ package com.android.inputmethod.keyboard; import android.graphics.Matrix; -import android.graphics.PointF; import android.graphics.RectF; /** @@ -45,9 +44,8 @@ public interface TextDecoratorUiOperator { /** * Called when the layout should be updated. * @param matrix The matrix that transforms the local coordinates into the screen coordinates. - * @param indicatorBounds The bounding box of the indicator, in local coordinates. * @param composingTextBounds The bounding box of the composing text, in local coordinates. + * @param useRtlLayout {@code true} if the indicator should be optimized for RTL layout. */ - void layoutUi(final Matrix matrix, final RectF indicatorBounds, - final RectF composingTextBounds); + void layoutUi(final Matrix matrix, final RectF composingTextBounds, final boolean useRtlLayout); }