128

Is there a way to allow the user to select / copy text in a TextView? I need the same functionality of EditText where you can long-press the control and get the popup options of select all / copy, but I need the control to look like a TextView.

Tried a few things like making an EditText use the editable="none" option or inputType="none", but those still retain the framed background of an EditText, which I don't want,

Thanks

------- Update ----------------------

This is 99% there, all I'd want is for the selection hilight to be visible (the orange stuff). Other than that it's good, could live with this though:

<EditText 
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:editable="false"
  style="?android:attr/textViewStyle"
  android:textColor="@color/white"
  android:textAppearance="@android:style/TextAppearance.Medium"
  android:cursorVisible="false"
  android:background="@null" />

I guess it's being caused because of cursorVisible="false" but without that the cursor is present even without any selection being made.

user291701
  • 38,411
  • 72
  • 187
  • 285
  • An alternative would be to use a WebView instead of a TextView to display the text. – aleb May 29 '13 at 23:11
  • [http://stackoverflow.com/questions/18042308/new-selectable-textview-in-android-3-api-level-11-component][1] [1]: http://stackoverflow.com/questions/18042308/new-selectable-textview-in-android-3-api-level-11-component – ali shekari Aug 04 '13 at 11:22
  • http://stackoverflow.com/questions/18042308/new-selectable-textview-in-android-3-api-level-11-component – ali shekari Aug 04 '13 at 11:24

10 Answers10

260

android:textIsSelectable works (at least in ICS - I haven't yet checked in earlier versions)

<TextView
    android:id="@+id/deviceIdTV"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textIsSelectable="true"
    android:text="" />
Milind
  • 2,760
  • 1
  • 16
  • 12
73

Text View needs to be enabled, focusable, longClickable and textIsSelectable

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text=""
    android:id="@+id/pwTextView"
    android:enabled="true"
    android:textIsSelectable="true"
    android:focusable="true"
    android:longClickable="true" />
Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
skd
  • 731
  • 5
  • 2
  • 1
    This is the best solution. – Brave Jun 26 '16 at 20:05
  • 12
    Why `textIsSelectable`is not enough ? it's works for me with only this option – herau Nov 15 '16 at 12:37
  • 6
    Or you can use `textview.setTextIsSelectable(true)` in the code java code. – berrytchaks Mar 14 '18 at 19:25
  • 1
    Just using `textIsSelectableis` do the job for me – crgarridos Apr 05 '18 at 19:46
  • 1
    somehow, `textIsSelectable` works for some cases, but not others. Sometimes, the same layout does not always work with just textIsSelectable but a different text. However, this solution does not seem to make it work better, so the issue might be coming from somewhere else. – Simon Ninon Jul 06 '18 at 22:39
23

I think I have a better solution. Just call
registerForContextMenu(yourTextView);

and your TextView will be registered for receiving context menu events.

Then override onCreateContextMenu in your Activity

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    //user has long pressed your TextView
    menu.add(0, v.getId(), 0, "text that you want to show in the context menu - I use simply Copy");

    //cast the received View to TextView so that you can get its text
    TextView yourTextView = (TextView) v;

    //place your TextView's text in clipboard
    ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); 
    clipboard.setText(yourTextView.getText());
}

Hope this helps you and anyone else looking for a way to copy text from a TextView

