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.


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

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

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


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


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


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


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.


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.