Sélectionner + copier du texte dans un TextView?

106

Existe-t-il un moyen de permettre à l'utilisateur de sélectionner / copier du texte dans un TextView? J'ai besoin de la même fonctionnalité de EditText où vous pouvez appuyer longuement sur le contrôle et obtenir les options contextuelles de sélectionner tout / copier, mais j'ai besoin que le contrôle ressemble à un TextView.

J'ai essayé quelques choses comme faire un EditText, utilisez l'option editable = "none" ou inputType = "none", mais celles-ci conservent toujours l'arrière-plan encadré d'un EditText, ce que je ne veux pas,

Merci

------- Mettre à jour ----------------------

C'est 99% là-bas, tout ce que je voudrais, c'est que la sélection hilight soit visible (le truc orange). A part ça, c'est bien, mais ça pourrait vivre avec ça:

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

Je suppose que cela est dû à cursorVisible = "false" mais sans cela, le curseur est présent même sans aucune sélection.

user291701
la source
Une alternative serait d'utiliser un WebView au lieu d'un TextView pour afficher le texte.
aleb

Réponses:

221

android: textIsSelectable fonctionne (au moins dans ICS - je n'ai pas encore vérifié dans les versions antérieures)

<TextView
    android:id="@+id/deviceIdTV"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textIsSelectable="true"
    android:text="" />
Milind
la source
15
API de niveau 11 et plus uniquement
Thierry-Dimitri Roy
10
Mais comment copier? Je peux mettre le texte en surbrillance, mais aucun menu de copie n'est apparu.
Bagusflyer
1
n'est-ce pas la cause du crash, lorsque vous jouez avec les curseurs.
Shubham
1
pouvez-vous me dire comment le faire fonctionner en vue de liste?
Ramesh Kumar
Beau, même menu de copie par défaut créé sur la barre d'outils
Farid
56

La vue texte doit être activée, mise au point, longue cliquable et 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" />
skd
la source
1
C'est la meilleure solution.
Brave
9
Pourquoi textIsSelectablene suffit-il pas? cela fonctionne pour moi avec seulement cette option
herau
4
Ou vous pouvez utiliser textview.setTextIsSelectable(true)dans le code java code.
berrytchaks
1
Juste en utilisant textIsSelectableisfaire le travail pour moi
crgarridos
1
en quelque sorte, textIsSelectablefonctionne pour certains cas, mais pas pour d'autres. Parfois, la même mise en page ne fonctionne pas toujours avec uniquement textIsSelectable mais un texte différent. Cependant, cette solution ne semble pas améliorer son fonctionnement, de sorte que le problème peut venir d'ailleurs.
Simon Ninon
23

Je pense que j'ai une meilleure solution. Il suffit d'appeler
registerForContextMenu(yourTextView);

et votre TextViewsera enregistré pour recevoir les événements du menu contextuel.

Puis remplacez onCreateContextMenuvotreActivity

@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());
}

J'espère que cela vous aidera, vous et toute autre personne, à rechercher un moyen de copier du texte à partir d'un TextView

pandre
la source
Où cela permet-il à l'utilisateur de sélectionner les bits de texte copiés? Ne copie-t-il pas simplement tout, ce qui n'est pas la question d'origine?
James Moore
4
Il est probablement bon de noter que cela entraîne la copie immédiate du texte, qu'ils sélectionnent ou non "Copier" dans le menu. Pour ne copier que lorsque l'élément approprié a été sélectionné, vous devez également remplacer onContextItemSelected () ou ajouter un gestionnaire de clics à l'élément de menu.
Faisal le
ClipboardManager.setText(CharSequence text)est obsolète au niveau 11 de l'API setPrimaryClip(ClipData). Cela crée un ClippedItem contenant le texte donné et le définit comme clip principal. Il n'a ni étiquette ni icône. Bonne lecture sur le copier-coller: lien
Marilia
Je veux ouvrir la boîte de dialogue après la sélection du texte. Alors, pouvez-vous nous faire des suggestions?
Anand Savjani
9
textview1.setTextIsSelectable(true);

Cela permettra à l'utilisateur de sélectionner et de copier du texte en cliquant longuement ou comme nous le faisons habituellement

Amitoj
la source
6

J'essaie de mettre en œuvre la même chose, et votre question m'a aidé à définir correctement ma mise en page editext. Donc merci! :)

Ensuite, j'ai réalisé que le surlignage sera effectivement visible si le curseur est allumé. Mais j'aime juste que vous ne vouliez pas voir un curseur avant de cliquer longtemps sur le texte, donc je cache le curseur dans le fichier layout.xml comme vous, et j'ai ajouté un eventlistener pour un clic long et n'affiche le curseur que lorsqu'une sélection commence .

Ajoutez donc l'auditeur dans votre activité dans la section onCreate:

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;
        }
    });

}

Et voilá, pas de curseur au début, et si vous cliquez longuement, le curseur apparaît avec les limites de sélection.

J'espère que je pourrais aider.

Salutations, fm

fmarton
la source
5

J'essayais également de faire quelque chose de similaire mais j'avais toujours besoin d'une approche personnalisée avec la manipulation de la mise en évidence du texte dans TextView. J'ai déclenché la mise en évidence et la copie sur l' LongClickaction.

C'est ainsi que j'ai réussi à utiliser 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);

et la fonction de copie:

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();
}

J'espère que c'est utile pour quelqu'un qui se retrouve sur cette question :)

Wahib Ul Haq
la source
4

Utilisation de Kotlin par programmation (copie manuelle)

button.setTextIsSelectable(true)

Ou, ajoutez une extension de propriété Kotlin

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

Puis appelez

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

Utilisation de Kotlin par programmation (copie automatique)

Si vous souhaitez copier automatiquement lorsque l'utilisateur appuie longuement sur vous, voici le code de base requis:

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
}

Vous voudrez peut-être ajouter un Toastpour confirmer que cela s'est produit

Ou ajoutez une fonction d'extension Kotlin

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
    }
}

Utilisation de Xml (copie manuelle)

Ajoutez ceci à votre <TextView>

android:textIsSelectable="true"

REMARQUE: Tous ces éléments nécessitent android:enabled="true"et android:focusable="true", qui sont les valeurs par défaut pour a TextView.

Gibolt
la source