Merge "Add a new API CursorAnchorInfo#getTextAppearanceInfo()."
This commit is contained in:
@@ -53362,6 +53362,7 @@ package android.view.inputmethod {
|
||||
method public android.graphics.Matrix getMatrix();
|
||||
method public int getSelectionEnd();
|
||||
method public int getSelectionStart();
|
||||
method @Nullable public android.view.inputmethod.TextAppearanceInfo getTextAppearanceInfo();
|
||||
method @NonNull public java.util.List<android.graphics.RectF> getVisibleLineBounds();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.CursorAnchorInfo> CREATOR;
|
||||
@@ -53382,6 +53383,7 @@ package android.view.inputmethod {
|
||||
method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float, int);
|
||||
method public android.view.inputmethod.CursorAnchorInfo.Builder setMatrix(android.graphics.Matrix);
|
||||
method public android.view.inputmethod.CursorAnchorInfo.Builder setSelectionRange(int, int);
|
||||
method @NonNull public android.view.inputmethod.CursorAnchorInfo.Builder setTextAppearanceInfo(@Nullable android.view.inputmethod.TextAppearanceInfo);
|
||||
}
|
||||
|
||||
public final class DeleteGesture extends android.view.inputmethod.HandwritingGesture implements android.os.Parcelable {
|
||||
@@ -53637,6 +53639,7 @@ package android.view.inputmethod {
|
||||
field public static final int CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS = 8; // 0x8
|
||||
field public static final int CURSOR_UPDATE_FILTER_EDITOR_BOUNDS = 4; // 0x4
|
||||
field public static final int CURSOR_UPDATE_FILTER_INSERTION_MARKER = 16; // 0x10
|
||||
field public static final int CURSOR_UPDATE_FILTER_TEXT_APPEARANCE = 64; // 0x40
|
||||
field public static final int CURSOR_UPDATE_FILTER_VISIBLE_LINE_BOUNDS = 32; // 0x20
|
||||
field public static final int CURSOR_UPDATE_IMMEDIATE = 1; // 0x1
|
||||
field public static final int CURSOR_UPDATE_MONITOR = 2; // 0x2
|
||||
@@ -53940,6 +53943,35 @@ package android.view.inputmethod {
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.SurroundingText> CREATOR;
|
||||
}
|
||||
|
||||
public final class TextAppearanceInfo implements android.os.Parcelable {
|
||||
ctor public TextAppearanceInfo(@NonNull android.widget.TextView);
|
||||
method public int describeContents();
|
||||
method @Nullable public String getFontFamilyName();
|
||||
method @Nullable public String getFontFeatureSettings();
|
||||
method @Nullable public String getFontVariationSettings();
|
||||
method public float getLetterSpacing();
|
||||
method public int getLineBreakStyle();
|
||||
method public int getLineBreakWordStyle();
|
||||
method public int getMaxLength();
|
||||
method @Px public float getShadowDx();
|
||||
method @Px public float getShadowDy();
|
||||
method @Px public float getShadowRadius();
|
||||
method @ColorInt public int getTextColor();
|
||||
method @ColorInt public int getTextColorHighlight();
|
||||
method @ColorInt public int getTextColorHint();
|
||||
method @Nullable public android.content.res.ColorStateList getTextColorLink();
|
||||
method @IntRange(from=0xffffffff, to=android.graphics.fonts.FontStyle.FONT_WEIGHT_MAX) public int getTextFontWeight();
|
||||
method @NonNull public android.os.LocaleList getTextLocales();
|
||||
method public float getTextScaleX();
|
||||
method @Px public float getTextSize();
|
||||
method public int getTextStyle();
|
||||
method public boolean isAllCaps();
|
||||
method public boolean isElegantTextHeight();
|
||||
method public boolean isFallbackLineSpacing();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.TextAppearanceInfo> CREATOR;
|
||||
}
|
||||
|
||||
public final class TextAttribute implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public android.os.PersistableBundle getExtras();
|
||||
|
||||
@@ -20,12 +20,14 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.RectF;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.Layout;
|
||||
import android.text.SpannedString;
|
||||
import android.text.TextUtils;
|
||||
import android.view.inputmethod.SparseRectFArray.SparseRectFArrayBuilder;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -110,7 +112,7 @@ public final class CursorAnchorInfo implements Parcelable {
|
||||
/**
|
||||
* Container of rectangular position of Editor in the local coordinates that will be transformed
|
||||
* with the transformation matrix when rendered on the screen.
|
||||
* @see {@link EditorBoundsInfo}.
|
||||
* @see EditorBoundsInfo
|
||||
*/
|
||||
private final EditorBoundsInfo mEditorBoundsInfo;
|
||||
|
||||
@@ -121,6 +123,12 @@ public final class CursorAnchorInfo implements Parcelable {
|
||||
@NonNull
|
||||
private final float[] mMatrixValues;
|
||||
|
||||
/**
|
||||
* Information about text appearance in the editor for use by {@link InputMethodService}.
|
||||
*/
|
||||
@Nullable
|
||||
private final TextAppearanceInfo mTextAppearanceInfo;
|
||||
|
||||
/**
|
||||
* A list of visible line bounds stored in a float array. This array is divided into segment of
|
||||
* four where each element in the segment represents left, top, right respectively and bottom
|
||||
@@ -157,10 +165,11 @@ public final class CursorAnchorInfo implements Parcelable {
|
||||
mInsertionMarkerTop = source.readFloat();
|
||||
mInsertionMarkerBaseline = source.readFloat();
|
||||
mInsertionMarkerBottom = source.readFloat();
|
||||
mCharacterBoundsArray = source.readParcelable(SparseRectFArray.class.getClassLoader(), android.view.inputmethod.SparseRectFArray.class);
|
||||
mCharacterBoundsArray = source.readTypedObject(SparseRectFArray.CREATOR);
|
||||
mEditorBoundsInfo = source.readTypedObject(EditorBoundsInfo.CREATOR);
|
||||
mMatrixValues = source.createFloatArray();
|
||||
mVisibleLineBounds = source.createFloatArray();
|
||||
mTextAppearanceInfo = source.readTypedObject(TextAppearanceInfo.CREATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,10 +190,11 @@ public final class CursorAnchorInfo implements Parcelable {
|
||||
dest.writeFloat(mInsertionMarkerTop);
|
||||
dest.writeFloat(mInsertionMarkerBaseline);
|
||||
dest.writeFloat(mInsertionMarkerBottom);
|
||||
dest.writeParcelable(mCharacterBoundsArray, flags);
|
||||
dest.writeTypedObject(mCharacterBoundsArray, flags);
|
||||
dest.writeTypedObject(mEditorBoundsInfo, flags);
|
||||
dest.writeFloatArray(mMatrixValues);
|
||||
dest.writeFloatArray(mVisibleLineBounds);
|
||||
dest.writeTypedObject(mTextAppearanceInfo, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -262,6 +272,11 @@ public final class CursorAnchorInfo implements Parcelable {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Objects.equals(mTextAppearanceInfo, that.mTextAppearanceInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -270,16 +285,17 @@ public final class CursorAnchorInfo implements Parcelable {
|
||||
return "CursorAnchorInfo{mHashCode=" + mHashCode
|
||||
+ " mSelection=" + mSelectionStart + "," + mSelectionEnd
|
||||
+ " mComposingTextStart=" + mComposingTextStart
|
||||
+ " mComposingText=" + Objects.toString(mComposingText)
|
||||
+ " mComposingText=" + mComposingText
|
||||
+ " mInsertionMarkerFlags=" + mInsertionMarkerFlags
|
||||
+ " mInsertionMarkerHorizontal=" + mInsertionMarkerHorizontal
|
||||
+ " mInsertionMarkerTop=" + mInsertionMarkerTop
|
||||
+ " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline
|
||||
+ " mInsertionMarkerBottom=" + mInsertionMarkerBottom
|
||||
+ " mCharacterBoundsArray=" + Objects.toString(mCharacterBoundsArray)
|
||||
+ " mCharacterBoundsArray=" + mCharacterBoundsArray
|
||||
+ " mEditorBoundsInfo=" + mEditorBoundsInfo
|
||||
+ " mVisibleLineBounds=" + getVisibleLineBounds()
|
||||
+ " mMatrix=" + Arrays.toString(mMatrixValues)
|
||||
+ " mTextAppearanceInfo=" + mTextAppearanceInfo
|
||||
+ "}";
|
||||
}
|
||||
|
||||
@@ -303,6 +319,7 @@ public final class CursorAnchorInfo implements Parcelable {
|
||||
private boolean mMatrixInitialized = false;
|
||||
private float[] mVisibleLineBounds = new float[LINE_BOUNDS_INITIAL_SIZE * 4];
|
||||
private int mVisibleLineBoundsCount = 0;
|
||||
private TextAppearanceInfo mTextAppearanceInfo = null;
|
||||
|
||||
/**
|
||||
* Sets the text range of the selection. Calling this can be skipped if there is no
|
||||
@@ -415,6 +432,17 @@ public final class CursorAnchorInfo implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the information related to text appearance, which is extracted from the original
|
||||
* {@link TextView}.
|
||||
* @param textAppearanceInfo {@link TextAppearanceInfo} of TextView.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setTextAppearanceInfo(@Nullable TextAppearanceInfo textAppearanceInfo) {
|
||||
mTextAppearanceInfo = textAppearanceInfo;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the bounds of a visible text line of the current editor.
|
||||
*
|
||||
@@ -504,6 +532,7 @@ public final class CursorAnchorInfo implements Parcelable {
|
||||
}
|
||||
mEditorBoundsInfo = null;
|
||||
clearVisibleLineBounds();
|
||||
mTextAppearanceInfo = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -524,7 +553,8 @@ public final class CursorAnchorInfo implements Parcelable {
|
||||
builder.mInsertionMarkerHorizontal, builder.mInsertionMarkerTop,
|
||||
builder.mInsertionMarkerBaseline, builder.mInsertionMarkerBottom,
|
||||
characterBoundsArray, builder.mEditorBoundsInfo, matrixValues,
|
||||
Arrays.copyOf(builder.mVisibleLineBounds, builder.mVisibleLineBoundsCount));
|
||||
Arrays.copyOf(builder.mVisibleLineBounds, builder.mVisibleLineBoundsCount),
|
||||
builder.mTextAppearanceInfo);
|
||||
}
|
||||
|
||||
private CursorAnchorInfo(int selectionStart, int selectionEnd, int composingTextStart,
|
||||
@@ -533,7 +563,8 @@ public final class CursorAnchorInfo implements Parcelable {
|
||||
float insertionMarkerBaseline, float insertionMarkerBottom,
|
||||
@Nullable SparseRectFArray characterBoundsArray,
|
||||
@Nullable EditorBoundsInfo editorBoundsInfo,
|
||||
@NonNull float[] matrixValues, @Nullable float[] visibleLineBounds) {
|
||||
@NonNull float[] matrixValues, @Nullable float[] visibleLineBounds,
|
||||
@Nullable TextAppearanceInfo textAppearanceInfo) {
|
||||
mSelectionStart = selectionStart;
|
||||
mSelectionEnd = selectionEnd;
|
||||
mComposingTextStart = composingTextStart;
|
||||
@@ -547,6 +578,7 @@ public final class CursorAnchorInfo implements Parcelable {
|
||||
mEditorBoundsInfo = editorBoundsInfo;
|
||||
mMatrixValues = matrixValues;
|
||||
mVisibleLineBounds = visibleLineBounds;
|
||||
mTextAppearanceInfo = textAppearanceInfo;
|
||||
|
||||
// To keep hash function simple, we only use some complex objects for hash.
|
||||
int hashCode = Objects.hashCode(mComposingText);
|
||||
@@ -573,7 +605,7 @@ public final class CursorAnchorInfo implements Parcelable {
|
||||
original.mInsertionMarkerTop, original.mInsertionMarkerBaseline,
|
||||
original.mInsertionMarkerBottom, original.mCharacterBoundsArray,
|
||||
original.mEditorBoundsInfo, computeMatrixValues(parentMatrix, original),
|
||||
original.mVisibleLineBounds);
|
||||
original.mVisibleLineBounds, original.mTextAppearanceInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -740,6 +772,16 @@ public final class CursorAnchorInfo implements Parcelable {
|
||||
return mEditorBoundsInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link TextAppearanceInfo} for the current editor, or {@code null} if IME is not
|
||||
* subscribed with {@link InputConnection#CURSOR_UPDATE_FILTER_TEXT_APPEARANCE}
|
||||
* or {@link InputConnection#CURSOR_UPDATE_MONITOR}.
|
||||
*/
|
||||
@Nullable
|
||||
public TextAppearanceInfo getTextAppearanceInfo() {
|
||||
return mTextAppearanceInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of {@link android.graphics.Matrix} that indicates the transformation
|
||||
* matrix that is to be applied other positional data in this class.
|
||||
|
||||
@@ -1057,8 +1057,10 @@ public interface InputConnection {
|
||||
* used together with {@link #CURSOR_UPDATE_MONITOR}.
|
||||
* <p>
|
||||
* Note by default all of {@link #CURSOR_UPDATE_FILTER_EDITOR_BOUNDS},
|
||||
* {@link #CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS} and
|
||||
* {@link #CURSOR_UPDATE_FILTER_INSERTION_MARKER} are included but specifying them can
|
||||
* {@link #CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS},
|
||||
* {@link #CURSOR_UPDATE_FILTER_VISIBLE_LINE_BOUNDS},
|
||||
* {@link #CURSOR_UPDATE_FILTER_TEXT_APPEARANCE}, and
|
||||
* {@link #CURSOR_UPDATE_FILTER_INSERTION_MARKER}, are included but specifying them can
|
||||
* filter-out others.
|
||||
* It can be CPU intensive to include all, filtering specific info is recommended.
|
||||
* </p>
|
||||
@@ -1076,7 +1078,8 @@ public interface InputConnection {
|
||||
* <p>
|
||||
* Note by default all of {@link #CURSOR_UPDATE_FILTER_EDITOR_BOUNDS},
|
||||
* {@link #CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS},
|
||||
* {@link #CURSOR_UPDATE_FILTER_VISIBLE_LINE_BOUNDS} and
|
||||
* {@link #CURSOR_UPDATE_FILTER_VISIBLE_LINE_BOUNDS},
|
||||
* {@link #CURSOR_UPDATE_FILTER_TEXT_APPEARANCE}, and
|
||||
* {@link #CURSOR_UPDATE_FILTER_INSERTION_MARKER}, are included but specifying them can
|
||||
* filter-out others.
|
||||
* It can be CPU intensive to include all, filtering specific info is recommended.
|
||||
@@ -1092,6 +1095,7 @@ public interface InputConnection {
|
||||
* <p>
|
||||
* This flag can be used together with filters: {@link #CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS},
|
||||
* {@link #CURSOR_UPDATE_FILTER_VISIBLE_LINE_BOUNDS},
|
||||
* {@link #CURSOR_UPDATE_FILTER_TEXT_APPEARANCE},
|
||||
* {@link #CURSOR_UPDATE_FILTER_INSERTION_MARKER} and update flags
|
||||
* {@link #CURSOR_UPDATE_IMMEDIATE} and {@link #CURSOR_UPDATE_MONITOR}.
|
||||
* </p>
|
||||
@@ -1107,8 +1111,8 @@ public interface InputConnection {
|
||||
* <p>
|
||||
* This flag can be combined with other filters: {@link #CURSOR_UPDATE_FILTER_EDITOR_BOUNDS},
|
||||
* {@link #CURSOR_UPDATE_FILTER_VISIBLE_LINE_BOUNDS},
|
||||
* {@link #CURSOR_UPDATE_FILTER_INSERTION_MARKER} and update flags
|
||||
* {@link #CURSOR_UPDATE_IMMEDIATE} and {@link #CURSOR_UPDATE_MONITOR}.
|
||||
* {@link #CURSOR_UPDATE_FILTER_TEXT_APPEARANCE}, {@link #CURSOR_UPDATE_FILTER_INSERTION_MARKER}
|
||||
* and update flags {@link #CURSOR_UPDATE_IMMEDIATE} and {@link #CURSOR_UPDATE_MONITOR}.
|
||||
* </p>
|
||||
*/
|
||||
int CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS = 1 << 3;
|
||||
@@ -1123,8 +1127,8 @@ public interface InputConnection {
|
||||
* <p>
|
||||
* This flag can be combined with other filters: {@link #CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS},
|
||||
* {@link #CURSOR_UPDATE_FILTER_VISIBLE_LINE_BOUNDS},
|
||||
* {@link #CURSOR_UPDATE_FILTER_EDITOR_BOUNDS} and update flags {@link #CURSOR_UPDATE_IMMEDIATE}
|
||||
* and {@link #CURSOR_UPDATE_MONITOR}.
|
||||
* {@link #CURSOR_UPDATE_FILTER_TEXT_APPEARANCE}, {@link #CURSOR_UPDATE_FILTER_EDITOR_BOUNDS}
|
||||
* and update flags {@link #CURSOR_UPDATE_IMMEDIATE} and {@link #CURSOR_UPDATE_MONITOR}.
|
||||
* </p>
|
||||
*/
|
||||
int CURSOR_UPDATE_FILTER_INSERTION_MARKER = 1 << 4;
|
||||
@@ -1138,13 +1142,28 @@ public interface InputConnection {
|
||||
* {@link InputConnection#requestCursorUpdates(int)} again with this flag off.
|
||||
* <p>
|
||||
* This flag can be combined with other filters: {@link #CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS},
|
||||
* {@link #CURSOR_UPDATE_FILTER_EDITOR_BOUNDS}, {@link #CURSOR_UPDATE_FILTER_INSERTION_MARKER}
|
||||
* and update flags {@link #CURSOR_UPDATE_IMMEDIATE}
|
||||
* and {@link #CURSOR_UPDATE_MONITOR}.
|
||||
* {@link #CURSOR_UPDATE_FILTER_EDITOR_BOUNDS}, {@link #CURSOR_UPDATE_FILTER_INSERTION_MARKER},
|
||||
* {@link #CURSOR_UPDATE_FILTER_TEXT_APPEARANCE} and update flags
|
||||
* {@link #CURSOR_UPDATE_IMMEDIATE} and {@link #CURSOR_UPDATE_MONITOR}.
|
||||
* </p>
|
||||
*/
|
||||
int CURSOR_UPDATE_FILTER_VISIBLE_LINE_BOUNDS = 1 << 5;
|
||||
|
||||
/**
|
||||
* The editor is requested to call
|
||||
* {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}
|
||||
* with new text appearance info {@link CursorAnchorInfo#getTextAppearanceInfo()}}
|
||||
* whenever cursor/anchor position is changed. To disable monitoring, call
|
||||
* {@link InputConnection#requestCursorUpdates(int)} again with this flag off.
|
||||
* <p>
|
||||
* This flag can be combined with other filters: {@link #CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS},
|
||||
* {@link #CURSOR_UPDATE_FILTER_EDITOR_BOUNDS}, {@link #CURSOR_UPDATE_FILTER_INSERTION_MARKER},
|
||||
* {@link #CURSOR_UPDATE_FILTER_VISIBLE_LINE_BOUNDS} and update flags
|
||||
* {@link #CURSOR_UPDATE_IMMEDIATE} and {@link #CURSOR_UPDATE_MONITOR}.
|
||||
* </p>
|
||||
*/
|
||||
int CURSOR_UPDATE_FILTER_TEXT_APPEARANCE = 1 << 6;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@@ -1158,7 +1177,8 @@ public interface InputConnection {
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(value = {CURSOR_UPDATE_FILTER_EDITOR_BOUNDS, CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS,
|
||||
CURSOR_UPDATE_FILTER_INSERTION_MARKER, CURSOR_UPDATE_FILTER_VISIBLE_LINE_BOUNDS},
|
||||
CURSOR_UPDATE_FILTER_INSERTION_MARKER, CURSOR_UPDATE_FILTER_VISIBLE_LINE_BOUNDS,
|
||||
CURSOR_UPDATE_FILTER_TEXT_APPEARANCE},
|
||||
flag = true, prefix = { "CURSOR_UPDATE_FILTER_" })
|
||||
@interface CursorUpdateFilter{}
|
||||
|
||||
|
||||
509
core/java/android/view/inputmethod/TextAppearanceInfo.java
Normal file
509
core/java/android/view/inputmethod/TextAppearanceInfo.java
Normal file
@@ -0,0 +1,509 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
package android.view.inputmethod;
|
||||
|
||||
import android.annotation.ColorInt;
|
||||
import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.Px;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.fonts.FontStyle;
|
||||
import android.graphics.text.LineBreakConfig;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.os.LocaleList;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.InputFilter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Information about text appearance in an editor, passed through
|
||||
* {@link CursorAnchorInfo} for use by {@link InputMethodService}.
|
||||
*
|
||||
* @see TextView
|
||||
* @see Paint
|
||||
* @see CursorAnchorInfo.Builder#setTextAppearanceInfo(TextAppearanceInfo)
|
||||
* @see CursorAnchorInfo#getTextAppearanceInfo()
|
||||
*/
|
||||
public final class TextAppearanceInfo implements Parcelable {
|
||||
/**
|
||||
* The text size (in pixels) for current {@link TextView}.
|
||||
*/
|
||||
private final @Px float mTextSize;
|
||||
|
||||
/**
|
||||
* The LocaleList of the text.
|
||||
*/
|
||||
@NonNull private final LocaleList mTextLocales;
|
||||
|
||||
/**
|
||||
* The font family name if the {@link Typeface} of the text is created from a system font
|
||||
* family, otherwise this value should be null.
|
||||
*/
|
||||
@Nullable private final String mSystemFontFamilyName;
|
||||
|
||||
/**
|
||||
* The weight of the text.
|
||||
*/
|
||||
private final @IntRange(from = -1, to = FontStyle.FONT_WEIGHT_MAX) int mTextFontWeight;
|
||||
|
||||
/**
|
||||
* The style (normal, bold, italic, bold|italic) of the text, see {@link Typeface}.
|
||||
*/
|
||||
private final @Typeface.Style int mTextStyle;
|
||||
|
||||
/**
|
||||
* Whether the transformation method applied to the current {@link TextView} is set to
|
||||
* ALL CAPS.
|
||||
*/
|
||||
private final boolean mAllCaps;
|
||||
|
||||
/**
|
||||
* The horizontal offset (in pixels) of the text shadow.
|
||||
*/
|
||||
private final @Px float mShadowDx;
|
||||
|
||||
/**
|
||||
* The vertical offset (in pixels) of the text shadow.
|
||||
*/
|
||||
private final @Px float mShadowDy;
|
||||
|
||||
/**
|
||||
* The blur radius (in pixels) of the text shadow.
|
||||
*/
|
||||
private final @Px float mShadowRadius;
|
||||
|
||||
/**
|
||||
* The elegant text height, especially for less compacted complex script text.
|
||||
*/
|
||||
private final boolean mElegantTextHeight;
|
||||
|
||||
/**
|
||||
* Whether to expand linespacing based on fallback fonts.
|
||||
*/
|
||||
private final boolean mFallbackLineSpacing;
|
||||
|
||||
/**
|
||||
* The text letter-spacing (in ems), which determines the spacing between characters.
|
||||
*/
|
||||
private final float mLetterSpacing;
|
||||
|
||||
/**
|
||||
* The font feature settings.
|
||||
*/
|
||||
@Nullable private final String mFontFeatureSettings;
|
||||
|
||||
/**
|
||||
* The font variation settings.
|
||||
*/
|
||||
@Nullable private final String mFontVariationSettings;
|
||||
|
||||
/**
|
||||
* The line-break strategies for text wrapping.
|
||||
*/
|
||||
private final @LineBreakConfig.LineBreakStyle int mLineBreakStyle;
|
||||
|
||||
/**
|
||||
* The line-break word strategies for text wrapping.
|
||||
*/
|
||||
private final @LineBreakConfig.LineBreakWordStyle int mLineBreakWordStyle;
|
||||
|
||||
/**
|
||||
* The extent by which text should be stretched horizontally. Returns 1.0 if not specified.
|
||||
*/
|
||||
private final float mTextScaleX;
|
||||
|
||||
/**
|
||||
* The color of the text selection highlight.
|
||||
*/
|
||||
private final @ColorInt int mTextColorHighlight;
|
||||
|
||||
/**
|
||||
* The current text color.
|
||||
*/
|
||||
private final @ColorInt int mTextColor;
|
||||
|
||||
/**
|
||||
* The current color of the hint text.
|
||||
*/
|
||||
private final @ColorInt int mTextColorHint;
|
||||
|
||||
/**
|
||||
* The text color for links.
|
||||
*/
|
||||
@Nullable private final ColorStateList mTextColorLink;
|
||||
|
||||
/**
|
||||
* The max length of text.
|
||||
*/
|
||||
private final int mMaxLength;
|
||||
|
||||
|
||||
public TextAppearanceInfo(@NonNull TextView textView) {
|
||||
mTextSize = textView.getTextSize();
|
||||
mTextLocales = textView.getTextLocales();
|
||||
Typeface typeface = textView.getPaint().getTypeface();
|
||||
String systemFontFamilyName = null;
|
||||
int textFontWeight = -1;
|
||||
if (typeface != null) {
|
||||
systemFontFamilyName = typeface.getSystemFontFamilyName();
|
||||
textFontWeight = typeface.getWeight();
|
||||
}
|
||||
mSystemFontFamilyName = systemFontFamilyName;
|
||||
mTextFontWeight = textFontWeight;
|
||||
mTextStyle = textView.getTypefaceStyle();
|
||||
mAllCaps = textView.isAllCaps();
|
||||
mShadowRadius = textView.getShadowRadius();
|
||||
mShadowDx = textView.getShadowDx();
|
||||
mShadowDy = textView.getShadowDy();
|
||||
mElegantTextHeight = textView.isElegantTextHeight();
|
||||
mFallbackLineSpacing = textView.isFallbackLineSpacing();
|
||||
mLetterSpacing = textView.getLetterSpacing();
|
||||
mFontFeatureSettings = textView.getFontFeatureSettings();
|
||||
mFontVariationSettings = textView.getFontVariationSettings();
|
||||
mLineBreakStyle = textView.getLineBreakStyle();
|
||||
mLineBreakWordStyle = textView.getLineBreakWordStyle();
|
||||
mTextScaleX = textView.getTextScaleX();
|
||||
mTextColorHighlight = textView.getHighlightColor();
|
||||
mTextColor = textView.getCurrentTextColor();
|
||||
mTextColorHint = textView.getCurrentHintTextColor();
|
||||
mTextColorLink = textView.getLinkTextColors();
|
||||
int maxLength = -1;
|
||||
for (InputFilter filter: textView.getFilters()) {
|
||||
if (filter instanceof InputFilter.LengthFilter) {
|
||||
maxLength = ((InputFilter.LengthFilter) filter).getMax();
|
||||
// There is at most one LengthFilter.
|
||||
break;
|
||||
}
|
||||
}
|
||||
mMaxLength = maxLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeFloat(mTextSize);
|
||||
mTextLocales.writeToParcel(dest, flags); // NonNull
|
||||
dest.writeBoolean(mAllCaps);
|
||||
dest.writeString8(mSystemFontFamilyName);
|
||||
dest.writeInt(mTextFontWeight);
|
||||
dest.writeInt(mTextStyle);
|
||||
dest.writeFloat(mShadowDx);
|
||||
dest.writeFloat(mShadowDy);
|
||||
dest.writeFloat(mShadowRadius);
|
||||
dest.writeBoolean(mElegantTextHeight);
|
||||
dest.writeBoolean(mFallbackLineSpacing);
|
||||
dest.writeFloat(mLetterSpacing);
|
||||
dest.writeString8(mFontFeatureSettings);
|
||||
dest.writeString8(mFontVariationSettings);
|
||||
dest.writeInt(mLineBreakStyle);
|
||||
dest.writeInt(mLineBreakWordStyle);
|
||||
dest.writeFloat(mTextScaleX);
|
||||
dest.writeInt(mTextColorHighlight);
|
||||
dest.writeInt(mTextColor);
|
||||
dest.writeInt(mTextColorHint);
|
||||
dest.writeTypedObject(mTextColorLink, flags);
|
||||
dest.writeInt(mMaxLength);
|
||||
}
|
||||
|
||||
private TextAppearanceInfo(@NonNull Parcel in) {
|
||||
mTextSize = in.readFloat();
|
||||
mTextLocales = LocaleList.CREATOR.createFromParcel(in);
|
||||
mAllCaps = in.readBoolean();
|
||||
mSystemFontFamilyName = in.readString8();
|
||||
mTextFontWeight = in.readInt();
|
||||
mTextStyle = in.readInt();
|
||||
mShadowDx = in.readFloat();
|
||||
mShadowDy = in.readFloat();
|
||||
mShadowRadius = in.readFloat();
|
||||
mElegantTextHeight = in.readBoolean();
|
||||
mFallbackLineSpacing = in.readBoolean();
|
||||
mLetterSpacing = in.readFloat();
|
||||
mFontFeatureSettings = in.readString8();
|
||||
mFontVariationSettings = in.readString8();
|
||||
mLineBreakStyle = in.readInt();
|
||||
mLineBreakWordStyle = in.readInt();
|
||||
mTextScaleX = in.readFloat();
|
||||
mTextColorHighlight = in.readInt();
|
||||
mTextColor = in.readInt();
|
||||
mTextColorHint = in.readInt();
|
||||
mTextColorLink = in.readTypedObject(ColorStateList.CREATOR);
|
||||
mMaxLength = in.readInt();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static final Creator<TextAppearanceInfo> CREATOR = new Creator<TextAppearanceInfo>() {
|
||||
@Override
|
||||
public TextAppearanceInfo createFromParcel(@NonNull Parcel in) {
|
||||
return new TextAppearanceInfo(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextAppearanceInfo[] newArray(int size) {
|
||||
return new TextAppearanceInfo[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the text size (in pixels) for current {@link TextView}.
|
||||
*/
|
||||
public @Px float getTextSize() {
|
||||
return mTextSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the LocaleList of the text.
|
||||
*/
|
||||
@NonNull
|
||||
public LocaleList getTextLocales() {
|
||||
return mTextLocales;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the font family name if the {@link Typeface} of the text is created from a
|
||||
* system font family. Returns null if no {@link Typeface} is specified, or it is not created
|
||||
* from a system font family.
|
||||
*/
|
||||
@Nullable
|
||||
public String getFontFamilyName() {
|
||||
return mSystemFontFamilyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the weight of the text. Returns -1 when no {@link Typeface} is specified.
|
||||
*/
|
||||
public @IntRange(from = -1, to = FontStyle.FONT_WEIGHT_MAX) int getTextFontWeight() {
|
||||
return mTextFontWeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the style (normal, bold, italic, bold|italic) of the text. Returns
|
||||
* {@link Typeface#NORMAL} when no {@link Typeface} is specified. See {@link Typeface} for
|
||||
* more information.
|
||||
*/
|
||||
public @Typeface.Style int getTextStyle() {
|
||||
return mTextStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the transformation method applied to the current {@link TextView} is set to
|
||||
* ALL CAPS.
|
||||
*/
|
||||
public boolean isAllCaps() {
|
||||
return mAllCaps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the horizontal offset (in pixels) of the text shadow.
|
||||
*/
|
||||
public @Px float getShadowDx() {
|
||||
return mShadowDx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the vertical offset (in pixels) of the text shadow.
|
||||
*/
|
||||
public @Px float getShadowDy() {
|
||||
return mShadowDy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the blur radius (in pixels) of the text shadow.
|
||||
*/
|
||||
public @Px float getShadowRadius() {
|
||||
return mShadowRadius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the elegant height metrics flag is set. This setting selects font
|
||||
* variants that have not been compacted to fit Latin-based vertical metrics, and also increases
|
||||
* top and bottom bounds to provide more space.
|
||||
*/
|
||||
public boolean isElegantTextHeight() {
|
||||
return mElegantTextHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether to expand linespacing based on fallback fonts.
|
||||
*
|
||||
* @see TextView#setFallbackLineSpacing(boolean)
|
||||
*/
|
||||
public boolean isFallbackLineSpacing() {
|
||||
return mFallbackLineSpacing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text letter-spacing, which determines the spacing between characters.
|
||||
* The value is in 'EM' units. Normally, this value is 0.0.
|
||||
*/
|
||||
public float getLetterSpacing() {
|
||||
return mLetterSpacing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the font feature settings. Returns null if not specified.
|
||||
*
|
||||
* @see Paint#getFontFeatureSettings()
|
||||
*/
|
||||
@Nullable
|
||||
public String getFontFeatureSettings() {
|
||||
return mFontFeatureSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the font variation settings. Returns null if no variation is specified.
|
||||
*
|
||||
* @see Paint#getFontVariationSettings()
|
||||
*/
|
||||
@Nullable
|
||||
public String getFontVariationSettings() {
|
||||
return mFontVariationSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the line-break strategies for text wrapping.
|
||||
*
|
||||
* @see TextView#setLineBreakStyle(int)
|
||||
*/
|
||||
public @LineBreakConfig.LineBreakStyle int getLineBreakStyle() {
|
||||
return mLineBreakStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the line-break word strategies for text wrapping.
|
||||
*
|
||||
* @see TextView#setLineBreakWordStyle(int)
|
||||
*/
|
||||
public @LineBreakConfig.LineBreakWordStyle int getLineBreakWordStyle() {
|
||||
return mLineBreakWordStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the extent by which text should be stretched horizontally. Returns 1.0 if not
|
||||
* specified.
|
||||
*/
|
||||
public float getTextScaleX() {
|
||||
return mTextScaleX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color of the text selection highlight.
|
||||
*/
|
||||
public @ColorInt int getTextColorHighlight() {
|
||||
return mTextColorHighlight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current text color.
|
||||
*/
|
||||
public @ColorInt int getTextColor() {
|
||||
return mTextColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current color of the hint text.
|
||||
*/
|
||||
public @ColorInt int getTextColorHint() {
|
||||
return mTextColorHint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text color for links.
|
||||
*/
|
||||
@Nullable
|
||||
public ColorStateList getTextColorLink() {
|
||||
return mTextColorLink;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the max length of text, which is used to set an input filter to constrain the text
|
||||
* length to the specified number. Returns -1 when there is no {@link InputFilter.LengthFilter}
|
||||
* in the Editor.
|
||||
*/
|
||||
public int getMaxLength() {
|
||||
return mMaxLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof TextAppearanceInfo)) return false;
|
||||
TextAppearanceInfo that = (TextAppearanceInfo) o;
|
||||
return Float.compare(that.mTextSize, mTextSize) == 0
|
||||
&& mTextFontWeight == that.mTextFontWeight && mTextStyle == that.mTextStyle
|
||||
&& mAllCaps == that.mAllCaps && Float.compare(that.mShadowDx, mShadowDx) == 0
|
||||
&& Float.compare(that.mShadowDy, mShadowDy) == 0 && Float.compare(
|
||||
that.mShadowRadius, mShadowRadius) == 0 && mMaxLength == that.mMaxLength
|
||||
&& mElegantTextHeight == that.mElegantTextHeight
|
||||
&& mFallbackLineSpacing == that.mFallbackLineSpacing && Float.compare(
|
||||
that.mLetterSpacing, mLetterSpacing) == 0 && mLineBreakStyle == that.mLineBreakStyle
|
||||
&& mLineBreakWordStyle == that.mLineBreakWordStyle
|
||||
&& mTextColorHighlight == that.mTextColorHighlight && mTextColor == that.mTextColor
|
||||
&& mTextColorLink.getDefaultColor() == that.mTextColorLink.getDefaultColor()
|
||||
&& mTextColorHint == that.mTextColorHint && Objects.equals(
|
||||
mTextLocales, that.mTextLocales) && Objects.equals(mSystemFontFamilyName,
|
||||
that.mSystemFontFamilyName) && Objects.equals(mFontFeatureSettings,
|
||||
that.mFontFeatureSettings) && Objects.equals(mFontVariationSettings,
|
||||
that.mFontVariationSettings) && Float.compare(that.mTextScaleX, mTextScaleX) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mTextSize, mTextLocales, mSystemFontFamilyName, mTextFontWeight,
|
||||
mTextStyle, mAllCaps, mShadowDx, mShadowDy, mShadowRadius, mElegantTextHeight,
|
||||
mFallbackLineSpacing, mLetterSpacing, mFontFeatureSettings, mFontVariationSettings,
|
||||
mLineBreakStyle, mLineBreakWordStyle, mTextScaleX, mTextColorHighlight, mTextColor,
|
||||
mTextColorHint, mTextColorLink, mMaxLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TextAppearanceInfo{"
|
||||
+ "mTextSize=" + mTextSize
|
||||
+ ", mTextLocales=" + mTextLocales
|
||||
+ ", mSystemFontFamilyName='" + mSystemFontFamilyName + '\''
|
||||
+ ", mTextFontWeight=" + mTextFontWeight
|
||||
+ ", mTextStyle=" + mTextStyle
|
||||
+ ", mAllCaps=" + mAllCaps
|
||||
+ ", mShadowDx=" + mShadowDx
|
||||
+ ", mShadowDy=" + mShadowDy
|
||||
+ ", mShadowRadius=" + mShadowRadius
|
||||
+ ", mElegantTextHeight=" + mElegantTextHeight
|
||||
+ ", mFallbackLineSpacing=" + mFallbackLineSpacing
|
||||
+ ", mLetterSpacing=" + mLetterSpacing
|
||||
+ ", mFontFeatureSettings='" + mFontFeatureSettings + '\''
|
||||
+ ", mFontVariationSettings='" + mFontVariationSettings + '\''
|
||||
+ ", mLineBreakStyle=" + mLineBreakStyle
|
||||
+ ", mLineBreakWordStyle=" + mLineBreakWordStyle
|
||||
+ ", mTextScaleX=" + mTextScaleX
|
||||
+ ", mTextColorHighlight=" + mTextColorHighlight
|
||||
+ ", mTextColor=" + mTextColor
|
||||
+ ", mTextColorHint=" + mTextColorHint
|
||||
+ ", mTextColorLink=" + mTextColorLink
|
||||
+ ", mMaxLength=" + mMaxLength
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
@@ -125,6 +125,7 @@ import android.view.inputmethod.ExtractedText;
|
||||
import android.view.inputmethod.ExtractedTextRequest;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.view.inputmethod.TextAppearanceInfo;
|
||||
import android.view.textclassifier.TextClassification;
|
||||
import android.view.textclassifier.TextClassificationManager;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
@@ -4630,14 +4631,17 @@ public class Editor {
|
||||
(filter & InputConnection.CURSOR_UPDATE_FILTER_INSERTION_MARKER) != 0;
|
||||
boolean includeVisibleLineBounds =
|
||||
(filter & InputConnection.CURSOR_UPDATE_FILTER_VISIBLE_LINE_BOUNDS) != 0;
|
||||
boolean includeTextAppearance =
|
||||
(filter & InputConnection.CURSOR_UPDATE_FILTER_TEXT_APPEARANCE) != 0;
|
||||
boolean includeAll =
|
||||
(!includeEditorBounds && !includeCharacterBounds && !includeInsertionMarker
|
||||
&& !includeVisibleLineBounds);
|
||||
&& !includeVisibleLineBounds && !includeTextAppearance);
|
||||
|
||||
includeEditorBounds |= includeAll;
|
||||
includeCharacterBounds |= includeAll;
|
||||
includeInsertionMarker |= includeAll;
|
||||
includeVisibleLineBounds |= includeAll;
|
||||
includeTextAppearance |= includeAll;
|
||||
|
||||
final CursorAnchorInfo.Builder builder = mSelectionInfoBuilder;
|
||||
builder.reset();
|
||||
@@ -4757,6 +4761,10 @@ public class Editor {
|
||||
}
|
||||
}
|
||||
|
||||
if (includeTextAppearance) {
|
||||
TextAppearanceInfo textAppearanceInfo = new TextAppearanceInfo(mTextView);
|
||||
builder.setTextAppearanceInfo(textAppearanceInfo);
|
||||
}
|
||||
imm.updateCursorAnchorInfo(mTextView, builder.build());
|
||||
|
||||
// Drop the immediate flag if any.
|
||||
|
||||
@@ -237,7 +237,9 @@ public final class EditableInputConnection extends BaseInputConnection
|
||||
| InputConnection.CURSOR_UPDATE_MONITOR;
|
||||
final int knownFilterFlags = InputConnection.CURSOR_UPDATE_FILTER_EDITOR_BOUNDS
|
||||
| InputConnection.CURSOR_UPDATE_FILTER_INSERTION_MARKER
|
||||
| InputConnection.CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS;
|
||||
| InputConnection.CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS
|
||||
| InputConnection.CURSOR_UPDATE_FILTER_VISIBLE_LINE_BOUNDS
|
||||
| InputConnection.CURSOR_UPDATE_FILTER_TEXT_APPEARANCE;
|
||||
|
||||
// It is possible that any other bit is used as a valid flag in a future release.
|
||||
// We should reject the entire request in such a case.
|
||||
|
||||
Reference in New Issue
Block a user