Definir texto do TextView a partir de um recurso de string formatado em html em XML

195

Eu tenho algumas cordas fixas dentro do meu strings.xml, algo como:

<resources>
    <string name="somestring">
        <B>Title</B><BR/>
        Content
    </string>
</resources>

e no meu layout eu tenho um TextViewque eu gostaria de preencher com a string formatada em html.

<TextView android:id="@+id/formattedtext"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/htmlstring"/>

se eu fizer isso, o conteúdo de formattedtexté apenas o conteúdo de somestringstripped de quaisquer tags html e, portanto, não formatado.

Eu sei que é possível definir o texto formatado programaticamente com

.setText(Html.fromHtml(somestring));

porque eu uso isso em outras partes do meu programa em que está funcionando conforme o esperado.

Para chamar essa função, preciso de um Activity, mas, no momento, meu layout é apenas uma visualização mais ou menos estática em XML simples e prefiro deixá-lo assim, para me salvar da sobrecarga de criar um Activityapenas para definir alguns texto.

Estou negligenciando algo óbvio? Não é possível? Qualquer ajuda ou soluções alternativas são bem-vindas!

Edit: Apenas tentei algumas coisas e parece que a formatação HTML no xml tem algumas restrições:

  • as tags devem ser escritas em minúsculas

  • algumas tags mencionadas aqui não funcionam, por exemplo <br/>(é possível usar \n)

slup
fonte
1
Já sei há muito tempo, mas consegui usar o <br> e não \ n para uma nova linha usando o html para um TextView.
19413 Tam
2
Isso pode funcionar apenas com xml? Eu tenho uma pequena recompensa na resposta. Eu não aceitaria respostas factuais neste momento que já codifiquei.
danny117
1
Acho interessante que ninguém realmente respondeu à pergunta. O OP afirma que ele sabe como fazê-lo com fromHtml (), mas deseja fazê-lo diretamente no arquivo de layout (embora os motivos não sejam bons ... você sempre tem uma atividade / contexto disponível se estiver usando a tela). Nenhuma das respostas também mergulha nos efeitos das tags âncora.
lilbyrdie

Respostas:

481

Caso alguém ache isso, existe uma alternativa melhor que não está documentada (eu tropecei nela depois de pesquisar por horas e finalmente a encontrei na lista de erros do próprio Android SDK). Você PODE incluir HTML bruto em strings.xml, contanto que você o envolva

<![CDATA[ ...raw html... ]]>

Exemplo:

<string name="nice_html">
<![CDATA[
<p>This is a html-formatted string with <b>bold</b> and <i>italic</i> text</p>
<p>This is another paragraph of the same string.</p>
]]>
</string>

Então, no seu código:

TextView foo = (TextView)findViewById(R.id.foo);
foo.setText(Html.fromHtml(getString(R.string.nice_html)));

IMHO, existem várias ordens de magnitude mais agradáveis ​​para trabalhar com :-)

Bitbang3r
fonte
26
Apenas para adicionar, você também pode apóstrofes / aspas simples de escape com barra invertida dentro do bloco CDATA, para que possa ter coisas como <b> can \ 't </b> em vez do infinitamente mais feio <b> não pode < / b>
Bitbang3r 6/11/11
5
Isso ainda funciona? Eu apenas tentei e ele literalmente exibe <p> e </p>.
Peri Hartman
1
@PeriHartman Você também fez a parte Html.fromHtml(getString(R.string.nice_html))? :)
assíncrono
1
Onde TextView foo = (TextView) findViewById (R.id.foo); foo.setText (Html.fromHtml (getString (R.string.nice_html))); preciso ir?
RustyIngles
2
Existe uma maneira de evitar "Html.fromHtml"?
desenvolvedor android
127

Como a resposta principal aqui está sugerindo algo errado (ou pelo menos muito complicado), acho que isso deve ser atualizado, embora a pergunta seja bastante antiga:

Ao usar recursos de String no Android, basta chamar getString(...)do código Java ou usar android:text="@string/..."no XML do layout.

