diff options
| author | 2010-11-12 12:23:00 -0800 | |
|---|---|---|
| committer | 2010-11-12 12:23:00 -0800 | |
| commit | e7b73d297499bd71bc556aeaf5129f565b90599c (patch) | |
| tree | cba6744a4fefe3737d4990447f8d540074a0e567 | |
| parent | 56a102c02e7af0f8a9a52b2a33452abaeeacb1da (diff) | |
| parent | 86b9c78e3e4ecf56cd999faaf3f67d66137b2f05 (diff) | |
Merge "Added a flag for TextView that allows for text selection in read-only TextViews."
| -rw-r--r-- | api/current.xml | 35 | ||||
| -rw-r--r-- | core/java/android/widget/TextView.java | 104 | ||||
| -rwxr-xr-x | core/res/res/values/attrs.xml | 7 | ||||
| -rw-r--r-- | core/res/res/values/public.xml | 7 |
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> |