Establecer estilo para TextView mediante programación

249

Estoy tratando de usar el TextViewconstructor con un estilo como este:

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

Sin embargo, cuando hago esto, la vista de texto no parece tomar el estilo (verifiqué el estilo configurándolo en un objeto estático).

También he intentado usar myText.setTextAppearance(MyActivity.this, R.style.my_style)pero tampoco funciona.

Ben
fuente

Respuestas:

318

No creo que pueda establecer el estilo mediante programación. Para evitar esto, puede crear un archivo xml de diseño de plantilla con el estilo asignado, por ejemplo en res / layout create tvtemplate.xml como con el siguiente contenido:

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

luego infle esto para crear una instancia de su nuevo TextView:

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

Espero que esto ayude.

Dan Kilpatrick
fuente
1
Donde esto gana a la respuesta de Dandre Allison es que no requiere API v11.
Martin Capodici
2
Podría haber funcionado, pero esto no tiene sentido. ¿Cómo se puede configurar con el archivo xml? si no es mediante programación . Hay razones para no usar archivos xml, una de ellas es que estoy acostumbrado a escribir código para construir la interfaz de usuario, así que no quiero aprender una nueva forma de hacerlo, ya que mi memoria es limitada y quiero dejar algo de espacio para otras cosas.
Iharob Al Asimi
@IharobAlAsimi es cierto, todas las cosas se pueden hacer mediante programación, y LayoutInflater sabe todo sobre cómo convertir XML en objetos. Lamentablemente, muchas de estas cosas están ocultas bajo API privadas, y la única forma de crear algunos objetos es proporcionando AttributeSet al constructor.
Miha_x64
A diferencia de todas las otras respuestas, esto realmente funcionó con hilanderos, por lo que una estrella de oro para ti
Rowan Berry
121

Puede crear un estilo genérico y reutilizarlo en múltiples vistas de texto como el siguiente:

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

Editar: esto se refiere al contexto

Shahul3D
fuente
50
Su respuesta funciona siempre que todo lo que haga sea simular el "estilo" del texto. No funciona si está intentando hacer otras cosas en TextView como agregar relleno o márgenes. Entonces, no digo que estés equivocado, pero tu respuesta es limitada. Inflar la vista en tiempo de ejecución es la única forma de aplicar un estilo integral.
Bill Mote
1
Ambas soluciones de usar una plantilla inflada y usar setTextAppearance son razonables. Para abordar el problema de relleno / márgenes para la segunda solución, puede llamar a textView.setLayoutParams (layoutParams)
AlanKley
Este método fue desaprobado en el nivel 23 de API. Use setTextAppearance (int) en su lugar en API 23+.
Sergii
Asegúrese de que la versión sea al menos API 23 (M)
Br0thazS0ul
44
use el método de la biblioteca de soporte,TextViewCompat.setTextAppearance
Rubin Yoo
97

Puede pasar un ContextThemeWrapper al constructor así:

TextView myText = new TextView(new ContextThemeWrapper(MyActivity.this, R.style.my_style));
maxcanna
fuente
1
¡Buena cosa! la única forma en que podía establecer estilos programáticamente mientras soportaba API 8.
tbraun
Por alguna razón, no afecta el estilo de mi botón. He definido mi estilo como: <style name="TabButton"><item name="android:background">@drawable/tabbar_button_bkgnd</item>...</style>. Y entonces invoco con una construcción: new Button(new ContextThemeWrapper(context, R.style.TabButton));. Pero el botón simplemente ignora mi configuración. ¿Estoy haciendo algo mal aquí?
Aleks N.
@ AlaksiejN. Deberías heredar de Widget. Estilo de botón como esteparent="@android:style/Widget.Button"
maxcanna
@maxcanna Por alguna razón, agregar parentno cambió un poco. Así que seguí adelante con la inflatesolución.
Aleks N.
11
@AliakseiN. Necesita usar el constructor de 3 argumentos, por ejemplo new Button(new ContextThemeWrapper(context, R.style.TabButton), null, 0). De lo contrario, se aplicará el estilo de botón predeterminado, y este estilo anulará el estilo de botón que ha fusionado con el tema a través de ContextThemeWrapper.
Newtonx
17

Puede configurar el estilo en el constructor (pero los estilos no se pueden cambiar / configurar dinámicamente).

