Selecionar + copiar texto em um TextView?

106

Existe uma maneira de permitir que o usuário selecione / copie texto em um TextView? Preciso da mesma funcionalidade do EditText, onde você pode pressionar longamente o controle e obter as opções pop-up de selecionar todos / copiar, mas preciso que o controle se pareça com um TextView.

Tentei algumas coisas como fazer um EditText usar a opção editable = "none" ou inputType = "none", mas eles ainda mantêm o fundo emoldurado de um EditText, o que eu não quero,

obrigado

------- Atualizar ----------------------

Isso está 99% lá, tudo que eu quero é que o brilho da seleção seja visível (o material laranja). Fora isso, é bom, mas poderia viver com isso:

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

Eu acho que está sendo causado por cursorVisible = "false", mas sem que o cursor esteja presente, mesmo sem qualquer seleção sendo feita.

user291701
fonte
Uma alternativa seria usar um WebView em vez de um TextView para exibir o texto.
aleb

Respostas:

221

android: textIsSelectable funciona (pelo menos no ICS - ainda não verifiquei nas versões anteriores)

<TextView
    android:id="@+id/deviceIdTV"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textIsSelectable="true"
    android:text="" />
Milind
fonte
15
API de nível 11 e superior apenas
Thierry-Dimitri Roy
10
Mas como copiar? Posso destacar o texto, mas nenhum menu de cópia apareceu.
Bagusflyer
1
isso não está causando o travamento, quando você mexe com os cursores.
Shubham
1
você pode me dizer como fazer funcionar no listview?
Ramesh Kumar,
Lindo, até mesmo menu de cópia padrão criado na barra de ferramentas
Farid
56

A visualização de texto precisa estar habilitada, focalizável, longClickable e 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
fonte
1
essa é a melhor solução.
Bravo
9
Por que textIsSelectablenão é suficiente? funciona para mim apenas com esta opção
herau
4
Ou você pode usar textview.setTextIsSelectable(true)o código Java no código.
berrytchaks
1
Apenas usando textIsSelectableisfazer o trabalho para mim
crgarridos
1
de alguma forma, textIsSelectablefunciona para alguns casos, mas não para outros. Às vezes, o mesmo layout nem sempre funciona com apenas textIsSelectable, mas com um texto diferente. No entanto, essa solução não parece fazer com que funcione melhor, então o problema pode estar vindo de outro lugar.
Simon Ninon
23

Acho que tenho uma solução melhor. Apenas ligue
registerForContextMenu(yourTextView);

e você TextViewserá registrado para receber eventos do menu de contexto.

Em seguida, substitua onCreateContextMenuem seuActivity

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

Espero que isso ajude você e qualquer outra pessoa que esteja procurando uma maneira de copiar o texto de um TextView

pandre
fonte
Onde isso permite que o usuário selecione quais bits de texto são copiados? Não copia apenas tudo, o que não é a pergunta original?
James Moore
4
Provavelmente é bom notar que isso faz com que o texto seja copiado imediatamente, independentemente de eles selecionarem ou não "Copiar" no menu. Para copiar apenas quando o item apropriado foi selecionado, você também precisa substituir onContextItemSelected () ou adicionar um manipulador de clique ao item de menu.
Faisal
ClipboardManager.setText(CharSequence text)foi descontinuado no nível de API 11. Use em seu setPrimaryClip(ClipData)lugar. Isso cria um ClippedItem que contém o texto fornecido e o define como o clipe principal. Não tem rótulo ou ícone. Boa leitura sobre copiar e colar: link
Marília
Quero abrir o diálogo após a seleção do texto. Então, você pode dar alguma sugestão para isso?
Anand Savjani,
9
textview1.setTextIsSelectable(true);

Isso permitirá que o usuário selecione e copie o texto com um clique longo ou como fazemos normalmente

Amitoj
fonte
6

Estou tentando implementar o mesmo, e sua dúvida me ajudou a definir o layout do meu editexto corretamente. Então, obrigado! :)

Então percebi que o realce ficará realmente visível se o cursor estiver ativado. Mas eu assim como você não quero ver um cursor antes de clicar no texto, então eu oculto o cursor no arquivo layout.xml assim como você, e adicionei um eventlistener para um clique longo e exibo o cursor apenas quando uma seleção começa .

Portanto, adicione o listener em sua Activity na seção 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;
        }
    });

}

E voilá, nenhum cursor no início, e se você clicar longamente, o cursor aparecerá com os limites da seleção.

Espero poder ajudar.

Saúde, fm

Fmarton
fonte
5

Eu também estava tentando fazer algo semelhante, mas ainda precisava de uma abordagem personalizada com manipulação de destaque de texto em TextView. Eu acionei o destaque e a cópia em LongClickação.

Foi assim que consegui usar 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);

e a função de cópia:

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

Espero que seja útil para quem chega a esta questão :)

Wahib Ul Haq
fonte
4

Usando Kotlin programaticamente (cópia manual)

button.setTextIsSelectable(true)

Ou adicione uma extensão de propriedade Kotlin

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

Então ligue

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

Usando Kotlin programaticamente (cópia automática)

Se você deseja copiar automaticamente quando o usuário pressiona longamente em sua visualização, este é o código base necessário:

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
}

Você pode querer adicionar um Toastpara confirmar que aconteceu

Ou adicione uma função de extensão 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
    }
}

Usando Xml (cópia manual)

Adicione isto ao seu <TextView>

android:textIsSelectable="true"

NOTA: Todos estes requerem android:enabled="true"e android:focusable="true", que são os valores padrão para a TextView.

Gibolt
fonte