programacion - manual de android en pdf
Implementando la elección del usuario del tema (3)
Quiero darle al usuario la opción entre algunos temas diferentes, y me preguntaba si esta es una forma correcta de hacer las cosas. Hice una pequeña prueba con este método y funcionó, pero creo que puede haber mejores formas y creo que puede causar algunos problemas más adelante, por lo que quería preguntar.
Estaba pensando en crear un diseño diferente para cada tema y en onCreate
solo tengo un cambio para el método setContentView()
. SharedPreference
valor de SharedPreference
guardado (entero) y, dependiendo de qué valor se mostrara, mostraría el diseño correspondiente. Obviamente, el usuario podría cambiar el valor SharedPreference
con un botón o algo así.
Como estos diseños serían básicamente los mismos, pero con colores diferentes, me gustaría usar los mismos ID para mis TextViews
y otras Vistas en cada archivo de diseño. Mi pregunta principal es si esto causaría problemas?
Perdón por el muro de texto sin código. Me gustaría obtener una idea general de las buenas prácticas para esta situación. Gracias por adelantado.
De hecho, tengo esta característica en mi aplicación y, además, les permito a los usuarios cambiar el tema en tiempo de ejecución. Como la lectura de un valor de las preferencias lleva algo de tiempo, obtengo una identificación de tema a través de una función accesible globalmente que contiene el valor en caché.
Como ya se señaló, cree algunos temas de Android usando esta guía . Tendrás al menos dos elementos <style>
en tu archivo styles.xml
. Por ejemplo:
<style name="Theme.App.Light" parent="@style/Theme.Light">...</style>
<style name="Theme.App.Dark" parent="@style/Theme">...</style>
Ahora, debe aplicar uno de estos estilos a sus actividades. Estoy haciendo esto en el método onCreate
la actividad, antes de cualquier otra llamada:
setTheme(MyApplication.getThemeId());
getThemeId
es un método que devuelve ID de tema en caché:
public static int getThemeId()
{
return themeId;
}
Este campo se está actualizando por otro método:
public static void reloadTheme()
{
themeSetting = PreferenceManager.getDefaultSharedPreferences(context).getString("defaultTheme", "0");
if(themeSetting.equals("0"))
themeId = R.style.Theme_Light;
else
themeId = R.style.Theme_Dark;
}
Que se llama cada vez que se cambian las preferencias (y, al inicio del curso). Estos dos métodos residen en la clase MyApplication
, que extiende la Application
. El oyente de cambio de preferencia se describe al final de esta publicación y reside en la clase de actividad principal.
Lo último y bastante importante: el tema se aplica cuando comienza una actividad. Asumiendo, puede cambiar un tema solo en la pantalla de preferencias y que solo hay una manera de llegar allí, es decir, de una sola actividad (principal), esta actividad no se reiniciará cuando salga de la pantalla de preferencias: el tema anterior seguirá siendo usado. Aquí está la solución para eso (reinicia su actividad principal):
@Override
protected void onResume() {
super.onResume();
if(schduledRestart)
{
schduledRestart = false;
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
}
scheduledRestart
es una variable booleana, inicialmente establecida en falso. Se establece en true cuando el tema es modificado por este oyente, que también actualiza el ID del tema en caché mencionado anteriormente:
private class themeListener implements OnSharedPreferenceChangeListener{
@Override
public void onSharedPreferenceChanged(SharedPreferences spref, String key) {
if(key.equals("defaultTheme") && !spref.getString(key, "0").equals(MyApplication.getThemeSetting()))
{
MyApplication.reloadTheme();
schduledRestart = true;
}
}
sp = PreferenceManager.getDefaultSharedPreferences(this);
listener = new themeListener();
sp.registerOnSharedPreferenceChangeListener(listener);
Recuerde mantener una referencia al objeto detector, de lo contrario será basura (y dejará de funcionar).
Funciona si lo haces de esta manera, y no creo que cause ningún problema, pero parece una gran molestia (tienes que multiplicar todos tus diseños por todos los temas que quieras agregar. Si quieres modificar un recurso en un diseño, tendrás que modificarlo en todos los temas. Definitivamente debes olvidarlo.
¿Por qué no usar la función Estilos y temas de Android?
Se pueden aplicar fácilmente a toda la actividad:
<activity android:theme="@style/my_theme">
De modo que cuando detecte un cambio en el valor de SharedPreferences
que usa (botón en una actividad de preferencia, o algo así), simplemente puede cambiar el estilo. O mejor, puede configurar el estilo para leer su valor de preferencia en el tiempo de ejecución (al crear la actividad) y aplicar el estilo / tema correcto en consecuencia.
También puede cambiar dinámicamente el tema usando:
ContextThemeWrapper w = new ContextThemeWrapper(this, <newTHEMEId>);
getTheme().setTo(w.getTheme());
Antes de onCreate para cada actividad.