View(Context, AttributeSet, int)( intes un atributo en el tema actual que contiene una referencia a un estilo)

Respuesta de Romain Guy

referencia

Dandre Allison
fuente
su respuesta es engañosa: ¿ha intentado leer este hilo hasta el final?
andr
3
¿Cómo es engañar? La respuesta aceptada es engañosa, porque Romain Guy dice explícitamente que puedes "establecer" un estilo mediante programación. Simplemente no hay una facilidad para cambiarlo dinámicamente. Sin embargo, este hilo no parece pensar que ese sea el caso.
Dandre Allison
1
Cuidado, esta llamada requiere API nivel 11.
Martin Capodici
1
@PaulVerest no es una cita.
Dandre Allison
66
El último int no es un recurso de estilo. Es "Un atributo en el tema actual que contiene una referencia a un recurso de estilo que proporciona valores predeterminados para la vista".
2015
11

El parámetro int defStyleAttrno especifica el estilo. De la documentación de Android:

defStyleAttr : un atributo en el tema actual que contiene una referencia a un recurso de estilo que proporciona valores predeterminados para la vista. Puede ser 0 para no buscar valores predeterminados.

Para configurar el estilo en View constructor tenemos 2 posibles soluciones:

  1. Con el uso de ContextThemeWrapper:

    ContextThemeWrapper wrappedContext = new ContextThemeWrapper(yourContext, R.style.your_style);
    TextView textView = new TextView(wrappedContext, null, 0);
  2. Con el constructor de cuatro argumentos (disponible a partir de LOLLIPOP):

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

Lo clave para ambas soluciones: el defStyleAttrparámetro debe ser 0 para aplicar nuestro estilo a la vista.

DmitryArc
fuente
5

Cambiar estilos dinámicamente no es compatible (todavía). Debe establecer el estilo antes de que se cree la vista, a través de XML.

Chris Cashwell
fuente
20
que resulta ser lo mismo, en realidad
njzk2
@ njzk2 gracias ... obviamente no pensó en su comentario antes de publicar. No hay forma de establecer el estilo mediante programación antes de que se construya la interfaz de usuario, por lo tanto, se usaría el mismo código para cambiar o establecer el estilo mediante programación.
Chris Cashwell
3

La respuesta aceptada fue una gran solución para mí. Lo único para agregar es sobre el inflate()método.

En la respuesta aceptada android:layout_*no se aplicarán todos los parámetros.

La razón no es forma de ajustarlo, la causa nullse pasó como ViewGroup parent.

Puedes usarlo así:

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

y el parentes el ViewGroup, desde donde te gusta ajustarandroid:layout_* .

En este caso, se establecerán todas las propiedades relativas.

Espero que sea útil para alguien.

Anor
fuente
2

Al usar vistas personalizadas que pueden usar herencia de estilo (o atributos con estilo de evento), debe modificar el segundo constructor para no perder el estilo. Esto funcionó para mí, sin necesidad de usar setTextAppearence () :

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

También conocí el problema y encontré la manera de establecer un estilo programáticamente. Quizás todos lo necesiten, así que actualizo allí.

El tercer parámetro de View constructor acepta un tipo de atributo en su tema como el código fuente a continuación:

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

Por lo tanto, debe pasar un tipo de R.attr. ** en lugar de R.style. **

En mis códigos, hice los siguientes pasos:

Primero, personalice un atributo personalizado para que lo utilicen los temas en attr.xml.

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

Segundo, especifique su estilo en su tema usado en 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>

¡Al final, úsalo!

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

la vista creada programáticamente usará el estilo especificado en su tema.

Puedes intentarlo y esperar que te funcione perfectamente.

mrtwo
fuente
0

Solo he probado con EditText pero puedes usar el método

public void setBackgroundResource (int resid)

para aplicar un estilo definido en un archivo XML.

Sine este método pertenece a View. Creo que funcionará con cualquier elemento de la interfaz de usuario.

Saludos.

floydaddict
fuente
Según la documentación, esto solo debería funcionar con elementos dibujables, no con estilo. Por lo tanto, si esto realmente funciona, es solo "por accidente" y no debe confiar en ello.
Heinzi
0

Podemos usar TextViewCompact.setTextAppearance(textView, R.style.xyz).

Documento de Android para referencia.

Kshitij Jain
fuente