Definir estilo para o TextView programaticamente

249

Estou tentando usar o TextViewconstrutor com um estilo como este:

TextView myText = new TextView(MyActivity.this, null, R.style.my_style);

No entanto, quando faço isso, a exibição de texto não parece ter o estilo (verifiquei o estilo configurando-o em um objeto estático).

Eu também tentei usar, myText.setTextAppearance(MyActivity.this, R.style.my_style)mas também não funciona.

Ben
fonte

Respostas:

318

Não acredito que você possa definir o estilo programaticamente. Para contornar isso, você pode criar um arquivo xml de layout de modelo com o estilo atribuído, por exemplo, em res / layout, crie tvtemplate.xml como no seguinte conteúdo:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="This is a template"
        style="@style/my_style" />

aumente isso para instanciar seu novo TextView:

TextView myText = (TextView)getLayoutInflater().inflate(R.layout.tvtemplate, null);

Espero que isto ajude.

Dan Kilpatrick
fonte
1
Onde isso vence a resposta de Dandre Allison é que ele não requer a API v11.
Martin Capodici
2
Pode ter funcionado, mas isso não faz sentido. Como isso pode ser definido com o arquivo xml? se não for programaticamente . Há motivos para não usar arquivos xml, um deles é que eu estou acostumado a escrever código para criar a interface do usuário, por isso não quero aprender uma nova maneira de fazer isso, já que minha memória é limitada e quero manter algum espaço para outras coisas.
Iharob Al Asimi
@IharobAlAsimi está certo, tudo pode ser feito de forma programática, e o LayoutInflater sabe tudo sobre como transformar XML em objetos. Infelizmente, muitas dessas coisas estão ocultas em APIs privadas, e a única maneira de criar alguns objetos é fornecendo AttributeSet ao construtor.
precisa saber é o seguinte
Ao contrário de todas as outras respostas, isso realmente funcionou com spinners, portanto, uma estrela de ouro para você
Rowan Berry
121

Você pode criar um estilo genérico e reutilizá-lo em várias visualizações de texto, como a abaixo:

textView.setTextAppearance(this, R.style.MyTextStyle);

Editar: esta refere-se a Contexto

Shahul3D
fonte
50
Sua resposta funciona desde que você faça o mesmo com o "estilo" do texto. Não funciona se você estiver tentando fazer outras coisas no TextView, como adicionar preenchimento ou margens. Então, não estou dizendo que você está errado, mas sua resposta é limitada. Inflar a visualização no tempo de execução é a única maneira de aplicar um estilo abrangente.
Bill Mote
1
Ambas as soluções de uso de um modelo inflado e de setTextAppearance são razoáveis. Para abordar a questão padding / margens para a 2ª solução que você pode chamar textView.setLayoutParams (layoutParams)
AlanKley
Este método foi preterido no nível 23 da API. Use setTextAppearance (int) em vez disso na API 23+.
Sergii 28/11
Certifique-se a versão é, pelo menos API 23 (M)
Br0thazS0ul
4
usar o método da biblioteca de apoio,TextViewCompat.setTextAppearance
Rubin Yoo
97

Você pode passar um ContextThemeWrapper para o construtor como este:

TextView myText = new TextView(new ContextThemeWrapper(MyActivity.this, R.style.my_style));
maxcanna
fonte
1
coisas boas! a única maneira que eu poderia definir estilos de programação, apoiando API 8.
tbraun
Por alguma razão, isso não afeta o estilo do meu botão. Defini meu estilo como: <style name="TabButton"><item name="android:background">@drawable/tabbar_button_bkgnd</item>...</style>. E então eu invocá-lo com uma construção: new Button(new ContextThemeWrapper(context, R.style.TabButton));. Mas o botão simplesmente ignora minhas configurações. Estou fazendo algo errado aqui?
27414 Aleks N.
Você pode herdar do estilo Widget.Button assimparent="@android:style/Widget.Button"
maxcanna
@maxcanna Por algum motivo, a adição parentnão mudou um pouco. Então, eu apenas fui em frente com a inflatesolução.
Aleks N.
11
@AliakseiN. Você precisa usar o construtor 3-arg, por exemplo new Button(new ContextThemeWrapper(context, R.style.TabButton), null, 0). Caso contrário, o estilo de botão padrão será aplicado e esse estilo substituirá o estilo de botão que você mesclou ao tema por meio do ContextThemeWrapper.
Newtonx 09/02
17

Você pode definir o estilo no construtor (mas os estilos não podem ser alterados / definidos dinamicamente).

View(Context, AttributeSet, int)( inté um atributo no tema atual que contém uma referência a um estilo)

Resposta de Romain Guy

referência

