Text in einer Textansicht auswählen + kopieren?

105

Gibt es eine Möglichkeit, dem Benutzer das Auswählen / Kopieren von Text in einer Textansicht zu ermöglichen? Ich benötige die gleiche Funktionalität von EditText, mit der Sie das Steuerelement lange drücken und die Popup-Optionen zum Auswählen aller / Kopieren abrufen können. Das Steuerelement muss jedoch wie eine Textansicht aussehen.

Versuchte ein paar Dinge wie das Erstellen eines EditText mit der Option editable = "none" oder inputType = "none", aber diese behalten immer noch den gerahmten Hintergrund eines EditText bei, den ich nicht möchte.

Vielen Dank

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

Dies ist zu 99% da. Ich möchte nur, dass die Auswahlhöhe sichtbar ist (das orangefarbene Zeug). Davon abgesehen ist es gut, könnte aber damit leben:

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

Ich denke, es wird durch cursorVisible = "false" verursacht, aber ohne das ist der Cursor auch ohne Auswahl vorhanden.

user291701
quelle
Eine Alternative wäre die Verwendung einer WebView anstelle einer TextView, um den Text anzuzeigen.
Aleeb

Antworten:

221

android: textIsSelectable funktioniert (zumindest in ICS - ich habe in früheren Versionen noch nicht eingecheckt)

<TextView
    android:id="@+id/deviceIdTV"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textIsSelectable="true"
    android:text="" />
Milind
quelle
15
Nur API Level 11 und höher
Thierry-Dimitri Roy
10
Aber wie kopiere ich? Ich kann den Text markieren, aber es wurde kein Kopiermenü angezeigt.
Bagusflyer
1
Verursacht dies nicht den Absturz, wenn Sie mit den Cursorn spielen?
Shubham
1
Können Sie mich wissen lassen, wie es in der Listenansicht funktioniert?
Ramesh Kumar
Schönes, sogar Standard-Kopiermenü erstellt auf Symbolleiste
Farid
56

Die Textansicht muss aktiviert, fokussierbar, longClickable und textIsSelectable sein

<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
quelle
1
Dies ist die beste Lösung.
Mutig
9
Warum textIsSelectableist nicht genug? es funktioniert für mich nur mit dieser Option
Herau
4
Oder Sie können textview.setTextIsSelectable(true)im Code Java-Code verwenden.
Berrytchaks
1
Nur mit textIsSelectableismachen den Job für mich
Crgarridos
1
textIsSelectablefunktioniert irgendwie für einige Fälle, aber nicht für andere. Manchmal funktioniert dasselbe Layout nicht immer nur mit textIsSelectable, sondern mit einem anderen Text. Diese Lösung scheint jedoch nicht besser zu funktionieren, sodass das Problem möglicherweise von einem anderen Ort stammt.
Simon Ninon
23

Ich denke, ich habe eine bessere Lösung. Ruf einfach an
registerForContextMenu(yourTextView);

und Sie TextViewwerden für den Empfang von Kontextmenüereignissen registriert.

Dann überschreiben Sie onCreateContextMenuin IhremActivity

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

Ich hoffe, dies hilft Ihnen und allen anderen, die nach einer Möglichkeit suchen, Text von einem zu kopieren TextView

Pandre
quelle
Wo kann der Benutzer auswählen, welche Textbits kopiert werden sollen? Kopiert es nicht einfach alles, was nicht die ursprüngliche Frage ist?
James Moore
4
Es ist wahrscheinlich gut zu beachten, dass dadurch der Text sofort kopiert wird, unabhängig davon, ob sie "Kopieren" aus dem Menü auswählen oder nicht. Um nur zu kopieren, wenn das entsprechende Element ausgewählt wurde, müssen Sie auch onContextItemSelected () überschreiben oder dem Menüelement einen Klick-Handler hinzufügen.
Faisal
ClipboardManager.setText(CharSequence text)wurde in API-Level 11 veraltet. Verwenden Sie setPrimaryClip(ClipData)stattdessen. Dadurch wird ein ClippedItem erstellt, das den angegebenen Text enthält, und als primärer Clip festgelegt. Es hat keine Beschriftung oder Symbol. Gute Lektüre über Copy-Paste: Link
Marilia
Ich möchte den Dialog nach der Textauswahl öffnen. Können Sie einen Vorschlag dafür machen?
Anand Savjani
9
textview1.setTextIsSelectable(true);

Auf diese Weise kann der Benutzer Text bei langem Klicken oder wie gewohnt auswählen und kopieren

Amitoj
quelle
6

Ich versuche, dasselbe zu implementieren, und Ihre Frage hat mir geholfen, mein Editext-Layout richtig einzustellen. So danke! :) :)

Dann wurde mir klar, dass die Hervorhebung tatsächlich sichtbar ist, wenn der Cursor eingeschaltet ist. Aber ich mag es einfach, dass Sie keinen Cursor sehen möchten, bevor Sie lange auf den Text klicken. Deshalb verstecke ich den Cursor genau wie Sie in der Datei layout.xml und füge einen Ereignislistener für lange Klicks hinzu und zeige den Cursor erst an, wenn eine Auswahl beginnt .

Fügen Sie also den Listener in Ihrer Aktivität im Abschnitt onCreate hinzu:

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

}

Und voilá, kein Cursor am Anfang, und wenn Sie lange klicken, erscheint der Cursor mit den Auswahlgrenzen.

Ich hoffe ich konnte helfen.

Prost, fm

fmarton
quelle
5

Ich habe auch versucht, etwas Ähnliches zu tun, brauchte aber immer noch einen benutzerdefinierten Ansatz mit der Manipulation der Hervorhebung von Text in TextView. Ich habe Highlight ausgelöst und weiter kopiertLongClick Aktion .

So habe ich es geschafft mit 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);

und die Kopierfunktion:

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

Ich hoffe, es ist hilfreich für jemanden, der diese Frage beantwortet :)

Wahib Ul Haq
quelle
4

Programmgesteuertes Verwenden von Kotlin (manuelle Kopie)

button.setTextIsSelectable(true)

Oder fügen Sie eine Kotlin-Eigenschaftserweiterung hinzu

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

Dann ruf an

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

Programmgesteuertes Verwenden von Kotlin (Auto-Copy)

Wenn Sie automatisch kopieren möchten, wenn der Benutzer lange drückt, ist dies der erforderliche Basiscode:

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
}

Möglicherweise möchten Sie eine hinzufügen Toast zu bestätigen, dass dies geschehen ist

Oder fügen Sie eine Kotlin-Erweiterungsfunktion hinzu

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

Verwenden von XML (manuelle Kopie)

Fügen Sie dies Ihrem hinzu <TextView>

android:textIsSelectable="true"

HINWEIS: All dies erfordert android:enabled="true"und android:focusable="true", was die Standardwerte für a sind TextView.

Gibolt
quelle