Loading core/java/android/text/method/LinkMovementMethod.java +30 −33 Original line number Diff line number Diff line Loading @@ -29,6 +29,9 @@ import android.widget.TextView; /** * A movement method that traverses links in the text buffer and scrolls if necessary. * Supports clicking on links with DPad Center or Enter. * * <p>Note: Starting from Android 8.0 (API level 25) this class no longer handles the touch * clicks. */ public class LinkMovementMethod extends ScrollingMovementMethod { private static final int CLICK = 1; Loading Loading @@ -98,14 +101,14 @@ public class LinkMovementMethod extends ScrollingMovementMethod { int padding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom(); int areatop = widget.getScrollY(); int areabot = areatop + widget.getHeight() - padding; int areaTop = widget.getScrollY(); int areaBot = areaTop + widget.getHeight() - padding; int linetop = layout.getLineForVertical(areatop); int linebot = layout.getLineForVertical(areabot); int lineTop = layout.getLineForVertical(areaTop); int lineBot = layout.getLineForVertical(areaBot); int first = layout.getLineStart(linetop); int last = layout.getLineEnd(linebot); int first = layout.getLineStart(lineTop); int last = layout.getLineEnd(lineBot); ClickableSpan[] candidates = buffer.getSpans(first, last, ClickableSpan.class); Loading Loading @@ -141,46 +144,46 @@ public class LinkMovementMethod extends ScrollingMovementMethod { break; case UP: int beststart, bestend; int bestStart, bestEnd; beststart = -1; bestend = -1; bestStart = -1; bestEnd = -1; for (int i = 0; i < candidates.length; i++) { int end = buffer.getSpanEnd(candidates[i]); if (end < selEnd || selStart == selEnd) { if (end > bestend) { beststart = buffer.getSpanStart(candidates[i]); bestend = end; if (end > bestEnd) { bestStart = buffer.getSpanStart(candidates[i]); bestEnd = end; } } } if (beststart >= 0) { Selection.setSelection(buffer, bestend, beststart); if (bestStart >= 0) { Selection.setSelection(buffer, bestEnd, bestStart); return true; } break; case DOWN: beststart = Integer.MAX_VALUE; bestend = Integer.MAX_VALUE; bestStart = Integer.MAX_VALUE; bestEnd = Integer.MAX_VALUE; for (int i = 0; i < candidates.length; i++) { int start = buffer.getSpanStart(candidates[i]); if (start > selStart || selStart == selEnd) { if (start < beststart) { beststart = start; bestend = buffer.getSpanEnd(candidates[i]); if (start < bestStart) { bestStart = start; bestEnd = buffer.getSpanEnd(candidates[i]); } } } if (bestend < Integer.MAX_VALUE) { Selection.setSelection(buffer, beststart, bestend); if (bestEnd < Integer.MAX_VALUE) { Selection.setSelection(buffer, bestStart, bestEnd); return true; } Loading @@ -195,8 +198,7 @@ public class LinkMovementMethod extends ScrollingMovementMethod { MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) { if (action == MotionEvent.ACTION_DOWN) { int x = (int) event.getX(); int y = (int) event.getY(); Loading @@ -210,17 +212,12 @@ public class LinkMovementMethod extends ScrollingMovementMethod { int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); ClickableSpan[] links = buffer.getSpans(off, off, ClickableSpan.class); if (link.length != 0) { if (action == MotionEvent.ACTION_UP) { link[0].onClick(widget); } else if (action == MotionEvent.ACTION_DOWN) { if (links.length != 0) { Selection.setSelection(buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0])); } buffer.getSpanStart(links[0]), buffer.getSpanEnd(links[0])); return true; } else { Selection.removeSelection(buffer); Loading core/java/android/widget/TextView.java +22 −13 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ import android.view.ActionMode; import android.view.Choreographer; import android.view.ContextMenu; import android.view.DragEvent; import android.view.GestureDetector; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.KeyCharacterMap; Loading Loading @@ -650,6 +651,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ private Editor mEditor; private final GestureDetector mClickableSpanOnClickGestureDetector; private static final int DEVICE_PROVISIONED_UNKNOWN = 0; private static final int DEVICE_PROVISIONED_NO = 1; private static final int DEVICE_PROVISIONED_YES = 2; Loading Loading @@ -1488,6 +1491,24 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); } mClickableSpanOnClickGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapConfirmed(MotionEvent e) { if (mLinksClickable && (mMovement != null) && (mMovement instanceof LinkMovementMethod || (mAutoLinkMask != 0 && isTextSelectable()))) { ClickableSpan[] links = ((Spannable) mText).getSpans( getSelectionStart(), getSelectionEnd(), ClickableSpan.class); if (links.length > 0) { links[0].onClick(TextView.this); return true; } } return false; } }); } private int[] parseDimensionArray(TypedArray dimens) { Loading Loading @@ -8515,21 +8536,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mMovement != null) { handled |= mMovement.onTouchEvent(this, (Spannable) mText, event); } handled |= mClickableSpanOnClickGestureDetector.onTouchEvent(event); final boolean textIsSelectable = isTextSelectable(); if (touchIsFinished && mLinksClickable && mAutoLinkMask != 0 && textIsSelectable) { // The LinkMovementMethod which should handle taps on links has not been installed // on non editable text that support text selection. // We reproduce its behavior here to open links for these. ClickableSpan[] links = ((Spannable) mText).getSpans(getSelectionStart(), getSelectionEnd(), ClickableSpan.class); if (links.length > 0) { links[0].onClick(this); handled = true; } } if (touchIsFinished && (isTextEditable() || textIsSelectable)) { // Show the IME, except when selecting in read-only text. final InputMethodManager imm = InputMethodManager.peekInstance(); Loading core/tests/coretests/src/android/widget/TextViewTest.java +65 −33 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.text.Spannable; * TextViewTest tests {@link TextView}. */ public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActivity> { private TextView mTextView; public TextViewTest() { super(TextViewActivity.class); Loading @@ -37,16 +38,22 @@ public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActiv @SmallTest @Presubmit public void testArray() throws Exception { TextView tv = new TextView(getActivity()); getActivity().runOnUiThread(new Runnable() { @Override public void run() { mTextView = new TextView(getActivity()); } }); getInstrumentation().waitForIdleSync(); char[] c = new char[] { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!' }; tv.setText(c, 1, 4); CharSequence oldText = tv.getText(); mTextView.setText(c, 1, 4); CharSequence oldText = mTextView.getText(); tv.setText(c, 4, 5); CharSequence newText = tv.getText(); mTextView.setText(c, 4, 5); CharSequence newText = mTextView.getText(); assertTrue(newText == oldText); Loading @@ -67,12 +74,18 @@ public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActiv @SmallTest public void testProcessTextActivityResultNonEditable() { final TextView tv = new TextView(getActivity()); getActivity().runOnUiThread(new Runnable() { @Override public void run() { mTextView = new TextView(getActivity()); } }); getInstrumentation().waitForIdleSync(); CharSequence originalText = "This is some text."; tv.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, tv.getText().toString()); tv.setTextIsSelectable(true); Selection.setSelection((Spannable) tv.getText(), 0, tv.getText().length()); mTextView.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, mTextView.getText().toString()); mTextView.setTextIsSelectable(true); Selection.setSelection((Spannable) mTextView.getText(), 0, mTextView.getText().length()); // We need to run this in the UI thread, as it will create a Toast. getActivity().runOnUiThread(new Runnable() { Loading @@ -81,60 +94,79 @@ public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActiv CharSequence newText = "Text is replaced."; Intent data = new Intent(); data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText); tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data); mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data); } }); getInstrumentation().waitForIdleSync(); // This is a TextView, which can't be modified. Hence no change should have been made. assertEquals(originalText, tv.getText().toString()); assertEquals(originalText, mTextView.getText().toString()); } @SmallTest public void testProcessTextActivityResultEditable() { EditText tv = new EditText(getActivity()); getActivity().runOnUiThread(new Runnable() { @Override public void run() { mTextView = new EditText(getActivity()); } }); getInstrumentation().waitForIdleSync(); CharSequence originalText = "This is some text."; tv.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, tv.getText().toString()); tv.setTextIsSelectable(true); Selection.setSelection(tv.getText(), 0, tv.getText().length()); mTextView.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, mTextView.getText().toString()); mTextView.setTextIsSelectable(true); Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length()); CharSequence newText = "Text is replaced."; Intent data = new Intent(); data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText); tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data); mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data); assertEquals(newText, tv.getText().toString()); assertEquals(newText, mTextView.getText().toString()); } @SmallTest public void testProcessTextActivityResultCancel() { EditText tv = new EditText(getActivity()); getActivity().runOnUiThread(new Runnable() { @Override public void run() { mTextView = new EditText(getActivity()); } }); getInstrumentation().waitForIdleSync(); CharSequence originalText = "This is some text."; tv.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, tv.getText().toString()); tv.setTextIsSelectable(true); Selection.setSelection(tv.getText(), 0, tv.getText().length()); mTextView.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, mTextView.getText().toString()); mTextView.setTextIsSelectable(true); Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length()); CharSequence newText = "Text is replaced."; Intent data = new Intent(); data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText); tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_CANCELED, data); mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_CANCELED, data); assertEquals(originalText, tv.getText().toString()); assertEquals(originalText, mTextView.getText().toString()); } @SmallTest public void testProcessTextActivityNoData() { EditText tv = new EditText(getActivity()); getActivity().runOnUiThread(new Runnable() { @Override public void run() { mTextView = new EditText(getActivity()); } }); getInstrumentation().waitForIdleSync(); CharSequence originalText = "This is some text."; tv.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, tv.getText().toString()); tv.setTextIsSelectable(true); Selection.setSelection(tv.getText(), 0, tv.getText().length()); mTextView.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, mTextView.getText().toString()); mTextView.setTextIsSelectable(true); Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length()); tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, null); mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, null); assertEquals(originalText, tv.getText().toString()); assertEquals(originalText, mTextView.getText().toString()); } } Loading
core/java/android/text/method/LinkMovementMethod.java +30 −33 Original line number Diff line number Diff line Loading @@ -29,6 +29,9 @@ import android.widget.TextView; /** * A movement method that traverses links in the text buffer and scrolls if necessary. * Supports clicking on links with DPad Center or Enter. * * <p>Note: Starting from Android 8.0 (API level 25) this class no longer handles the touch * clicks. */ public class LinkMovementMethod extends ScrollingMovementMethod { private static final int CLICK = 1; Loading Loading @@ -98,14 +101,14 @@ public class LinkMovementMethod extends ScrollingMovementMethod { int padding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom(); int areatop = widget.getScrollY(); int areabot = areatop + widget.getHeight() - padding; int areaTop = widget.getScrollY(); int areaBot = areaTop + widget.getHeight() - padding; int linetop = layout.getLineForVertical(areatop); int linebot = layout.getLineForVertical(areabot); int lineTop = layout.getLineForVertical(areaTop); int lineBot = layout.getLineForVertical(areaBot); int first = layout.getLineStart(linetop); int last = layout.getLineEnd(linebot); int first = layout.getLineStart(lineTop); int last = layout.getLineEnd(lineBot); ClickableSpan[] candidates = buffer.getSpans(first, last, ClickableSpan.class); Loading Loading @@ -141,46 +144,46 @@ public class LinkMovementMethod extends ScrollingMovementMethod { break; case UP: int beststart, bestend; int bestStart, bestEnd; beststart = -1; bestend = -1; bestStart = -1; bestEnd = -1; for (int i = 0; i < candidates.length; i++) { int end = buffer.getSpanEnd(candidates[i]); if (end < selEnd || selStart == selEnd) { if (end > bestend) { beststart = buffer.getSpanStart(candidates[i]); bestend = end; if (end > bestEnd) { bestStart = buffer.getSpanStart(candidates[i]); bestEnd = end; } } } if (beststart >= 0) { Selection.setSelection(buffer, bestend, beststart); if (bestStart >= 0) { Selection.setSelection(buffer, bestEnd, bestStart); return true; } break; case DOWN: beststart = Integer.MAX_VALUE; bestend = Integer.MAX_VALUE; bestStart = Integer.MAX_VALUE; bestEnd = Integer.MAX_VALUE; for (int i = 0; i < candidates.length; i++) { int start = buffer.getSpanStart(candidates[i]); if (start > selStart || selStart == selEnd) { if (start < beststart) { beststart = start; bestend = buffer.getSpanEnd(candidates[i]); if (start < bestStart) { bestStart = start; bestEnd = buffer.getSpanEnd(candidates[i]); } } } if (bestend < Integer.MAX_VALUE) { Selection.setSelection(buffer, beststart, bestend); if (bestEnd < Integer.MAX_VALUE) { Selection.setSelection(buffer, bestStart, bestEnd); return true; } Loading @@ -195,8 +198,7 @@ public class LinkMovementMethod extends ScrollingMovementMethod { MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) { if (action == MotionEvent.ACTION_DOWN) { int x = (int) event.getX(); int y = (int) event.getY(); Loading @@ -210,17 +212,12 @@ public class LinkMovementMethod extends ScrollingMovementMethod { int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); ClickableSpan[] links = buffer.getSpans(off, off, ClickableSpan.class); if (link.length != 0) { if (action == MotionEvent.ACTION_UP) { link[0].onClick(widget); } else if (action == MotionEvent.ACTION_DOWN) { if (links.length != 0) { Selection.setSelection(buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0])); } buffer.getSpanStart(links[0]), buffer.getSpanEnd(links[0])); return true; } else { Selection.removeSelection(buffer); Loading
core/java/android/widget/TextView.java +22 −13 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ import android.view.ActionMode; import android.view.Choreographer; import android.view.ContextMenu; import android.view.DragEvent; import android.view.GestureDetector; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.KeyCharacterMap; Loading Loading @@ -650,6 +651,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ private Editor mEditor; private final GestureDetector mClickableSpanOnClickGestureDetector; private static final int DEVICE_PROVISIONED_UNKNOWN = 0; private static final int DEVICE_PROVISIONED_NO = 1; private static final int DEVICE_PROVISIONED_YES = 2; Loading Loading @@ -1488,6 +1491,24 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); } mClickableSpanOnClickGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapConfirmed(MotionEvent e) { if (mLinksClickable && (mMovement != null) && (mMovement instanceof LinkMovementMethod || (mAutoLinkMask != 0 && isTextSelectable()))) { ClickableSpan[] links = ((Spannable) mText).getSpans( getSelectionStart(), getSelectionEnd(), ClickableSpan.class); if (links.length > 0) { links[0].onClick(TextView.this); return true; } } return false; } }); } private int[] parseDimensionArray(TypedArray dimens) { Loading Loading @@ -8515,21 +8536,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mMovement != null) { handled |= mMovement.onTouchEvent(this, (Spannable) mText, event); } handled |= mClickableSpanOnClickGestureDetector.onTouchEvent(event); final boolean textIsSelectable = isTextSelectable(); if (touchIsFinished && mLinksClickable && mAutoLinkMask != 0 && textIsSelectable) { // The LinkMovementMethod which should handle taps on links has not been installed // on non editable text that support text selection. // We reproduce its behavior here to open links for these. ClickableSpan[] links = ((Spannable) mText).getSpans(getSelectionStart(), getSelectionEnd(), ClickableSpan.class); if (links.length > 0) { links[0].onClick(this); handled = true; } } if (touchIsFinished && (isTextEditable() || textIsSelectable)) { // Show the IME, except when selecting in read-only text. final InputMethodManager imm = InputMethodManager.peekInstance(); Loading
core/tests/coretests/src/android/widget/TextViewTest.java +65 −33 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.text.Spannable; * TextViewTest tests {@link TextView}. */ public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActivity> { private TextView mTextView; public TextViewTest() { super(TextViewActivity.class); Loading @@ -37,16 +38,22 @@ public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActiv @SmallTest @Presubmit public void testArray() throws Exception { TextView tv = new TextView(getActivity()); getActivity().runOnUiThread(new Runnable() { @Override public void run() { mTextView = new TextView(getActivity()); } }); getInstrumentation().waitForIdleSync(); char[] c = new char[] { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!' }; tv.setText(c, 1, 4); CharSequence oldText = tv.getText(); mTextView.setText(c, 1, 4); CharSequence oldText = mTextView.getText(); tv.setText(c, 4, 5); CharSequence newText = tv.getText(); mTextView.setText(c, 4, 5); CharSequence newText = mTextView.getText(); assertTrue(newText == oldText); Loading @@ -67,12 +74,18 @@ public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActiv @SmallTest public void testProcessTextActivityResultNonEditable() { final TextView tv = new TextView(getActivity()); getActivity().runOnUiThread(new Runnable() { @Override public void run() { mTextView = new TextView(getActivity()); } }); getInstrumentation().waitForIdleSync(); CharSequence originalText = "This is some text."; tv.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, tv.getText().toString()); tv.setTextIsSelectable(true); Selection.setSelection((Spannable) tv.getText(), 0, tv.getText().length()); mTextView.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, mTextView.getText().toString()); mTextView.setTextIsSelectable(true); Selection.setSelection((Spannable) mTextView.getText(), 0, mTextView.getText().length()); // We need to run this in the UI thread, as it will create a Toast. getActivity().runOnUiThread(new Runnable() { Loading @@ -81,60 +94,79 @@ public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActiv CharSequence newText = "Text is replaced."; Intent data = new Intent(); data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText); tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data); mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data); } }); getInstrumentation().waitForIdleSync(); // This is a TextView, which can't be modified. Hence no change should have been made. assertEquals(originalText, tv.getText().toString()); assertEquals(originalText, mTextView.getText().toString()); } @SmallTest public void testProcessTextActivityResultEditable() { EditText tv = new EditText(getActivity()); getActivity().runOnUiThread(new Runnable() { @Override public void run() { mTextView = new EditText(getActivity()); } }); getInstrumentation().waitForIdleSync(); CharSequence originalText = "This is some text."; tv.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, tv.getText().toString()); tv.setTextIsSelectable(true); Selection.setSelection(tv.getText(), 0, tv.getText().length()); mTextView.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, mTextView.getText().toString()); mTextView.setTextIsSelectable(true); Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length()); CharSequence newText = "Text is replaced."; Intent data = new Intent(); data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText); tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data); mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data); assertEquals(newText, tv.getText().toString()); assertEquals(newText, mTextView.getText().toString()); } @SmallTest public void testProcessTextActivityResultCancel() { EditText tv = new EditText(getActivity()); getActivity().runOnUiThread(new Runnable() { @Override public void run() { mTextView = new EditText(getActivity()); } }); getInstrumentation().waitForIdleSync(); CharSequence originalText = "This is some text."; tv.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, tv.getText().toString()); tv.setTextIsSelectable(true); Selection.setSelection(tv.getText(), 0, tv.getText().length()); mTextView.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, mTextView.getText().toString()); mTextView.setTextIsSelectable(true); Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length()); CharSequence newText = "Text is replaced."; Intent data = new Intent(); data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText); tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_CANCELED, data); mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_CANCELED, data); assertEquals(originalText, tv.getText().toString()); assertEquals(originalText, mTextView.getText().toString()); } @SmallTest public void testProcessTextActivityNoData() { EditText tv = new EditText(getActivity()); getActivity().runOnUiThread(new Runnable() { @Override public void run() { mTextView = new EditText(getActivity()); } }); getInstrumentation().waitForIdleSync(); CharSequence originalText = "This is some text."; tv.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, tv.getText().toString()); tv.setTextIsSelectable(true); Selection.setSelection(tv.getText(), 0, tv.getText().length()); mTextView.setText(originalText, TextView.BufferType.SPANNABLE); assertEquals(originalText, mTextView.getText().toString()); mTextView.setTextIsSelectable(true); Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length()); tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, null); mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, null); assertEquals(originalText, tv.getText().toString()); assertEquals(originalText, mTextView.getText().toString()); } }