Select + copy text in a TextView?

Android

Android Problem Overview


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.

Android Solutions


Solution 1 - Android

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="" />

Solution 2 - Android

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" />

Solution 3 - Android

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

Solution 4 - Android

textview1.setTextIsSelectable(true);

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

Solution 5 - Android

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

Solution 6 - Android

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.

Solution 7 - Android

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 :)

Solution 8 - Android

Just use this simple library: GitHub: Selectable TextView

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser291701View Question on Stackoverflow
Solution 1 - AndroidMilindView Answer on Stackoverflow
Solution 2 - AndroidskdView Answer on Stackoverflow
Solution 3 - AndroidpandreView Answer on Stackoverflow
Solution 4 - AndroidAmitojView Answer on Stackoverflow
Solution 5 - AndroidfmartonView Answer on Stackoverflow
Solution 6 - AndroidGiboltView Answer on Stackoverflow
Solution 7 - AndroidWahib Ul HaqView Answer on Stackoverflow
Solution 8 - AndroidSadeq ShajaryView Answer on Stackoverflow