Mesmo se você quiser usar a marcação HTML em suas Strings, não precisará alterar muito:

Os únicos caracteres que você precisa escapar nos recursos da String são:

  • aspas duplas: "torna - se\"
  • aspas simples: 'torna - se\'
  • e comercial: &torna - se &#38;ou&amp;

Isso significa que você pode adicionar sua marcação HTML sem escapar das tags:

<string name="my_string"><b>Hello World!</b> This is an example.</string>

No entanto, para ter certeza, você deve usar apenas <b>, <i>e <u>como eles estão listados na documentação.

Se você deseja usar suas seqüências HTML a partir de XML , continue usando android:text="@string/...", ele funcionará bem.

A única diferença é que, se você quiser usar suas seqüências HTML a partir do código Java , precisará usá- las em getText(...)vez de getString(...)agora, pois a primeira mantém o estilo e a segunda apenas o tira.

É tão fácil quanto isso. Sem CDATA, não Html.fromHtml(...).

Você só vai precisar Html.fromHtml(...)se você fez codificar seus caracteres especiais em HTML marcação. Use-o com getString(...)então. Isso pode ser necessário se você deseja passar a String para String.format(...).

Isso também está descrito nos documentos .

Editar:

Não há diferença entre o getText(...)HTML sem escape (como propus) ou as CDATAseções e Html.fromHtml(...).

Veja o gráfico a seguir para uma comparação:

insira a descrição da imagem aqui

caw
fonte
O meu está tirando isso. Estou usando o seguinte código:getResources().getText(R.string.codename)
Si8 15/10
3
Para ajudar melhor, eu precisaria ver os trechos Java / XML. Mas, como eu escrevi: Você só é certo se você estiver usando <b>, <i>, <u>. Outras tags nem sempre são suportadas.
quer
1
Sua resposta funciona e é simples. Basta colocar sua string em strings.xml, com as tags html desejadas, e referenciá-la no seu arquivo xml de layout. Eu usei a tag <sup>.
Peri Hartman
1
A sua é outra solução, não uma alternativa à outra, porque ela não suporta todas as tags, como a outra. Não vejo nenhuma vantagem nesta solução quando a outra é muito simples.
Mobilepotato7
1
Como experimentei usar "CDATA", tenho um problema, algo como isto, por exemplo: <! [CDATA [... HTML ...]]> com 22 letras e a parte html possui 10. Portanto, se você usar HTML.fromhtml ( getstring (...)) seu texto será exibido corretamente, mas o conteúdo do texto precisa de 22 espaços de letras. Eu usei no listview e vi espaços com ervas daninhas. então gettext () é MELHOR.
David
16

Escapa suas tags HTML ...

<resources>
    <string name="somestring">
        &lt;B&gt;Title&lt;/B&gt;&lt;BR/&gt;
        Content
    </string>
</resources>
ekawas
fonte
É o que dizem os documentos: developer.android.com/intl/zh-TW/guide/topics/resources/…, mas isso é suficiente para TextViewmostrar HTML?
Macarse
3
Eu testei isso, e se você o usar no código-fonte java, tudo bem. Mas se você associar seu texto diretamente do XML layout, as tags são mostrados na exibição de texto (por exemplo, <B> Título </ B> ...)
ZoltanF
Para mostrar o texto em uma exibição, use a classe [ developer.android.com/reference/android/text/Html.html] , especificamente fromHTML().
ekawas
@ZoltanF está certo, usando android: text = "" a partir de um layout com o HTML mostrará as tags na string.
Andrew Mackenzie
1
Se você quiser usar a string HTML diretamente do XML, você pode não HTML codificar caracteres especiais na string. No entanto, se você quiser usar a string a partir do código via Html.fromHTML()você tem que codificar os caracteres especiais. Estranho!
caw
11

O Android não possui uma especificação para indicar o tipo de sequência de recursos (por exemplo, texto / sem formatação ou texto / html). Existe uma solução alternativa, no entanto, que permitirá que o desenvolvedor especifique isso no arquivo XML.

  1. Defina um atributo personalizado para especificar que o atributo android: text seja html.
  2. Use um TextView subclasse.

