am f2474d33: Merge "Implement better handling of text in assist." into mnc-dev
* commit 'f2474d336a7df696f3897e2cd255d138eb3fac02': Implement better handling of text in assist.
This commit is contained in:
@@ -5822,6 +5822,8 @@ package android.app.assist {
|
|||||||
method public java.lang.CharSequence getText();
|
method public java.lang.CharSequence getText();
|
||||||
method public int getTextBackgroundColor();
|
method public int getTextBackgroundColor();
|
||||||
method public int getTextColor();
|
method public int getTextColor();
|
||||||
|
method public int[] getTextLineBaselines();
|
||||||
|
method public int[] getTextLineCharOffsets();
|
||||||
method public int getTextSelectionEnd();
|
method public int getTextSelectionEnd();
|
||||||
method public int getTextSelectionStart();
|
method public int getTextSelectionStart();
|
||||||
method public float getTextSize();
|
method public float getTextSize();
|
||||||
@@ -36953,6 +36955,7 @@ package android.view {
|
|||||||
method public abstract void setSelected(boolean);
|
method public abstract void setSelected(boolean);
|
||||||
method public abstract void setText(java.lang.CharSequence);
|
method public abstract void setText(java.lang.CharSequence);
|
||||||
method public abstract void setText(java.lang.CharSequence, int, int);
|
method public abstract void setText(java.lang.CharSequence, int, int);
|
||||||
|
method public abstract void setTextLines(int[], int[]);
|
||||||
method public abstract void setTextStyle(float, int, int, int);
|
method public abstract void setTextStyle(float, int, int, int);
|
||||||
method public abstract void setTransformation(android.graphics.Matrix);
|
method public abstract void setTransformation(android.graphics.Matrix);
|
||||||
method public abstract void setVisibility(int);
|
method public abstract void setVisibility(int);
|
||||||
|
|||||||
@@ -5954,6 +5954,8 @@ package android.app.assist {
|
|||||||
method public java.lang.CharSequence getText();
|
method public java.lang.CharSequence getText();
|
||||||
method public int getTextBackgroundColor();
|
method public int getTextBackgroundColor();
|
||||||
method public int getTextColor();
|
method public int getTextColor();
|
||||||
|
method public int[] getTextLineBaselines();
|
||||||
|
method public int[] getTextLineCharOffsets();
|
||||||
method public int getTextSelectionEnd();
|
method public int getTextSelectionEnd();
|
||||||
method public int getTextSelectionStart();
|
method public int getTextSelectionStart();
|
||||||
method public float getTextSize();
|
method public float getTextSize();
|
||||||
@@ -39243,6 +39245,7 @@ package android.view {
|
|||||||
method public abstract void setSelected(boolean);
|
method public abstract void setSelected(boolean);
|
||||||
method public abstract void setText(java.lang.CharSequence);
|
method public abstract void setText(java.lang.CharSequence);
|
||||||
method public abstract void setText(java.lang.CharSequence, int, int);
|
method public abstract void setText(java.lang.CharSequence, int, int);
|
||||||
|
method public abstract void setTextLines(int[], int[]);
|
||||||
method public abstract void setTextStyle(float, int, int, int);
|
method public abstract void setTextStyle(float, int, int, int);
|
||||||
method public abstract void setTransformation(android.graphics.Matrix);
|
method public abstract void setTransformation(android.graphics.Matrix);
|
||||||
method public abstract void setVisibility(int);
|
method public abstract void setVisibility(int);
|
||||||
|
|||||||
@@ -61,37 +61,53 @@ public class AssistStructure implements Parcelable {
|
|||||||
|
|
||||||
final static class ViewNodeText {
|
final static class ViewNodeText {
|
||||||
CharSequence mText;
|
CharSequence mText;
|
||||||
int mTextSelectionStart;
|
|
||||||
int mTextSelectionEnd;
|
|
||||||
int mTextColor;
|
|
||||||
int mTextBackgroundColor;
|
|
||||||
float mTextSize;
|
float mTextSize;
|
||||||
int mTextStyle;
|
int mTextStyle;
|
||||||
|
int mTextColor = ViewNode.TEXT_COLOR_UNDEFINED;
|
||||||
|
int mTextBackgroundColor = ViewNode.TEXT_COLOR_UNDEFINED;
|
||||||
|
int mTextSelectionStart;
|
||||||
|
int mTextSelectionEnd;
|
||||||
|
int[] mLineCharOffsets;
|
||||||
|
int[] mLineBaselines;
|
||||||
String mHint;
|
String mHint;
|
||||||
|
|
||||||
ViewNodeText() {
|
ViewNodeText() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewNodeText(Parcel in) {
|
boolean isSimple() {
|
||||||
mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
|
return mTextBackgroundColor == ViewNode.TEXT_COLOR_UNDEFINED
|
||||||
mTextSelectionStart = in.readInt();
|
&& mTextSelectionStart == 0 && mTextSelectionEnd == 0
|
||||||
mTextSelectionEnd = in.readInt();
|
&& mLineCharOffsets == null && mLineBaselines == null && mHint == null;
|
||||||
mTextColor = in.readInt();
|
|
||||||
mTextBackgroundColor = in.readInt();
|
|
||||||
mTextSize = in.readFloat();
|
|
||||||
mTextStyle = in.readInt();
|
|
||||||
mHint = in.readString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeToParcel(Parcel out) {
|
ViewNodeText(Parcel in, boolean simple) {
|
||||||
|
mText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
|
||||||
|
mTextSize = in.readFloat();
|
||||||
|
mTextStyle = in.readInt();
|
||||||
|
mTextColor = in.readInt();
|
||||||
|
if (!simple) {
|
||||||
|
mTextBackgroundColor = in.readInt();
|
||||||
|
mTextSelectionStart = in.readInt();
|
||||||
|
mTextSelectionEnd = in.readInt();
|
||||||
|
mLineCharOffsets = in.createIntArray();
|
||||||
|
mLineBaselines = in.createIntArray();
|
||||||
|
mHint = in.readString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeToParcel(Parcel out, boolean simple) {
|
||||||
TextUtils.writeToParcel(mText, out, 0);
|
TextUtils.writeToParcel(mText, out, 0);
|
||||||
out.writeInt(mTextSelectionStart);
|
|
||||||
out.writeInt(mTextSelectionEnd);
|
|
||||||
out.writeInt(mTextColor);
|
|
||||||
out.writeInt(mTextBackgroundColor);
|
|
||||||
out.writeFloat(mTextSize);
|
out.writeFloat(mTextSize);
|
||||||
out.writeInt(mTextStyle);
|
out.writeInt(mTextStyle);
|
||||||
out.writeString(mHint);
|
out.writeInt(mTextColor);
|
||||||
|
if (!simple) {
|
||||||
|
out.writeInt(mTextBackgroundColor);
|
||||||
|
out.writeInt(mTextSelectionStart);
|
||||||
|
out.writeInt(mTextSelectionEnd);
|
||||||
|
out.writeIntArray(mLineCharOffsets);
|
||||||
|
out.writeIntArray(mLineBaselines);
|
||||||
|
out.writeString(mHint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,9 +268,10 @@ public class AssistStructure implements Parcelable {
|
|||||||
static final int FLAGS_HAS_LARGE_COORDS = 0x04000000;
|
static final int FLAGS_HAS_LARGE_COORDS = 0x04000000;
|
||||||
static final int FLAGS_HAS_CONTENT_DESCRIPTION = 0x02000000;
|
static final int FLAGS_HAS_CONTENT_DESCRIPTION = 0x02000000;
|
||||||
static final int FLAGS_HAS_TEXT = 0x01000000;
|
static final int FLAGS_HAS_TEXT = 0x01000000;
|
||||||
static final int FLAGS_HAS_EXTRAS = 0x00800000;
|
static final int FLAGS_HAS_COMPLEX_TEXT = 0x00800000;
|
||||||
static final int FLAGS_HAS_ID = 0x00400000;
|
static final int FLAGS_HAS_EXTRAS = 0x00400000;
|
||||||
static final int FLAGS_HAS_CHILDREN = 0x00200000;
|
static final int FLAGS_HAS_ID = 0x00200000;
|
||||||
|
static final int FLAGS_HAS_CHILDREN = 0x00100000;
|
||||||
static final int FLAGS_ALL_CONTROL = 0xfff00000;
|
static final int FLAGS_ALL_CONTROL = 0xfff00000;
|
||||||
|
|
||||||
int mFlags;
|
int mFlags;
|
||||||
@@ -316,7 +333,7 @@ public class AssistStructure implements Parcelable {
|
|||||||
mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
|
mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
|
||||||
}
|
}
|
||||||
if ((flags&FLAGS_HAS_TEXT) != 0) {
|
if ((flags&FLAGS_HAS_TEXT) != 0) {
|
||||||
mText = new ViewNodeText(in);
|
mText = new ViewNodeText(in, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0);
|
||||||
}
|
}
|
||||||
if ((flags&FLAGS_HAS_EXTRAS) != 0) {
|
if ((flags&FLAGS_HAS_EXTRAS) != 0) {
|
||||||
mExtras = in.readBundle();
|
mExtras = in.readBundle();
|
||||||
@@ -356,6 +373,9 @@ public class AssistStructure implements Parcelable {
|
|||||||
}
|
}
|
||||||
if (mText != null) {
|
if (mText != null) {
|
||||||
flags |= FLAGS_HAS_TEXT;
|
flags |= FLAGS_HAS_TEXT;
|
||||||
|
if (!mText.isSimple()) {
|
||||||
|
flags |= FLAGS_HAS_COMPLEX_TEXT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (mExtras != null) {
|
if (mExtras != null) {
|
||||||
flags |= FLAGS_HAS_EXTRAS;
|
flags |= FLAGS_HAS_EXTRAS;
|
||||||
@@ -403,7 +423,7 @@ public class AssistStructure implements Parcelable {
|
|||||||
TextUtils.writeToParcel(mContentDescription, out, 0);
|
TextUtils.writeToParcel(mContentDescription, out, 0);
|
||||||
}
|
}
|
||||||
if ((flags&FLAGS_HAS_TEXT) != 0) {
|
if ((flags&FLAGS_HAS_TEXT) != 0) {
|
||||||
mText.writeToParcel(out);
|
mText.writeToParcel(out, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0);
|
||||||
}
|
}
|
||||||
if ((flags&FLAGS_HAS_EXTRAS) != 0) {
|
if ((flags&FLAGS_HAS_EXTRAS) != 0) {
|
||||||
out.writeBundle(mExtras);
|
out.writeBundle(mExtras);
|
||||||
@@ -702,6 +722,26 @@ public class AssistStructure implements Parcelable {
|
|||||||
return mText != null ? mText.mTextStyle : 0;
|
return mText != null ? mText.mTextStyle : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return per-line offsets into the text returned by {@link #getText()}. Each entry
|
||||||
|
* in the array is a formatted line of text, and the value it contains is the offset
|
||||||
|
* into the text string where that line starts. May return null if there is no line
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
public int[] getTextLineCharOffsets() {
|
||||||
|
return mText != null ? mText.mLineCharOffsets : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return per-line baselines into the text returned by {@link #getText()}. Each entry
|
||||||
|
* in the array is a formatted line of text, and the value it contains is the baseline
|
||||||
|
* where that text appears in the view. May return null if there is no line
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
public int[] getTextLineBaselines() {
|
||||||
|
return mText != null ? mText.mLineBaselines : null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return additional hint text associated with the node; this is typically used with
|
* Return additional hint text associated with the node; this is typically used with
|
||||||
* a node that takes user input, describing to the user what the input means.
|
* a node that takes user input, describing to the user what the input means.
|
||||||
@@ -900,6 +940,13 @@ public class AssistStructure implements Parcelable {
|
|||||||
t.mTextStyle = style;
|
t.mTextStyle = style;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTextLines(int[] charOffsets, int[] baselines) {
|
||||||
|
ViewNodeText t = getNodeText();
|
||||||
|
t.mLineCharOffsets = charOffsets;
|
||||||
|
t.mLineBaselines = baselines;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setHint(CharSequence hint) {
|
public void setHint(CharSequence hint) {
|
||||||
getNodeText().mHint = hint != null ? hint.toString() : null;
|
getNodeText().mHint = hint != null ? hint.toString() : null;
|
||||||
|
|||||||
@@ -177,6 +177,17 @@ public abstract class ViewStructure {
|
|||||||
*/
|
*/
|
||||||
public abstract void setTextStyle(float size, int fgColor, int bgColor, int style);
|
public abstract void setTextStyle(float size, int fgColor, int bgColor, int style);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set line information for test that was previously supplied through
|
||||||
|
* {@link #setText(CharSequence)}. This provides the line breaking of the text as it
|
||||||
|
* is shown on screen. This function takes ownership of the provided arrays; you should
|
||||||
|
* not make further modification to them.
|
||||||
|
*
|
||||||
|
* @param charOffsets The offset in to {@link #setText} where a line starts.
|
||||||
|
* @param baselines The baseline where the line is drawn on screen.
|
||||||
|
*/
|
||||||
|
public abstract void setTextLines(int[] charOffsets, int[] baselines);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set optional hint text associated with this view; this is for example the text that is
|
* Set optional hint text associated with this view; this is for example the text that is
|
||||||
* shown by an EditText when it is empty to indicate to the user the kind of text to input.
|
* shown by an EditText when it is empty to indicate to the user the kind of text to input.
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ import android.graphics.Rect;
|
|||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.inputmethodservice.ExtractEditText;
|
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
@@ -116,6 +115,7 @@ import android.view.KeyCharacterMap;
|
|||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewParent;
|
||||||
import android.view.ViewStructure;
|
import android.view.ViewStructure;
|
||||||
import android.view.ViewConfiguration;
|
import android.view.ViewConfiguration;
|
||||||
import android.view.ViewDebug;
|
import android.view.ViewDebug;
|
||||||
@@ -5823,6 +5823,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
|||||||
return super.getBaseline();
|
return super.getBaseline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return getBaselineOffset() + mLayout.getLineBaseline(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getBaselineOffset() {
|
||||||
int voffset = 0;
|
int voffset = 0;
|
||||||
if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
|
if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
|
||||||
voffset = getVerticalOffset(true);
|
voffset = getVerticalOffset(true);
|
||||||
@@ -5832,7 +5836,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
|||||||
voffset -= getOpticalInsets().top;
|
voffset -= getOpticalInsets().top;
|
||||||
}
|
}
|
||||||
|
|
||||||
return getExtendedPaddingTop() + voffset + mLayout.getLineBaseline(0);
|
return getExtendedPaddingTop() + voffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -8767,7 +8771,79 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
|||||||
final boolean isPassword = hasPasswordTransformationMethod()
|
final boolean isPassword = hasPasswordTransformationMethod()
|
||||||
|| isPasswordInputType(getInputType());
|
|| isPasswordInputType(getInputType());
|
||||||
if (!isPassword) {
|
if (!isPassword) {
|
||||||
structure.setText(getText(), getSelectionStart(), getSelectionEnd());
|
if (mLayout == null) {
|
||||||
|
assumeLayout();
|
||||||
|
}
|
||||||
|
Layout layout = mLayout;
|
||||||
|
final int lineCount = layout.getLineCount();
|
||||||
|
if (lineCount <= 1) {
|
||||||
|
// Simple case: this is a single line.
|
||||||
|
structure.setText(getText(), getSelectionStart(), getSelectionEnd());
|
||||||
|
} else {
|
||||||
|
// Complex case: multi-line, could be scrolled or within a scroll container
|
||||||
|
// so some lines are not visible.
|
||||||
|
final int[] tmpCords = new int[2];
|
||||||
|
getLocationInWindow(tmpCords);
|
||||||
|
final int topWindowLocation = tmpCords[1];
|
||||||
|
View root = this;
|
||||||
|
ViewParent viewParent = getParent();
|
||||||
|
while (viewParent instanceof View) {
|
||||||
|
root = (View) viewParent;
|
||||||
|
viewParent = root.getParent();
|
||||||
|
}
|
||||||
|
final int windowHeight = root.getHeight();
|
||||||
|
final int topLine;
|
||||||
|
final int bottomLine;
|
||||||
|
if (topWindowLocation >= 0) {
|
||||||
|
// The top of the view is fully within its window; start text at line 0.
|
||||||
|
topLine = getLineAtCoordinateUnclamped(0);
|
||||||
|
bottomLine = getLineAtCoordinateUnclamped(windowHeight-1);
|
||||||
|
} else {
|
||||||
|
// The top of hte window has scrolled off the top of the window; figure out
|
||||||
|
// the starting line for this.
|
||||||
|
topLine = getLineAtCoordinateUnclamped(-topWindowLocation);
|
||||||
|
bottomLine = getLineAtCoordinateUnclamped(windowHeight-1-topWindowLocation);
|
||||||
|
}
|
||||||
|
// We want to return some contextual lines above/below the lines that are
|
||||||
|
// actually visible.
|
||||||
|
int expandedTopLine = topLine - (bottomLine-topLine)/2;
|
||||||
|
if (expandedTopLine < 0) {
|
||||||
|
expandedTopLine = 0;
|
||||||
|
}
|
||||||
|
int expandedBottomLine = bottomLine + (bottomLine-topLine)/2;
|
||||||
|
if (expandedBottomLine >= lineCount) {
|
||||||
|
expandedBottomLine = lineCount-1;
|
||||||
|
}
|
||||||
|
// Convert lines into character offsets.
|
||||||
|
int expandedTopChar = layout.getLineStart(expandedTopLine);
|
||||||
|
int expandedBottomChar = layout.getLineEnd(expandedBottomLine);
|
||||||
|
// Take into account selection -- if there is a selection, we need to expand
|
||||||
|
// the text we are returning to include that selection.
|
||||||
|
final int selStart = getSelectionStart();
|
||||||
|
final int selEnd = getSelectionEnd();
|
||||||
|
if (selStart < selEnd) {
|
||||||
|
if (selStart < expandedTopChar) {
|
||||||
|
expandedTopChar = selStart;
|
||||||
|
}
|
||||||
|
if (selEnd > expandedBottomChar) {
|
||||||
|
expandedBottomChar = selEnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Get the text and trim it to the range we are reporting.
|
||||||
|
CharSequence text = getText();
|
||||||
|
if (expandedTopChar > 0 || expandedBottomChar < text.length()) {
|
||||||
|
text = text.subSequence(expandedTopChar, expandedBottomChar);
|
||||||
|
}
|
||||||
|
structure.setText(text, selStart-expandedTopChar, selEnd-expandedTopChar);
|
||||||
|
final int[] lineOffsets = new int[bottomLine-topLine+1];
|
||||||
|
final int[] lineBaselines = new int[bottomLine-topLine+1];
|
||||||
|
final int baselineOffset = getBaselineOffset();
|
||||||
|
for (int i=topLine; i<=bottomLine; i++) {
|
||||||
|
lineOffsets[i-topLine] = layout.getLineStart(i);
|
||||||
|
lineBaselines[i-topLine] = layout.getLineBaseline(i) + baselineOffset;
|
||||||
|
}
|
||||||
|
structure.setTextLines(lineOffsets, lineBaselines);
|
||||||
|
}
|
||||||
|
|
||||||
// Extract style information that applies to the TextView as a whole.
|
// Extract style information that applies to the TextView as a whole.
|
||||||
int style = 0;
|
int style = 0;
|
||||||
@@ -9200,24 +9276,25 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
|||||||
* If provided, this ActionMode.Callback will be used to create the ActionMode when text
|
* If provided, this ActionMode.Callback will be used to create the ActionMode when text
|
||||||
* selection is initiated in this View.
|
* selection is initiated in this View.
|
||||||
*
|
*
|
||||||
* The standard implementation populates the menu with a subset of Select All, Cut, Copy,
|
* <p>The standard implementation populates the menu with a subset of Select All, Cut, Copy,
|
||||||
* Paste, Replace and Share actions, depending on what this View supports.
|
* Paste, Replace and Share actions, depending on what this View supports.
|
||||||
*
|
*
|
||||||
* A custom implementation can add new entries in the default menu in its
|
* <p>A custom implementation can add new entries in the default menu in its
|
||||||
* {@link android.view.ActionMode.Callback#onPrepareActionMode(ActionMode, Menu)} method. The
|
* {@link android.view.ActionMode.Callback#onPrepareActionMode(ActionMode, android.view.Menu)}
|
||||||
* default actions can also be removed from the menu using
|
* method. The default actions can also be removed from the menu using
|
||||||
* {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll},
|
* {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll},
|
||||||
* {@link android.R.id#cut}, {@link android.R.id#copy}, {@link android.R.id#paste},
|
* {@link android.R.id#cut}, {@link android.R.id#copy}, {@link android.R.id#paste},
|
||||||
* {@link android.R.id#replaceText} or {@link android.R.id#shareText} ids as parameters.
|
* {@link android.R.id#replaceText} or {@link android.R.id#shareText} ids as parameters.
|
||||||
*
|
*
|
||||||
* Returning false from
|
* <p>Returning false from
|
||||||
* {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, Menu)} will prevent
|
* {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, android.view.Menu)}
|
||||||
* the action mode from being started.
|
* will prevent the action mode from being started.
|
||||||
*
|
*
|
||||||
* Action click events should be handled by the custom implementation of
|
* <p>Action click events should be handled by the custom implementation of
|
||||||
* {@link android.view.ActionMode.Callback#onActionItemClicked(ActionMode, MenuItem)}.
|
* {@link android.view.ActionMode.Callback#onActionItemClicked(ActionMode,
|
||||||
|
* android.view.MenuItem)}.
|
||||||
*
|
*
|
||||||
* Note that text selection mode is not started when a TextView receives focus and the
|
* <p>Note that text selection mode is not started when a TextView receives focus and the
|
||||||
* {@link android.R.attr#selectAllOnFocus} flag has been set. The content is highlighted in
|
* {@link android.R.attr#selectAllOnFocus} flag has been set. The content is highlighted in
|
||||||
* that case, to allow for quick replacement.
|
* that case, to allow for quick replacement.
|
||||||
*/
|
*/
|
||||||
@@ -9448,6 +9525,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
|||||||
return getLayout().getLineForVertical((int) y);
|
return getLayout().getLineForVertical((int) y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getLineAtCoordinateUnclamped(float y) {
|
||||||
|
y -= getTotalPaddingTop();
|
||||||
|
y += getScrollY();
|
||||||
|
return getLayout().getLineForVertical((int) y);
|
||||||
|
}
|
||||||
|
|
||||||
int getOffsetAtCoordinate(int line, float x) {
|
int getOffsetAtCoordinate(int line, float x) {
|
||||||
x = convertToLocalHorizontalCoordinate(x);
|
x = convertToLocalHorizontalCoordinate(x);
|
||||||
return getLayout().getOffsetForHorizontal(line, x);
|
return getLayout().getOffsetForHorizontal(line, x);
|
||||||
|
|||||||
@@ -30,10 +30,17 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingTop="64dp"
|
android:paddingTop="64dp"
|
||||||
android:paddingBottom="64dp"
|
|
||||||
android:text="@string/asyncStructure"
|
android:text="@string/asyncStructure"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<EditText android:id="@+id/text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:paddingTop="64dp"
|
||||||
|
android:paddingBottom="64dp"
|
||||||
|
android:text="@string/largetext" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,4 +30,233 @@
|
|||||||
<string name="cancelVoice">Cancel</string>
|
<string name="cancelVoice">Cancel</string>
|
||||||
<string name="jumpOut">Jump out</string>
|
<string name="jumpOut">Jump out</string>
|
||||||
|
|
||||||
|
<string name="largetext">This is a bunch of text that we will use to show how we handle it
|
||||||
|
when reporting it for assist data. We need many many lines of text, like\n
|
||||||
|
this\n
|
||||||
|
and\n
|
||||||
|
this other\n
|
||||||
|
one\n
|
||||||
|
two\n
|
||||||
|
three\n
|
||||||
|
four\n
|
||||||
|
five\n
|
||||||
|
six\n
|
||||||
|
seven\n
|
||||||
|
eight\n
|
||||||
|
nine\n
|
||||||
|
ten\n
|
||||||
|
eleven\n
|
||||||
|
twelve\n
|
||||||
|
thirteen\n
|
||||||
|
fourteen\n
|
||||||
|
fifteen\n
|
||||||
|
sixteen\n
|
||||||
|
seventeen\n
|
||||||
|
eighteen\n
|
||||||
|
nineteen\n
|
||||||
|
twenty\n
|
||||||
|
<big><big><big>So shaken as we are, so wan with care,\n
|
||||||
|
Find we a time for frighted peace to pant,\n</big>
|
||||||
|
And breathe short-winded accents of new broils\n
|
||||||
|
To be commenced in strands afar remote.\n</big>
|
||||||
|
No more the thirsty entrance of this soil\n
|
||||||
|
Shall daub her lips with her own children\'s blood;\n</big>
|
||||||
|
<b>Nor more shall trenching war channel her fields,\n
|
||||||
|
Nor bruise her flowerets with the armed hoofs\n</b>
|
||||||
|
<i>Of hostile paces: those opposed eyes,\n
|
||||||
|
Which, like the meteors of a troubled heaven,\n</i>
|
||||||
|
All of one nature, of one substance bred,\n
|
||||||
|
Did lately meet in the intestine shock\n
|
||||||
|
And furious close of civil butchery\n
|
||||||
|
Shall now, in mutual well-beseeming ranks,\n
|
||||||
|
March all one way and be no more opposed\n
|
||||||
|
Against acquaintance, kindred and allies:\n
|
||||||
|
The edge of war, like an ill-sheathed knife,\n
|
||||||
|
No more shall cut his master. Therefore, friends,\n
|
||||||
|
As far as to the sepulchre of Christ,\n
|
||||||
|
Whose soldier now, under whose blessed cross\n
|
||||||
|
We are impressed and engaged to fight,\n
|
||||||
|
Forthwith a power of English shall we levy;\n
|
||||||
|
Whose arms were moulded in their mothers\' womb\n
|
||||||
|
To chase these pagans in those holy fields\n
|
||||||
|
Over whose acres walk\'d those blessed feet\n
|
||||||
|
Which fourteen hundred years ago were nail\'d\n
|
||||||
|
For our advantage on the bitter cross.\n
|
||||||
|
But this our purpose now is twelve month old,\n
|
||||||
|
And bootless \'tis to tell you we will go:\n
|
||||||
|
Therefore we meet not now. Then let me hear\n
|
||||||
|
Of you, my gentle cousin Westmoreland,\n
|
||||||
|
What yesternight our council did decree\n
|
||||||
|
In forwarding this dear expedience.\n
|
||||||
|
\n
|
||||||
|
Hear him but reason in divinity,\n
|
||||||
|
And all-admiring with an inward wish\n
|
||||||
|
You would desire the king were made a prelate:\n
|
||||||
|
Hear him debate of commonwealth affairs,\n
|
||||||
|
You would say it hath been all in all his study:\n
|
||||||
|
List his discourse of war, and you shall hear\n
|
||||||
|
A fearful battle render\'d you in music:\n
|
||||||
|
Turn him to any cause of policy,\n
|
||||||
|
The Gordian knot of it he will unloose,\n
|
||||||
|
Familiar as his garter: that, when he speaks,\n
|
||||||
|
The air, a charter\'d libertine, is still,\n
|
||||||
|
And the mute wonder lurketh in men\'s ears,\n
|
||||||
|
To steal his sweet and honey\'d sentences;\n
|
||||||
|
So that the art and practic part of life\n
|
||||||
|
Must be the mistress to this theoric:\n
|
||||||
|
Which is a wonder how his grace should glean it,\n
|
||||||
|
Since his addiction was to courses vain,\n
|
||||||
|
His companies unletter\'d, rude and shallow,\n
|
||||||
|
His hours fill\'d up with riots, banquets, sports,\n
|
||||||
|
And never noted in him any study,\n
|
||||||
|
Any retirement, any sequestration\n
|
||||||
|
From open haunts and popularity.\n
|
||||||
|
\n
|
||||||
|
I come no more to make you laugh: things now,\n
|
||||||
|
That bear a weighty and a serious brow,\n
|
||||||
|
Sad, high, and working, full of state and woe,\n
|
||||||
|
Such noble scenes as draw the eye to flow,\n
|
||||||
|
e now present. Those that can pity, here\n
|
||||||
|
May, if they think it well, let fall a tear;\n
|
||||||
|
The subject will deserve it. Such as give\n
|
||||||
|
Their money out of hope they may believe,\n
|
||||||
|
May here find truth too. Those that come to see\n
|
||||||
|
Only a show or two, and so agree\n
|
||||||
|
The play may pass, if they be still and willing,\n
|
||||||
|
I\'ll undertake may see away their shilling\n
|
||||||
|
Richly in two short hours. Only they\n
|
||||||
|
That come to hear a merry bawdy play,\n
|
||||||
|
A noise of targets, or to see a fellow\n
|
||||||
|
In a long motley coat guarded with yellow,\n
|
||||||
|
Will be deceived; for, gentle hearers, know,\n
|
||||||
|
To rank our chosen truth with such a show\n
|
||||||
|
As fool and fight is, beside forfeiting\n
|
||||||
|
Our own brains, and the opinion that we bring,\n
|
||||||
|
To make that only true we now intend,\n
|
||||||
|
Will leave us never an understanding friend.\n
|
||||||
|
Therefore, for goodness\' sake, and as you are known\n
|
||||||
|
The first and happiest hearers of the town,\n
|
||||||
|
Be sad, as we would make ye: think ye see\n
|
||||||
|
The very persons of our noble story\n
|
||||||
|
As they were living; think you see them great,\n
|
||||||
|
And follow\'d with the general throng and sweat\n
|
||||||
|
Of thousand friends; then in a moment, see\n
|
||||||
|
How soon this mightiness meets misery:\n
|
||||||
|
And, if you can be merry then, I\'ll say\n
|
||||||
|
A man may weep upon his wedding-day.\n
|
||||||
|
\n
|
||||||
|
<big>First, heaven be the record to my speech!\n
|
||||||
|
In the devotion of a subject\'s love,\n</big>
|
||||||
|
<b>Tendering the precious safety of my prince,\n
|
||||||
|
And free from other misbegotten hate,\n</b>
|
||||||
|
Come I appellant to this princely presence.\n
|
||||||
|
Now, Thomas Mowbray, do I turn to thee,\n
|
||||||
|
And mark my greeting well; for what I speak\n
|
||||||
|
My body shall make good upon this earth,\n
|
||||||
|
Or my divine soul answer it in heaven.\n
|
||||||
|
Thou art a traitor and a miscreant,\n
|
||||||
|
Too good to be so and too bad to live,\n
|
||||||
|
Since the more fair and crystal is the sky,\n
|
||||||
|
The uglier seem the clouds that in it fly.\n
|
||||||
|
Once more, the more to aggravate the note,\n
|
||||||
|
With a foul traitor\'s name stuff I thy throat;\n
|
||||||
|
And wish, so please my sovereign, ere I move,\n
|
||||||
|
What my tongue speaks my right drawn sword may prove.\n
|
||||||
|
\n
|
||||||
|
Now is the winter of our discontent\n
|
||||||
|
Made glorious summer by this sun of York;\n
|
||||||
|
And all the clouds that lour\'d upon our house\n
|
||||||
|
In the deep bosom of the ocean buried.\n
|
||||||
|
Now are our brows bound with victorious wreaths;\n
|
||||||
|
Our bruised arms hung up for monuments;\n
|
||||||
|
Our stern alarums changed to merry meetings,\n
|
||||||
|
Our dreadful marches to delightful measures.\n
|
||||||
|
Grim-visaged war hath smooth\'d his wrinkled front;\n
|
||||||
|
And now, instead of mounting barded steeds\n
|
||||||
|
To fright the souls of fearful adversaries,\n
|
||||||
|
He capers nimbly in a lady\'s chamber\n
|
||||||
|
To the lascivious pleasing of a lute.\n
|
||||||
|
But I, that am not shaped for sportive tricks,\n
|
||||||
|
Nor made to court an amorous looking-glass;\n
|
||||||
|
I, that am rudely stamp\'d, and want love\'s majesty\n
|
||||||
|
To strut before a wanton ambling nymph;\n
|
||||||
|
I, that am curtail\'d of this fair proportion,\n
|
||||||
|
Cheated of feature by dissembling nature,\n
|
||||||
|
Deformed, unfinish\'d, sent before my time\n
|
||||||
|
Into this breathing world, scarce half made up,\n
|
||||||
|
And that so lamely and unfashionable\n
|
||||||
|
That dogs bark at me as I halt by them;\n
|
||||||
|
Why, I, in this weak piping time of peace,\n
|
||||||
|
Have no delight to pass away the time,\n
|
||||||
|
Unless to spy my shadow in the sun\n
|
||||||
|
And descant on mine own deformity:\n
|
||||||
|
And therefore, since I cannot prove a lover,\n
|
||||||
|
To entertain these fair well-spoken days,\n
|
||||||
|
I am determined to prove a villain\n
|
||||||
|
And hate the idle pleasures of these days.\n
|
||||||
|
Plots have I laid, inductions dangerous,\n
|
||||||
|
By drunken prophecies, libels and dreams,\n
|
||||||
|
To set my brother Clarence and the king\n
|
||||||
|
In deadly hate the one against the other:\n
|
||||||
|
And if King Edward be as true and just\n
|
||||||
|
As I am subtle, false and treacherous,\n
|
||||||
|
This day should Clarence closely be mew\'d up,\n
|
||||||
|
About a prophecy, which says that \'G\'\n
|
||||||
|
Of Edward\'s heirs the murderer shall be.\n
|
||||||
|
Dive, thoughts, down to my soul: here\n
|
||||||
|
Clarence comes.\n
|
||||||
|
\n
|
||||||
|
To bait fish withal: if it will feed nothing else,\n
|
||||||
|
it will feed my revenge. He hath disgraced me, and\n
|
||||||
|
hindered me half a million; laughed at my losses,\n
|
||||||
|
mocked at my gains, scorned my nation, thwarted my\n
|
||||||
|
bargains, cooled my friends, heated mine\n
|
||||||
|
enemies; and what\'s his reason? I am a Jew. Hath\n
|
||||||
|
not a Jew eyes? hath not a Jew hands, organs,\n
|
||||||
|
dimensions, senses, affections, passions? fed with\n
|
||||||
|
the same food, hurt with the same weapons, subject\n
|
||||||
|
to the same diseases, healed by the same means,\n
|
||||||
|
warmed and cooled by the same winter and summer, as\n
|
||||||
|
a Christian is? If you prick us, do we not bleed?\n
|
||||||
|
if you tickle us, do we not laugh? if you poison\n
|
||||||
|
us, do we not die? and if you wrong us, shall we not\n
|
||||||
|
revenge? If we are like you in the rest, we will\n
|
||||||
|
resemble you in that. If a Jew wrong a Christian,\n
|
||||||
|
what is his humility? Revenge. If a Christian\n
|
||||||
|
wrong a Jew, what should his sufferance be by\n
|
||||||
|
Christian example? Why, revenge. The villany you\n
|
||||||
|
teach me, I will execute, and it shall go hard but I\n
|
||||||
|
will better the instruction.\n
|
||||||
|
\n
|
||||||
|
Virtue! a fig! \'tis in ourselves that we are thus\n
|
||||||
|
or thus. Our bodies are our gardens, to the which\n
|
||||||
|
our wills are gardeners: so that if we will plant\n
|
||||||
|
nettles, or sow lettuce, set hyssop and weed up\n
|
||||||
|
thyme, supply it with one gender of herbs, or\n
|
||||||
|
distract it with many, either to have it sterile\n
|
||||||
|
with idleness, or manured with industry, why, the\n
|
||||||
|
power and corrigible authority of this lies in our\n
|
||||||
|
wills. If the balance of our lives had not one\n
|
||||||
|
scale of reason to poise another of sensuality, the\n
|
||||||
|
blood and baseness of our natures would conduct us\n
|
||||||
|
to most preposterous conclusions: but we have\n
|
||||||
|
reason to cool our raging motions, our carnal\n
|
||||||
|
stings, our unbitted lusts, whereof I take this that\n
|
||||||
|
you call love to be a sect or scion.\n
|
||||||
|
\n
|
||||||
|
Blow, winds, and crack your cheeks! rage! blow!\n
|
||||||
|
You cataracts and hurricanoes, spout\n
|
||||||
|
Till you have drench\'d our steeples, drown\'d the cocks!\n
|
||||||
|
You sulphurous and thought-executing fires,\n
|
||||||
|
Vaunt-couriers to oak-cleaving thunderbolts,\n
|
||||||
|
Singe my white head! And thou, all-shaking thunder,\n
|
||||||
|
Smite flat the thick rotundity o\' the world!\n
|
||||||
|
Crack nature\'s moulds, an germens spill at once,\n
|
||||||
|
That make ingrateful man!
|
||||||
|
5...\n
|
||||||
|
4...\n
|
||||||
|
3...\n
|
||||||
|
2...\n
|
||||||
|
1...\n
|
||||||
|
BEEEEEEEEEEEEEEEEEP!</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ public class AssistVisualizer extends View {
|
|||||||
final Matrix matrix;
|
final Matrix matrix;
|
||||||
final String className;
|
final String className;
|
||||||
final CharSequence text;
|
final CharSequence text;
|
||||||
|
final int scrollY;
|
||||||
|
final int[] lineCharOffsets;
|
||||||
|
final int[] lineBaselines;
|
||||||
|
|
||||||
TextEntry(AssistStructure.ViewNode node, int parentLeft, int parentTop, Matrix matrix) {
|
TextEntry(AssistStructure.ViewNode node, int parentLeft, int parentTop, Matrix matrix) {
|
||||||
int left = parentLeft+node.getLeft();
|
int left = parentLeft+node.getLeft();
|
||||||
@@ -48,16 +51,19 @@ public class AssistVisualizer extends View {
|
|||||||
this.matrix = new Matrix(matrix);
|
this.matrix = new Matrix(matrix);
|
||||||
this.className = node.getClassName();
|
this.className = node.getClassName();
|
||||||
this.text = node.getText() != null ? node.getText() : node.getContentDescription();
|
this.text = node.getText() != null ? node.getText() : node.getContentDescription();
|
||||||
|
this.scrollY = node.getScrollY();
|
||||||
|
this.lineCharOffsets = node.getTextLineCharOffsets();
|
||||||
|
this.lineBaselines = node.getTextLineBaselines();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AssistStructure mAssistStructure;
|
AssistStructure mAssistStructure;
|
||||||
final Paint mFramePaint = new Paint();
|
final Paint mFramePaint = new Paint();
|
||||||
|
final Paint mFrameBaselinePaint = new Paint();
|
||||||
final Paint mFrameNoTransformPaint = new Paint();
|
final Paint mFrameNoTransformPaint = new Paint();
|
||||||
final ArrayList<Matrix> mMatrixStack = new ArrayList<>();
|
final ArrayList<Matrix> mMatrixStack = new ArrayList<>();
|
||||||
final ArrayList<TextEntry> mTextRects = new ArrayList<>();
|
final ArrayList<TextEntry> mTextRects = new ArrayList<>();
|
||||||
final int[] mTmpLocation = new int[2];
|
final int[] mTmpLocation = new int[2];
|
||||||
final float[] mTmpMatrixPoint = new float[2];
|
|
||||||
|
|
||||||
public AssistVisualizer(Context context, @Nullable AttributeSet attrs) {
|
public AssistVisualizer(Context context, @Nullable AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
@@ -65,6 +71,9 @@ public class AssistVisualizer extends View {
|
|||||||
mFramePaint.setColor(0xffff0000);
|
mFramePaint.setColor(0xffff0000);
|
||||||
mFramePaint.setStyle(Paint.Style.STROKE);
|
mFramePaint.setStyle(Paint.Style.STROKE);
|
||||||
mFramePaint.setStrokeWidth(0);
|
mFramePaint.setStrokeWidth(0);
|
||||||
|
mFrameBaselinePaint.setColor(0xa0b0b000);
|
||||||
|
mFrameBaselinePaint.setStyle(Paint.Style.STROKE);
|
||||||
|
mFrameBaselinePaint.setStrokeWidth(0);
|
||||||
float density = getResources().getDisplayMetrics().density;
|
float density = getResources().getDisplayMetrics().density;
|
||||||
mFramePaint.setShadowLayer(density, density, density, 0xff000000);
|
mFramePaint.setShadowLayer(density, density, density, 0xff000000);
|
||||||
mFrameNoTransformPaint.setColor(0xff0000ff);
|
mFrameNoTransformPaint.setColor(0xff0000ff);
|
||||||
@@ -106,6 +115,14 @@ public class AssistVisualizer extends View {
|
|||||||
+ " in " + te.parentLeft + "," + te.parentTop
|
+ " in " + te.parentLeft + "," + te.parentTop
|
||||||
+ " matrix=" + te.matrix.toShortString() + ": "
|
+ " matrix=" + te.matrix.toShortString() + ": "
|
||||||
+ te.text);
|
+ te.text);
|
||||||
|
if (te.lineCharOffsets != null && te.lineBaselines != null) {
|
||||||
|
final int num = te.lineCharOffsets.length < te.lineBaselines.length
|
||||||
|
? te.lineCharOffsets.length : te.lineBaselines.length;
|
||||||
|
for (int j=0; j<num; j++) {
|
||||||
|
Log.d(TAG, " Line #" + j + ": offset=" + te.lineCharOffsets[j]
|
||||||
|
+ " baseline=" + te.lineBaselines[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,6 +188,13 @@ public class AssistVisualizer extends View {
|
|||||||
canvas.concat(te.matrix);
|
canvas.concat(te.matrix);
|
||||||
canvas.drawRect(0, 0, te.bounds.right - te.bounds.left, te.bounds.bottom - te.bounds.top,
|
canvas.drawRect(0, 0, te.bounds.right - te.bounds.left, te.bounds.bottom - te.bounds.top,
|
||||||
mFramePaint);
|
mFramePaint);
|
||||||
|
if (te.lineBaselines != null) {
|
||||||
|
for (int j=0; j<te.lineBaselines.length; j++) {
|
||||||
|
canvas.drawLine(0, te.lineBaselines[j] - te.scrollY,
|
||||||
|
te.bounds.right - te.bounds.left, te.lineBaselines[j] - te.scrollY,
|
||||||
|
mFrameBaselinePaint);
|
||||||
|
}
|
||||||
|
}
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user