Dandre Allison
fonte
sua resposta é enganosa - você tentou ler este tópico até o fim?
andr 14/03
3
Como isso é enganoso? A resposta aceita é enganosa, porque Romain Guy diz explicitamente que você pode "definir" um estilo programaticamente. Simplesmente não existe a possibilidade de alterá-lo dinamicamente. Este tópico não parece pensar que é o caso.
Dandre Allison
1
Cuidado, esta chamada requer nível API 11.
Martin Capodici
1
@PaulVerest não é uma citação.
Dandre Allison 26/10
6
O último int não é um recurso de estilo. É "Um atributo no tema atual que contém uma referência a um recurso de estilo que fornece valores padrão para a exibição".
Rve
11

O parâmetro int defStyleAttrnão especifica o estilo. Na documentação do Android:

defStyleAttr - Um atributo no tema atual que contém uma referência a um recurso de estilo que fornece valores padrão para a exibição. Pode ser 0 para não procurar padrões.

Para configurar o estilo no construtor View, temos 2 soluções possíveis:

  1. Com o uso do ContextThemeWrapper:

    ContextThemeWrapper wrappedContext = new ContextThemeWrapper(yourContext, R.style.your_style);
    TextView textView = new TextView(wrappedContext, null, 0);
  2. Com construtor de quatro argumentos (disponível a partir de LOLLIPOP):

    TextView textView = new TextView(yourContext, null, 0, R.style.your_style);

O principal para ambas as soluções - o defStyleAttrparâmetro deve ser 0 para aplicar nosso estilo à visualização.

DmitryArc
fonte
5

A alteração dinâmica de estilos ainda não é suportada. Você precisa definir o estilo antes que a exibição seja criada, via XML.

Chris Cashwell
fonte
20
que passa a ser a mesma coisa, na verdade
njzk2
@ njzk2 obrigado ... obviamente não pensou em seu comentário antes de postar. Não há como definir o estilo programaticamente antes da criação da interface do usuário; portanto, o mesmo código seria usado para alterar ou definir o estilo programaticamente.
Chris Cashwell
3

A resposta aceita foi uma ótima solução para mim. A única coisa a acrescentar é sobre o inflate()método.

Na resposta aceita, todos os android:layout_*parâmetros não serão aplicados.

O motivo não é uma maneira de ajustá-lo, a causa nullfoi passada como ViewGroup parent.

Você pode usá-lo assim:

View view = inflater.inflate(R.layout.view, parent, false);

e o parenté o ViewGroup, de onde você deseja ajustar android:layout_*.

Nesse caso, todas as propriedades relativas serão definidas.

Espero que seja útil para alguém.

Anor
fonte
2

Ao usar visualizações personalizadas que podem usar herança de estilo (ou atributos com estilo de evento), você deve modificar o segundo construtor para não perder o estilo. Isso funcionou para mim, sem a necessidade de usar setTextAppearence () :

public CustomView(Context context, AttributeSet attrs) {
    this(context, attrs, attrs.getStyleAttribute());
}
saiyancoder
fonte
2

Também encontrei o problema e encontrei o caminho para definir estilo por meio de programação. Talvez todos vocês precisem, então eu atualizo lá.

O terceiro parâmetro do construtor View aceita um tipo de atributo no seu tema como o código-fonte abaixo:

public TextView(Context context, AttributeSet attrs) {
    this(context, attrs, com.android.internal.R.attr.textViewStyle);
}

Portanto, você deve passar um tipo de R.attr. ** em vez de R.style. **

Nos meus códigos, executei as seguintes etapas:

Primeiro, personalize um atributo personalizado para ser usado pelos temas em attr.xml.

<attr name="radio_button_style" format="reference" />

Segundo, especifique seu estilo no tema usado em style.xml.

 <style name="AppTheme" parent="android:Theme.Translucent">
    <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    <item name="radio_button_style">@style/radioButtonStyle</item>
</style>
<style name="radioButtonStyle" parent="@android:style/Widget.CompoundButton.RadioButton">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">64dp</item>
    <item name="android:background">#000</item>
    <item name="android:button">@null</item>
    <item name="android:gravity">center</item>
    <item name="android:saveEnabled">false</item>
    <item name="android:textColor">@drawable/option_text_color</item>
    <item name="android:textSize">9sp</item>
</style>

No final, use-o!

            RadioButton radioButton = new RadioButton(mContext, null, R.attr.radio_button_style);

a visualização criada programaticamente usará o estilo especificado no seu tema.

Você pode tentar e espero que funcione perfeitamente para você.

mrtwo
fonte
0

Eu testei apenas com EditText, mas você pode usar o método

public void setBackgroundResource (int res)

para aplicar um estilo definido em um arquivo XML.

Se esse método pertence ao View, acredito que funcionará com qualquer elemento da interface do usuário.

Saudações.

floydaddict
fonte
De acordo com a documentação, isso deve funcionar apenas com desenháveis, não com estilo. Portanto, se isso realmente funcionar, é apenas "por acidente" e você não deve confiar nisso.
Heinzi
0

Nós podemos usar TextViewCompact.setTextAppearance(textView, R.style.xyz).

Doc Android para referência.

Kshitij Jain
fonte