Wybrać + skopiować tekst w TextView?

106

Czy istnieje sposób, aby zezwolić użytkownikowi na zaznaczanie / kopiowanie tekstu w TextView? Potrzebuję tej samej funkcji EditText, w której można długo nacisnąć kontrolkę i uzyskać wyskakujące opcje zaznacz wszystko / kopiuj, ale potrzebuję, aby kontrolka wyglądała jak TextView.

Próbowałem kilku rzeczy, takich jak ustawienie EditText przy użyciu opcji editable = "none" lub inputType = "none", ale te nadal zachowują oprawione tło EditText, czego nie chcę,

Dzięki

------- Aktualizacja ----------------------

To jest 99%, wszystko czego bym chciał, to żeby hilight selekcji był widoczny (pomarańczowe rzeczy). Poza tym jest dobrze, ale można z tym żyć:

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

Wydaje mi się, że jest to spowodowane przez kursorVisible = "false", ale bez tego kursor jest obecny nawet bez dokonywania wyboru.

user291701
źródło
Alternatywą byłoby użycie WebView zamiast TextView do wyświetlenia tekstu.
aleb

Odpowiedzi:

221

android: textIsSelectable działa (przynajmniej w ICS - jeszcze nie sprawdzałem we wcześniejszych wersjach)

<TextView
    android:id="@+id/deviceIdTV"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textIsSelectable="true"
    android:text="" />
Milind
źródło
15
Tylko poziom API 11 i
nowsze
10
Ale jak skopiować? Mogę zaznaczyć tekst, ale nie pojawiło się menu kopiowania.
Bagusflyer
1
czy to nie powoduje awarii, kiedy bawisz się kursorami.
Shubham
1
czy możesz dać mi znać, jak to działa w widoku listy?
Ramesh Kumar
Piękne, nawet domyślne menu kopiowania utworzone na pasku narzędzi
Farid
56

Widok tekstu musi być włączony, możliwy do zaznaczenia, longClickable i 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
źródło
1
To najlepsze rozwiązanie.
Brave
9
Dlaczego textIsSelectableto za mało? to działa dla mnie tylko z tą opcją
herau
4
Lub możesz użyć textview.setTextIsSelectable(true)w kodzie java.
berrytchaks
1
Po prostu używam textIsSelectableisdo pracy za mnie
crgarridos
1
jakoś textIsSelectabledziała w niektórych przypadkach, ale nie w innych. Czasami ten sam układ nie zawsze działa tylko z tekstem textIsSelectable, ale z innym tekstem. Jednak to rozwiązanie nie wydaje się działać lepiej, więc problem może pochodzić z innego miejsca.
Simon Ninon,
23

Myślę, że mam lepsze rozwiązanie. Zadzwoń
registerForContextMenu(yourTextView);

a Twoja TextViewzostanie zarejestrowana do otrzymywania zdarzeń z menu kontekstowego.

Następnie nadpisz onCreateContextMenuw swoimActivity

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

Mam nadzieję, że pomoże to Tobie i każdemu, kto szuka sposobu na skopiowanie tekstu z pliku TextView

pandre
źródło
Gdzie to pozwala użytkownikowi wybrać, które fragmenty tekstu mają być kopiowane? Czy nie kopiuje wszystkiego, co nie jest pierwotnym pytaniem?
James Moore
4
Prawdopodobnie warto zauważyć, że powoduje to natychmiastowe skopiowanie tekstu, niezależnie od tego, czy wybiorą z menu opcję „Kopiuj”. Aby kopiować tylko wtedy, gdy wybrany został odpowiedni element, należałoby również nadpisać onContextItemSelected () lub dodać moduł obsługi kliknięcia do elementu menu.
Faisal
ClipboardManager.setText(CharSequence text)został uznany za przestarzały na poziomie API 11. Użyj setPrimaryClip(ClipData)zamiast tego. Spowoduje to utworzenie ClippedItem przechowującego podany tekst i ustawienie go jako klipu podstawowego. Nie ma etykiety ani ikony. Dobra lektura na temat kopiowania i wklejania: link
Marilia
Chcę otworzyć okno dialogowe po zaznaczeniu tekstu. Czy możesz więc przedstawić jakąś sugestię?
Anand Savjani
9
textview1.setTextIsSelectable(true);

Umożliwi to użytkownikowi zaznaczanie i kopiowanie tekstu po długim kliknięciu lub tak jak zwykle

Amitoj
źródło
6

Próbuję zaimplementować to samo, a twoje pytanie pomogło mi poprawnie ustawić układ mojego pliku editext. Więc dziękuję! :)

Wtedy zdałem sobie sprawę, że podświetlenie będzie faktycznie widoczne, jeśli kursor jest włączony. Ale ja tak jak ty nie chcesz widzieć kursora przed długim kliknięciem tekstu, więc ukrywam kursor w pliku layout.xml, tak jak ty, i dodałem Eventlistener dla długiego kliknięcia i wyświetlam kursor tylko wtedy, gdy zaczyna się zaznaczanie .

Więc dodaj odbiorcę do swojej aktywności w sekcji 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;
        }
    });

}

I voilá, na początku nie ma kursora, a długie kliknięcie spowoduje wyświetlenie kursora z granicami zaznaczenia.

Mam nadzieję, że mógłbym pomóc.

Pozdrawiam, fm

fmarton
źródło
5

Próbowałem też zrobić coś podobnego, ale nadal potrzebowałem niestandardowego podejścia z manipulacją podświetlaniem tekstu w TextView. Uruchomiłem podświetlanie i kopiowanie w LongClickakcji.

Oto jak poradziłem sobie z użyciem 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);

oraz funkcja kopiowania:

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

Mam nadzieję, że komuś, kto trafi na to pytanie, będzie pomocne :)

Wahib Ul Haq
źródło
4

Używanie Kotlin programowo (kopiowanie ręczne)

button.setTextIsSelectable(true)

Lub dodaj rozszerzenie właściwości Kotlin

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

Wtedy zadzwoń

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

Używanie Kotlin programowo (automatyczne kopiowanie)

Jeśli chcesz automatycznie kopiować, gdy użytkownik długo naciska na przeglądarkę, jest to wymagany kod podstawowy:

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
}

Możesz dodać, Toastaby potwierdzić, że to się stało

Lub dodaj funkcję rozszerzenia 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
    }
}

Korzystanie z XML (kopiowanie ręczne)

Dodaj to do swojego <TextView>

android:textIsSelectable="true"

UWAGA: Wszystkie te wymagają android:enabled="true"i android:focusable="true", które są wartościami domyślnymi dla pliku TextView.

Gibolt
źródło