summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Gilles Debunne <debunne@google.com> 2010-11-12 12:23:00 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2010-11-12 12:23:00 -0800
commite7b73d297499bd71bc556aeaf5129f565b90599c (patch)
treecba6744a4fefe3737d4990447f8d540074a0e567
parent56a102c02e7af0f8a9a52b2a33452abaeeacb1da (diff)
parent86b9c78e3e4ecf56cd999faaf3f67d66137b2f05 (diff)
Merge "Added a flag for TextView that allows for text selection in read-only TextViews."
-rw-r--r--api/current.xml35
-rw-r--r--core/java/android/widget/TextView.java104
-rwxr-xr-xcore/res/res/values/attrs.xml7
-rw-r--r--core/res/res/values/public.xml7
4 files changed, 143 insertions, 10 deletions
diff --git a/api/current.xml b/api/current.xml
index 992302048277..fcb0c0e114d3 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -9425,6 +9425,17 @@
visibility="public"
>
</field>
+<field name="textIsSelectable"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843558"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="textLineHeight"
type="int"
transient="false"
@@ -243415,6 +243426,17 @@
<parameter name="attrs" type="android.content.res.TypedArray">
</parameter>
</method>
+<method name="getTextIsSelectable"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getTextScaleX"
return="float"
abstract="false"
@@ -244583,6 +244605,19 @@
<parameter name="colors" type="android.content.res.ColorStateList">
</parameter>
</method>
+<method name="setTextIsSelectable"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="selectable" type="boolean">
+</parameter>
+</method>
<method name="setTextKeepState"
return="void"
abstract="false"
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index fdd75d5aa6cf..5320b101ca45 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -66,6 +66,7 @@ import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.TextWatcher;
+import android.text.method.ArrowKeyMovementMethod;
import android.text.method.DateKeyListener;
import android.text.method.DateTimeKeyListener;
import android.text.method.DialerKeyListener;
@@ -755,6 +756,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (lineHeight != 0) {
setLineHeight(lineHeight);
}
+ break;
+
+ case com.android.internal.R.styleable.TextView_textIsSelectable:
+ mTextIsSelectable = a.getBoolean(attr, false);
+ break;
}
}
a.recycle();
@@ -844,6 +850,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mInput = TextKeyListener.getInstance(autotext, cap);
mInputType = inputType;
+ } else if (mTextIsSelectable) {
+ // Prevent text changes from keyboard.
+ mInputType = EditorInfo.TYPE_NULL;
+ mInput = null;
+ bufferType = BufferType.SPANNABLE;
+ setFocusableInTouchMode(true);
+ // So that selection can be changed using arrow keys and touch is handled.
+ setMovementMethod(ArrowKeyMovementMethod.getInstance());
} else if (editable) {
mInput = TextKeyListener.getInstance();
mInputType = EditorInfo.TYPE_CLASS_TEXT;
@@ -1098,6 +1112,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* within the text can cause individual lines to be taller or shorter
* than this height, and the layout may contain additional first-
* or last-line padding.
+ *
+ * @attr ref android.R.styleable#TextView_textLineHeight
*/
public int getLineHeight() {
if (mLineHeight != 0) {
@@ -4028,6 +4044,71 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return false;
}
+ /**
+ * When a TextView is used to display a useful piece of information to the user (such as a
+ * contact's address), it should be made selectable, so that the user can select and copy this
+ * content.
+ *
+ * Use {@link #setTextIsSelectable(boolean)} or the
+ * {@link android.R.styleable#TextView_textIsSelectable} XML attribute to make this TextView
+ * selectable (the text is not selectable by default). Note that the content of an EditText is
+ * always selectable.
+ *
+ * @return True if the text displayed in this TextView can be selected by the user.
+ *
+ * @attr ref android.R.styleable#TextView_textIsSelectable
+ */
+ public boolean isTextSelectable() {
+ return mTextIsSelectable;
+ }
+
+ /**
+ * Sets whether or not (default) the content of this view is selectable by the user.
+ *
+ * See {@link #isTextSelectable} for details.
+ *
+ * @param selectable Whether or not the content of this TextView should be selectable.
+ */
+ public void setTextIsSelectable(boolean selectable) {
+ if (mTextIsSelectable == selectable) return;
+
+ mTextIsSelectable = selectable;
+
+ setFocusableInTouchMode(selectable);
+ setFocusable(selectable);
+ setClickable(selectable);
+ setLongClickable(selectable);
+
+ // mInputType is already EditorInfo.TYPE_NULL and mInput is null;
+
+ setMovementMethod(selectable ? ArrowKeyMovementMethod.getInstance() : null);
+ setText(getText(), selectable ? BufferType.SPANNABLE : BufferType.NORMAL);
+
+ // Called by setText above, but safer in case of future code changes
+ prepareCursorControllers();
+ }
+
+ @Override
+ protected int[] onCreateDrawableState(int extraSpace) {
+ final int[] drawableState = super.onCreateDrawableState(extraSpace);
+ if (mTextIsSelectable) {
+ // Disable pressed state, which was introduced when TextView was made clickable.
+ // Prevents text color change.
+ // setClickable(false) would have a similar effect, but it also disables focus changes
+ // and long press actions, which are both needed by text selection.
+ final int length = drawableState.length;
+ for (int i = 0; i < length; i++) {
+ if (drawableState[i] == R.attr.state_pressed) {
+ final int[] nonPressedState = new int[length - 1];
+ System.arraycopy(drawableState, 0, nonPressedState, 0, i);
+ System.arraycopy(drawableState, i + 1, nonPressedState, i, length - i - 1);
+ return nonPressedState;
+ }
+ }
+ }
+ return drawableState;
+ }
+
@Override
protected void onDraw(Canvas canvas) {
if (mCurrentAlpha <= ViewConfiguration.ALPHA_THRESHOLD_INT) return;
@@ -4190,12 +4271,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
selStart = getSelectionStart();
selEnd = getSelectionEnd();
- if (mCursorVisible && selStart >= 0 && isEnabled()) {
+ if ((mCursorVisible || mTextIsSelectable) && selStart >= 0 && isEnabled()) {
if (mHighlightPath == null)
mHighlightPath = new Path();
if (selStart == selEnd) {
- if ((SystemClock.uptimeMillis() - mShowCursor) % (2 * BLINK) < BLINK) {
+ if (!mTextIsSelectable &&
+ (SystemClock.uptimeMillis() - mShowCursor) % (2 * BLINK) < BLINK) {
if (mHighlightPathBogus) {
mHighlightPath.reset();
mLayout.getCursorPath(selStart, mHighlightPath, mText);
@@ -7011,9 +7093,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mSelectionModifierCursorController.updatePosition();
}
}
- if (action == MotionEvent.ACTION_UP && isFocused() && !mScrolled) {
+ if (action == MotionEvent.ACTION_UP && !mScrolled && isFocused()) {
InputMethodManager imm = (InputMethodManager)
- getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
CommitSelectionReceiver csr = null;
if (getSelectionStart() != oldSelStart || getSelectionEnd() != oldSelEnd ||
@@ -7047,7 +7129,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|| windowParams.type > WindowManager.LayoutParams.LAST_SUB_WINDOW;
}
- if (windowSupportsHandles && isTextEditable() && mCursorVisible && mLayout != null) {
+ if (windowSupportsHandles && isTextEditable() && mCursorVisible && mLayout != null &&
+ !mTextIsSelectable) {
if (mInsertionPointCursorController == null) {
mInsertionPointCursorController = new InsertionPointCursorController();
}
@@ -7070,10 +7153,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
- * @return True iff this TextView contains a text that can be edited.
+ * @return True iff this TextView contains a text that can be edited, or if this is
+ * a selectable TextView.
*/
private boolean isTextEditable() {
- return mText instanceof Editable && onCheckIsTextEditor() && isEnabled();
+ return (mText instanceof Editable && onCheckIsTextEditor() && isEnabled())
+ || mTextIsSelectable;
}
/**
@@ -7320,9 +7405,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// prepareCursorController() relies on this method.
// If you change this condition, make sure prepareCursorController is called anywhere
// the value of this condition might be changed.
- return (mText instanceof Spannable &&
- mMovement != null &&
- mMovement.canSelectArbitrarily());
+ return (mText instanceof Spannable && mMovement != null && mMovement.canSelectArbitrarily());
}
private boolean canCut() {
@@ -8883,6 +8966,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private float mSpacingMult = 1;
private float mSpacingAdd = 0;
private int mLineHeight = 0;
+ private boolean mTextIsSelectable = false;
private static final int LINES = 1;
private static final int EMS = LINES;
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 7ff75b36a395..d3052605b5ef 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -635,6 +635,10 @@
<!-- Height of a line of text. -->
<attr name="textLineHeight" format="dimension" />
+ <!-- Indicates that the content of a non-editable TextView can be selected.
+ Default value is false. EditText content is always selectable. -->
+ <attr name="textIsSelectable" format="boolean" />
+
<!-- Where to ellipsize text. -->
<attr name="ellipsize">
<enum name="none" value="0" />
@@ -2477,6 +2481,9 @@
<!-- Height of a line of text. -->
<attr name="textLineHeight" />
+ <!-- Indicates that a non-editable text can be selected. -->
+ <attr name="textIsSelectable" />
+
</declare-styleable>
<!-- An <code>input-extras</code> is a container for extra data to supply to
an input method. Contains
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index bf0ac47bd239..01d2bba0840f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1440,4 +1440,11 @@
<public type="style" name="Theme.Holo.DialogWhenLarge" />
<public type="string" name="selectTextMode" />
+
+ <public type="attr" name="actionModeCutDrawable" />
+ <public type="attr" name="actionModeCopyDrawable" />
+ <public type="attr" name="actionModePasteDrawable" />
+ <public type="attr" name="textEditPasteWindowLayout" />
+ <public type="attr" name="textEditNoPasteWindowLayout" />
+ <public type="attr" name="textIsSelectable" />
</resources>