pandre
  • 6,685
  • 7
  • 42
  • 50
  • Where does this allow the user to select which bits of text are copied? Doesn't it just copy everything, which isn't the original question? – James Moore Jul 01 '11 at 23:56
  • 4
    It's probably good to note that this causes the text to be copied immediately, regardless of whether or not they select "Copy" from the menu. In order to copy only when the appropriate item was selected, you'd need to override onContextItemSelected() as well, or add a click handler to the menu item. – Faisal Jul 14 '11 at 17:19
  • `ClipboardManager.setText(CharSequence text)` was deprecated in API level 11. Use `setPrimaryClip(ClipData)` instead. This creates a ClippedItem holding the given text and sets it as the primary clip. It has no label or icon. Good reading about copy-paste: [link](https://developer.android.com/guide/topics/text/copy-paste.html) – Marilia Aug 17 '16 at 21:06
  • I want to open dialog after text selection. So can you provide any suggestion for it ? – Anand Savjani Sep 02 '16 at 18:22
12
textview1.setTextIsSelectable(true);

This will enable user to select and copy text on long clicking or as we do usually

Amitoj
  • 171
  • 2
  • 15
10

Using Kotlin Programmatically (Manual Copy)

button.setTextIsSelectable(true)

Or, add a Kotlin property extension

var TextView.selectable
    get() = isTextSelectable
    set(value) = setTextIsSelectable(value)

Then call

textview.selectable = true
// or
if (textview.selectable) { ...

Using Kotlin Programmatically (Auto-Copy)

If you want to auto-copy when user long-presses you view, this is the base code required:

myView.setOnLongClickListener {  
    val clipboardManager = context.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
    val clip = ClipData.newPlainText("Copied String", myString)
    clipboardManager.setPrimaryClip(clip)
    true // Or false if not consumed
}

You may want to add a Toast to confirm it happened

Or, add a Kotlin extension function

myView.copyOnHold() // pass custom string to not use view contents

fun TextView.copyOnHold(customText: String? = null) {
    setOnLongClickListener {
        val clipboardManager = context.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
        val clip = ClipData.newPlainText("Copied String", customText ?: text)
        clipboardManager.setPrimaryClip(clip)
        true // Or false if not consumed
    }
}

Using Xml (Manual Copy)

Add this to your <TextView>

android:textIsSelectable="true"

NOTE: All of these require android:enabled="true" and android:focusable="true", which are the default values for a TextView.

Gibolt
  • 42,564
  • 15
  • 187
  • 127
6

I'm trying to implement the same, and your question helped me to set my editext layout correctly. So Thanks! :)

Then I realized, that the highlight will actually be visible if the cursor is on. But I just like you do not want to see a cursor before long clicking on the text, so I hide the cursor in the layout.xml file just like you, and added an eventlistener for long click and display the cursor only when a selection starts.

So add the listener in your Activity in the onCreate section:

public TextView htmltextview;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ...

    htmltextview.setOnLongClickListener(new OnLongClickListener(){

        public boolean onLongClick(View v) {
            htmltextview.setCursorVisible(true);
            return false;
        }
    });

}

And voilá, no cursor at the beginning, and if you long-click, the cursor appears with the selection boundaries.

I hope I could help.

Cheers, fm

fmarton
  • 336
  • 2
  • 6
5

I was also trying to do something similar but still needed a custom approach with manipulation of highlighting of text in TextView. I triggered highlight and copying on LongClick action.

This is how I managed using SpannableString:

SpannableString highlightString = new SpannableString(textView.getText());
highlightString.setSpan(new BackgroundColorSpan(ContextCompat.getColor(getActivity(), R.color.gray))
            , 0, textView.getText().length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
textView.setText(highlightString);
copyToClipboard(urlToShare);

and the copy function:

public void copyToClipboard(String copyText) {
    ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
    ClipData clip = ClipData.newPlainText("url", copyText);
    clipboard.setPrimaryClip(clip);
    Toast toast = Toast.makeText(getActivity(), "Link is copied", Toast.LENGTH_SHORT);
    toast.show();
}

I hope it's helpful for someone who ends up on this question :)

Rohit5k2
  • 17,948
  • 8
  • 45
  • 57
Wahib Ul Haq
  • 4,185
  • 3
  • 44
  • 41
  • UI Hqaq What is the "urlToShare" that you mention above? Should you do this instead: "coptToClipboard(textView)"? – AJW Apr 12 '22 at 03:09
0

I have found it doesn't work the first time I double click, but it works there after ( at least in android 11). This told me it needed to get focus. So, in the onCreate event, I first made the text view selectable, then I requested the focus to shift to the text view. Now I'm not saying the text view can lose focus and the first attempted selection will work. Not guaranteed. What is guaranteed is once it has focus, it'll work every time until it loses focus again. Don't forget about androids animations. So allow at least a half second for the non overridable animation to play out when the keyboard is hiding.

// In onCreate

TextView1.setTextIsSelectable( true );
// Allow animations to play out. 

    timer = new TimerTask() {
        @Override
        public void run() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    TextView1.requestFocus();
                }
            });
        }
    };
    _timer.schedule(timer, (int)(1000));
    }
0

Thanks a lot gilbot for your explanation. I just want to add another thing.

Selected text background color follows your app theme's colorAccent

For example check the image below

styles.xml

Here AppTheme is my application theme.

<item name="colorAccent">@color/cold</item>

and the colorAccent value will be the selected text background color.

-4

Just use this simple library: GitHub: Selectable TextView

Sadeq Shajary
  • 427
  • 6
  • 17