Depois de defini-las, você pode se expressar com HTML em arquivos xml sem precisar chamar setText (Html.fromHtml (...)) novamente. Estou bastante surpreso que essa abordagem não faça parte da API.

Esta solução funciona na medida em que o simulador de estúdio Android exibirá o texto como HTML renderizado.

insira a descrição da imagem aqui

res / values ​​/ strings.xml (o recurso de string como HTML)

<resources>
<string name="app_name">TextViewEx</string>
<string name="string_with_html"><![CDATA[
       <em>Hello</em> <strong>World</strong>!
 ]]></string>
</resources>

layout.xml (apenas as partes relevantes)

Declare o espaço para nome do atributo customizado e inclua o atributo android_ex: isHtml. Também use a subclasse de TextView.

<RelativeLayout
...
xmlns:android_ex="http://schemas.android.com/apk/res-auto"
...>

<tv.twelvetone.samples.textviewex.TextViewEx
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/string_with_html"
    android_ex:isHtml="true"
    />
 </RelativeLayout>

res / values ​​/ attrs.xml (defina os atributos customizados para a subclasse)

 <resources>
<declare-styleable name="TextViewEx">
    <attr name="isHtml" format="boolean"/>
    <attr name="android:text" />
</declare-styleable>
</resources>

TextViewEx.java (a subclasse de TextView)

 package tv.twelvetone.samples.textviewex;

 import android.content.Context;
 import android.content.res.TypedArray;
 import android.support.annotation.Nullable;
 import android.text.Html;
 import android.util.AttributeSet;
 import android.widget.TextView;

public TextViewEx(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextViewEx, 0, 0);
    try {
        boolean isHtml = a.getBoolean(R.styleable.TextViewEx_isHtml, false);
        if (isHtml) {
            String text = a.getString(R.styleable.TextViewEx_android_text);
            if (text != null) {
                setText(Html.fromHtml(text));
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        a.recycle();
    }
}
}
Steven Spungin
fonte
Essa abordagem será melhor, se o aplicativo usar seqüências de caracteres formatadas em HTML em vários locais, em vez de chamar HTML.fromHtml em todos os lugares. O aplicativo em si terá duas visualizações, uma para normal e outra para HTML.
Manju
10

Última atualização:

Html.fromHtml(string);// descontinuado após as versões do Android N ..

O código a seguir dá suporte ao Android N e versões acima ...

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
textView.setText(Html.fromHtml(yourHtmlString,Html.FROM_HTML_MODE_LEGACY));
}

else 
{
textView.setText(Html.fromHtml(yourHtmlString));
}
Ranjith Kumar
fonte
3
  String termsOfCondition="<font color=#cc0029>Terms of Use </font>";
  String commma="<font color=#000000>, </font>";
  String privacyPolicy="<font color=#cc0029>Privacy Policy </font>";
  Spanned text=Html.fromHtml("I am of legal age and I have read, understood, agreed and accepted the "+termsOfCondition+commma+privacyPolicy);
        secondCheckBox.setText(text);
Dishant Kawatra
fonte
2

Tenho outro caso em que não tenho chance de colocar CDATA no xml ao receber a string HTML de um servidor.

Aqui está o que eu recebo de um servidor:

<p>The quick brown&nbsp;<br />
fox jumps&nbsp;<br />
 over the lazy dog<br />
</p>

Parece ser mais complicado, mas a solução é muito mais simples.

private TextView textView;

protected void onCreate(Bundle savedInstanceState) { 
.....
textView = (TextView) findViewById(R.id.text); //need to define in your layout
String htmlFromServer = getHTMLContentFromAServer(); 
textView.setText(Html.fromHtml(htmlFromServer).toString());

}

Espero que ajude!
Linh

Linh Lino
fonte
4
onde representa a implementação de getHTMLContentFromAServer () função
Pallavi