Pergunta

É possível definir vários estilos para diferentes peças de texto dentro de uma visão de texto?

Por exemplo, estou definindo o texto da seguinte maneira:

tv.setText(line1 + "\n" + line2 + "\n" + word1 + "\t" + word2 + "\t" + word3);

É possível ter um estilo diferente para cada elemento de texto? Por exemplo, linha1 negro, word1 itálico, etc.

O guia do desenvolvedor Tarefas comuns e como fazê -las no Android inclui Selecionar, destacar ou modelar partes do texto:

// Get our EditText object.
EditText vw = (EditText)findViewById(R.id.text);

// Set the EditText's text.
vw.setText("Italic, highlighted, bold.");

// If this were just a TextView, we could do:
// vw.setText("Italic, highlighted, bold.", TextView.BufferType.SPANNABLE);
// to force it to use Spannable storage so styles can be attached.
// Or we could specify that in the XML.

// Get the EditText's internal text storage
Spannable str = vw.getText();

// Create our span sections, and assign a format to each.
str.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
str.setSpan(new BackgroundColorSpan(0xFFFFFF00), 8, 19, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 21, str.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

Mas isso usa números explícitos de posição dentro do texto. Existe uma maneira mais limpa de fazer isso?

Foi útil?

Solução

Caso alguém esteja se perguntando como fazer isso, aqui está uma maneira: (graças a Mark de novo!)

mBox = new TextView(context);
mBox.setText(Html.fromHtml("<b>" + title + "</b>" +  "<br />" + 
            "<small>" + description + "</small>" + "<br />" + 
            "<small>" + DateAdded + "</small>"));

Para uma lista não oficial de tags suportadas por este método, consulte esse link ou esta pergunta: Quais tags HTML são suportadas pelo Android TextView?

Outras dicas

Tentar Html.fromHtml(), e marque seu texto com tags HTML em negrito e itálico, por exemplo:

Spanned text = Html.fromHtml("This mixes <b>bold</b> and <i>italic</i> stuff");
textView.setText(text);

Um pouco fora do tópico, mas achei isso útil demais para não ser mencionado aqui.

E se gostarmos de ler o texto html de String.xml recurso e, assim, facilite a localização. CDATA tornar isso possível:

<string name="my_text">
  <![CDATA[
    <b>Autor:</b> Mr Nice Guy<br/>
    <b>Contact:</b> myemail@grail.com<br/>
    <i>Copyright © 2011-2012 Intergalactic Spacebar Confederation </i>
  ]]>
</string> 

Do nosso código Java, agora poderíamos utilizá -lo assim:

TextView tv = (TextView) findViewById(R.id.myTextView);
tv.setText(Html.fromHtml(getString(R.string.my_text))); 

Eu não esperava que isso funcionasse. Mas isso aconteceu.

Espero que seja útil para alguns de vocês!

Se você não quiser usar o HTML, você pode simplesmente criar um styles.xml e usá -lo assim:

TextView tv = (TextView) findViewById(R.id.textview);
SpannableString text = new SpannableString(myString);

text.setSpan(new TextAppearanceSpan(getContext(), R.style.myStyle), 0, 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
text.setSpan(new TextAppearanceSpan(getContext(), R.style.myNextStyle), 6, 10, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

tv.setText(text, TextView.BufferType.SPANNABLE);

É mais leve para usar um SpannableString Em vez de marcação HTML. Isso me ajuda a ver exemplos visuais, então aqui está uma resposta suplementar.

enter image description here

Este é um único TextView.

// set the text
SpannableString s1 = new SpannableString("bold\n");
SpannableString s2 = new SpannableString("italic\n");
SpannableString s3 = new SpannableString("foreground color\n");
SpannableString s4 = new SpannableString("background color\n");
SpannableString s5 = new SpannableString("underline\n");
SpannableString s6 = new SpannableString("strikethrough\n");
SpannableString s7 = new SpannableString("bigger\n");
SpannableString s8 = new SpannableString("smaller\n");
SpannableString s9 = new SpannableString("font\n");
SpannableString s10 = new SpannableString("URL span\n");
SpannableString s11 = new SpannableString("clickable span\n");
SpannableString s12 = new SpannableString("overlapping spans\n");

// set the style
int flag = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
s1.setSpan(new StyleSpan(Typeface.BOLD), 0, s1.length(), flag);
s2.setSpan(new StyleSpan(Typeface.ITALIC), 0, s2.length(), flag);
s3.setSpan(new ForegroundColorSpan(Color.RED), 0, s3.length(), flag);
s4.setSpan(new BackgroundColorSpan(Color.YELLOW), 0, s4.length(), flag);
s5.setSpan(new UnderlineSpan(), 0, s5.length(), flag);
s6.setSpan(new StrikethroughSpan(), 0, s6.length(), flag);
s7.setSpan(new RelativeSizeSpan(2), 0, s7.length(), flag);
s8.setSpan(new RelativeSizeSpan(0.5f), 0, s8.length(), flag);
s9.setSpan(new TypefaceSpan("monospace"), 0, s9.length(), flag);
s10.setSpan(new URLSpan("https://developer.android.com"), 0, s10.length(), flag);
s11.setSpan(new ClickableSpan() {
    @Override
    public void onClick(View widget) {
        Toast.makeText(getApplicationContext(), "Span clicked", Toast.LENGTH_SHORT).show();
    }
}, 0, s11.length(), flag);
s12.setSpan(new ForegroundColorSpan(Color.RED), 0, 11, flag);
s12.setSpan(new BackgroundColorSpan(Color.YELLOW), 4, s12.length(), flag);
s12.setSpan(new UnderlineSpan(), 4, 11, flag);

// build the string
SpannableStringBuilder builder = new SpannableStringBuilder();
builder.append(s1);
builder.append(s2);
builder.append(s3);
builder.append(s4);
builder.append(s5);
builder.append(s6);
builder.append(s7);
builder.append(s8);
builder.append(s9);
builder.append(s10);
builder.append(s11);
builder.append(s12);

// set the text view with the styled text
textView.setText(builder);
// enables clicking on spans for clickable span and url span
textView.setMovementMethod(LinkMovementMethod.getInstance());

Um estudo mais aprofundado

Este exemplo foi originalmente inspirado de aqui.

A lista de tags suportadas é:

Se você usar um recurso de string, poderá adicionar um estilo simples, como negrito ou itálico usando a notação HTML. As tags atualmente suportadas são: B (negrito), I (itálico), U (sublinhado), TT (Monospace), BIG, SMALL, SUP (sobrescrito), SUB (subscrito) e STRIKE (Strikethrough). Então, por exemplo, em res/values/strings.xml Você pode declarar isso:

<resource>
    <string id="@+id/styled_welcome_message">We are <b><i>so</i></b> glad to see you.</string>
</resources>

(A partir de http://developer.android.com/guide/faq/commontasks.html#selectingtext - Link do arquivo da web, <resource> Erro está no original!)

Também mostra que Html.fromHtml Não é realmente necessário em casos simples.

Eu estava encontrando o mesmo problema. Eu poderia usar o Fromhtml, mas agora sou Android, não, não, decidi experimentar isso. Eu tenho que localizar isso, então eu dei uma chance usando o conceito de substituição de cordas. Defino o estilo no TextView como o estilo principal e, em seguida, apenas formato as outras peças.

Espero que isso ajude outras pessoas que desejam fazer a mesma coisa - não sei por que isso não é mais fácil na estrutura.

Minhas cordas são assim:


<string name="my_text">{0} You will need a {1} to complete this assembly</string>
<string name="text_sub0">1:</string>
<string name="text_sub1">screwdriver, hammer, and measuring tape</string>

Aqui estão os estilos:


<style name="MainStyle">
    <item name="android:textSize">@dimen/regular_text</item>
    <item name="android:textColor">@color/regular_text</item>
</style>
<style name="style0">
    <item name="android:textSize">@dimen/paragraph_bullet</item>
    <item name="android:textColor">@color/standout_text</item>
    <item name="android:textStyle">bold</item>
</style>
<style name="style1">
    <item name="android:textColor">@color/standout_light_text</item>
    <item name="android:textStyle">italic</item>
</style>

Aqui está o meu código que chama meu método FormatStyles:


SpannableString formattedSpan = formatStyles(getString(R.string.my_text), getString(R.string.text_sub0), R.style.style0, getString(R.string.main_text_sub1), R.style.style1);
textView.setText(formattedSpan, TextView.BufferType.SPANNABLE);

O método de formato:


private SpannableString formatStyles(String value, String sub0, int style0, String sub1, int style1)
{
    String tag0 = "{0}";
    int startLocation0 = value.indexOf(tag0);
    value = value.replace(tag0, sub0);

    String tag1 = "{1}";
    int startLocation1 = value.indexOf(tag1);
    if (sub1 != null && !sub1.equals(""))
    {
        value = value.replace(tag1, sub1);
    }

    SpannableString styledText = new SpannableString(value);
    styledText.setSpan(new TextAppearanceSpan(getActivity(), style0), startLocation0, startLocation0 + sub0.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    if (sub1 != null && !sub1.equals(""))
    {
        styledText.setSpan(new TextAppearanceSpan(getActivity(), style1), startLocation1, startLocation1 + sub1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }

    return styledText;
}

Agora o <b> o elemento é descontinuado. <strong> renderiza como <b>, e <em> renderiza como <i>.

tv.setText(Html.fromHtml("<strong>bold</strong> and <em>italic</em> "));

Este trabalho é bom para mim

Se você deseja adicionar o texto com estilo no XML, pode criar uma exibição personalizada estendendo o TextView e substituir setText ():

public class HTMLStyledTextView extends TextView
{
    public HTMLStyledTextView(Context context) {
        super(context);
    }

    public HTMLStyledTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public HTMLStyledTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void setText(CharSequence text, BufferType type)
    {
       super.setText(Html.fromHtml(text.toString()), type);
    }
}

Então, você pode usá -lo assim (substitua PACKAGE_NAME com o nome do seu pacote):

<PACKAGE_NAME.HTMLStyledTextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="<![CDATA[
        <b>Bolded Text:</b> Non-Bolded Text
    ]]>"
/>

Aqui está uma maneira fácil de fazer isso usando Htmlbuilder

    myTextView.setText(new HtmlBuilder().
                    open(HtmlBuilder.Type.BOLD).
                    append("Some bold text ").
                    close(HtmlBuilder.Type.BOLD).
                    open(HtmlBuilder.Type.ITALIC).
                    append("Some italic text").
                    close(HtmlBuilder.Type.ITALIC).
                    build()
    );

Resultado:

Algum texto ousado Algum texto em itálico

Como afirmado, use TextView.setText(Html.fromHtml(String))

E use essas tags em sua sequência formatada HTML:

<a href="...">
<b>
<big>
<blockquote>
<br>
<cite>
<dfn>
<div align="...">
<em>
<font size="..." color="..." face="...">
<h1>
<h2>
<h3>
<h4>
<h5>
<h6>
<i>
<img src="...">
<p>
<small>
<strike>
<strong>
<sub>
<sup>
<tt>
<u>

http://commonsware.com/blog/android/2010/05/26/html-tags-supported-by-textview.html

Eu também

Que tal usar uma bela marcação com Kotlin e Anko -

import org.jetbrains.anko.*
override fun onCreate(savedInstanceState: Bundle?) {
    title = "Created with Beautiful Markup"
    super.onCreate(savedInstanceState)

    verticalLayout {
        editText {
            hint = buildSpanned {
                append("Italic, ", Italic)
                append("highlighted", backgroundColor(0xFFFFFF00.toInt()))
                append(", Bold", Bold)
            }
        }
    }
}

Created with Beautiful Markup

Sim, é possível usar SpannedString. Se você está usando Kotlin, fica ainda mais fácil de fazer usando core-ktx, como fornece um Languagem específica do domínio (DSL) por fazer isso:

    val string: SpannedString = buildSpannedString {
        bold {
            append("1111")
        }
        append("Devansh")     
    }

Mais opções fornecidas por ele são:

append("Hello There")
bold {
    append("bold")
    italic {
        append("bold and italic")
        underline {
            append("then some text with underline")
        }
    }
}

Por fim, você pode apenas:

textView.text = string

De fato, exceto o objeto HTML, você também pode usar as classes do tipo espanhável, por exemplo, TextApPearancespan ou Typefacespan e Spannablestring alternando. A classe HTML também usa esses mecanismos. Mas com as classes do tipo espanhável, você tem mais liberdade.

Pode ser tão simples quanto alavancar o método Length () da String:

  1. Divida a sequência de texto no arquivo XML Strings em tantas sub-strings (uma sequência separada do ponto de vista do Android) como muitos você precisa de estilos diferentes, para que possa ser como: STR1, STR2, STR3 (como no seu caso), que, quando unidos, são toda a string que você usa.

  2. E, em seguida, basta seguir o método "span", assim como você apresentou seu código - mas, em vez de uma única string, combine todas as substringas mesclando -as em uma única, cada uma com um estilo personalizado diferente.

Você ainda usa os números, mas não diretamente - eles não assumem mais uma forma codificada (como no seu código) agora, mas estão sendo substituídos pelos métodos de comprimento combinado () (Nota duas estrelas que precedem e sufixam o STR. comprimento () no lugar do número absoluto para existir a mudança):

str.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, **str.length()**, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

para o tamanho da primeira corda, então str.Length () + 1, str.Length () + str2.Length () Para o tamanho da segunda corda, e assim por diante com todas as substringas, em vez de por exemplo, 0,7 ou 8,19 e assim por diante ...

Usando uma classe auxiliar espanhável como Recursos de String Android compartilha na parte inferior da página da web. Você pode abordar isso criandoCharSquences e dando a eles um estilo.

Mas no exemplo que eles nos dão, é apenas para o texto ousado, itálico e até colorizado. Eu precisava embrulhar vários estilos em umCharSequence Para defini -los em um TextView. Então, para essa aula (eu o nomeei CharSequenceStyles) Acabei de adicionar essa função.

public static CharSequence applyGroup(LinkedList<CharSequence> content){
    SpannableStringBuilder text = new SpannableStringBuilder();
    for (CharSequence item : content) {
        text.append(item);
    }
    return text;
}

E na vista, adicionei isso.

            message.push(postMessageText);
            message.push(limitDebtAmount);
            message.push(pretMessageText);
            TextView.setText(CharSequenceStyles.applyGroup(message));

Espero que isso lhe ajude!

Espaninha facilitar o uso da Spannablestring.

Spanny spanny = new Spanny("Underline text", new UnderlineSpan())
                .append("\nRed text", new ForegroundColorSpan(Color.RED))
                .append("\nPlain text");
textView.setText(spanny)

Como Jon disse, para mim, esta é a melhor solução e você não precisa definir nenhum texto em tempo de execução, use apenas esta classe personalizada htmltextview

public class HtmlTextView extends TextView {

  public HtmlTextView(Context context) {
      super(context);
  }

  public HtmlTextView(Context context, AttributeSet attrs) {
      super(context, attrs);
  }

  public HtmlTextView(Context context, AttributeSet attrs, int defStyleAttr) 
  {
      super(context, attrs, defStyleAttr);
  }

  @TargetApi(21)
  public HtmlTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
      super(context, attrs, defStyleAttr, defStyleRes);
  }

  @Override
  public void setText(CharSequence s,BufferType b){
      super.setText(Html.fromHtml(s.toString()),b);
  }

}

E é isso, agora só coloque -o em seu XML

<com.fitc.views.HtmlTextView
    android:id="@+id/html_TV"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/example_html" />

com sua string html

<string name="example_html">
<![CDATA[
<b>Author:</b> Mr Donuthead<br/>
<b>Contact:</b> me@donut.com<br/>
<i>Donuts for life </i>
]]>

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top