El tema / estilo no se aplica cuando se usa un inflador con ApplicationContext

Tengo el tema que especifica textColor para TextView como rojo.

Estoy usando LayoutInflater para instanciar TextView. El problema es que los estilos no se aplican a TextView cuando se crea un inflater con ApplicationContext, el color no es rojo. Todo funciona bien cuando LayoutInflater crea usando la actividad.

¿Por qué sucede esto y cómo se puede solucionar?

/res/values/styles.xml:

   @style/MyTextView   #f00   

AndroidManifest.xml:

  

Código:

 public class A extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_a); final LayoutInflater goodInflater = getInflater((Activity)this); final LayoutInflater badInflater = getInflater(getApplicationContext()); final LinearLayout container = (LinearLayout)findViewById(R.id.container); findViewById(R.id.add_with_appContext).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { add(container, badInflater); // Creates gray TextView } }); findViewById(R.id.add_with_activity).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { add(container, goodInflater); // Creates red TextView } }); } private LayoutInflater getInflater(Context context) { return (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } private void add(LinearLayout container, LayoutInflater inflater) { inflater.inflate(R.layout.my_template, container, true); } } 

/res/layout/test_a.xml

   

/res/layout/my_template.xml:

     

Solución n. ° 1

El método inflate acepta el argumento opcional ‘ViewGroup root’:

 public View inflate (int resource, ViewGroup root, boolean attachToRoot) 

Si tenemos valor para pasar como parámetro ‘raíz’, entonces podemos usarlo para obtener ‘contexto de actividad’ desde donde podemos obtener el LayoutInflater correcto:

 ViewGroup root > activity context > LayoutInflater 

Entonces mi código podría ser:

 private void add(LinearLayout container) { LayoutInflater inflater = getInflater(container.getContext()); inflater.inflate(R.layout.my_template, container, true); } 

Solución n. ° 2

Solo traté de establecer el tema Contexto de la Aplicación mediante progtwigción, y funciona :

 getApplicationContext().setTheme(R.style.MyTheme); 

Creo que era lógico esperar este marcado:

  

para establecerlo automáticamente, pero no es así.

Nunca utilice un contexto de aplicación para inflar las vistas, porque el estilo no funciona con este contexto. Utilice siempre el contexto de una actividad cuando juegue con vistas. La única excepción es cuando necesita crear RemoteViews desde un servicio.

Se puede encontrar más información sobre los diferentes tipos de contextos y sus capacidades en este excelente artículo .

Por lo general, me encuentro con este problema al inflar una vista personalizada. Esto es lo que personalmente hago para mantener el mismo tema de la actividad en CustomView.

 public class CustomView extends ViewGroup{ public CustomView (Context context) { super(context); init(context); } public CustomView (Context context, AttributeSet attrs) { super(context, attrs); init(context); } public CustomView (Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } @TargetApi(21) public CustomView (Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(context); } private void init(Context context) { LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View v = mInflater.inflate(R.layout.review_list_item, this, true); //rest of view initialization } }