2011-02-02 13 views
21

¿Es posible establecer una configuración de toda la aplicación para el tamaño de fuente que utilizarán todas las vistas que muestren texto? Me gustaría proporcionar una preferencia para el usuario que debería permitir escalar todo el texto en la aplicación.Android: preferencia de tamaño de fuente en toda la aplicación

Android explícitamente permite utilizar el texto escalable "sp" dimension unit, sin embargo, no hay una forma real de establecer la "preferencia de tamaño de fuente del usuario" de forma global.

Iterar a través de todos los puntos de vista sobre la instanciación actividad no es realmente una opción ;-)

+0

posible duplicado de [Cambiar dinámicamente el tamaño de la vista de texto múltiple desde el código (sin un tema xml "en disco")?] (Http://stackoverflow.com/questions/4473397/dynamically-change-size-of-multiple- textview-from-code-without-a-on-disk-xml-t) –

+0

Esta pregunta se ha debatido varias veces, consulte http://stackoverflow.com/questions/4473397/dynamically-change-size-of- multiple-textview-from-code-without-a-on-disk-xml-t para obtener una lista de otros enlaces relevantes. –

Respuesta

46

Aquí así es como lo hice para mi aplicación. En pocas palabras: en Activity.onCreate() obtienes la identificación de recursos de estilo con un conjunto específico de tamaños de fuente y aplicas este estilo al tema de actividad. Luego, con la actividad de preferencias puede cambiar entre estos conjuntos.

Primero de todos en valores/atributos.atributos XML para declarar conjunto de tamaños de fuente:

<declare-styleable name="FontStyle"> 
    <attr name="font_small" format="dimension" /> 
    <attr name="font_medium" format="dimension" /> 
    <attr name="font_large" format="dimension" /> 
    <attr name="font_xlarge" format="dimension" /> 
</declare-styleable> 

Luego, en valores/styles.xml declaran unos conjuntos de tamaños de fuente:

<style name="FontStyle"> 
</style> 

<style name="FontStyle.Small"> 
    <item name="font_small">14sp</item> 
    <item name="font_medium">16sp</item> 
    <item name="font_large">18sp</item> 
    <item name="font_xlarge">20sp</item> 
</style> 

<style name="FontStyle.Medium"> 
    <item name="font_small">18sp</item> 
    <item name="font_medium">20sp</item> 
    <item name="font_large">22sp</item> 
    <item name="font_xlarge">24sp</item> 
</style> 

<style name="FontStyle.Large"> 
    <item name="font_small">26sp</item> 
    <item name="font_medium">28sp</item> 
    <item name="font_large">30sp</item> 
    <item name="font_xlarge">32sp</item> 
</style> 

Luego, en onCreate() método para cada actividad Añadir:

getTheme().applyStyle(new Preferences(this).getFontStyle().getResId(), true); 

donde Preferences es una fachada para SharedPreferences objeto:

public class Preferences { 
    private final static String FONT_STYLE = "FONT_STYLE"; 

    private final Context context; 

    public Preferences(Context context) { 
     this.context = context; 
    } 

    protected SharedPreferences open() { 
     return context.getSharedPreferences("prefs", Context.MODE_PRIVATE); 
    } 

    protected Editor edit() { 
     return open().edit(); 
    } 

    public FontStyle getFontStyle() { 
     return FontStyle.valueOf(open().getString(FONT_STYLE, 
      FontStyle.Medium.name())); 
    } 

    public void setFontStyle(FontStyle style) { 
     edit().putString(FONT_STYLE, style.name()).commit(); 
    } 
} 

y FontStyle es:

public enum FontStyle { 
    Small(R.style.FontStyle_Small, "Small"), 
    Medium(R.style.FontStyle_Medium, "Medium"), 
    Large(R.style.FontStyle_Large, "Large"); 

    private int resId; 
    private String title; 

    public int getResId() { 
     return resId; 
    } 

    public String getTitle() { 
     return title; 
    } 

    FontStyle(int resId, String title) { 
     this.resId = resId; 
     this.title = title; 
    } 
} 

Y FontStyle.values() se utiliza como artículos para Spinner en su PreferencesActivity. Así es como el mío se parece a:

public class PreferencesActivity extends Activity { 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    getTheme().applyStyle(new Preferences(this).getFontStyle().getResId(), true); 
    super.onCreate(savedInstanceState); 

    setContentView(R.layout.preferences); 

    Preferences prefs = new Preferences(this); 

    Spinner fontStylesView = (Spinner) findViewById(R.id.font_styles); 
    FontStylesAdapter adapter = new FontStylesAdapter(this, 
      R.layout.font_styles_row, FontStyle.values()); 
    fontStylesView.setAdapter(adapter); 

    fontStylesView.setSelection(prefs.getFontStyle().ordinal()); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    MenuInflater inflater = getSupportMenuInflater(); 
    inflater.inflate(R.menu.preferences, menu); 
    return super.onCreateOptionsMenu(menu); 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    switch (item.getItemId()) { 
    case R.id.menu_done: 
     onMenuDone(); 
     finish(); 
     return true; 
    case R.id.menu_cancel: 
     finish(); 
     return true; 
    default: 
     return false; 
    } 
} 

private void onMenuDone() { 
    Preferences prefs = new Preferences(this); 

    Spinner fontStylesView = (Spinner) findViewById(R.id.font_styles); 
    prefs.setFontStyle((FontStyle) fontStylesView.getSelectedItem()); 
} 
} 

Y finalmente usted puede utilizar sus preferencias de tamaño de las fuentes:

<TextView android:textSize="?attr/font_large" /> 

O prefiero usar estilos, en los valores/styles.xml añadir:

<style name="Label" parent="@android:style/Widget.TextView"> 
    <item name="android:textSize">?attr/font_medium</item> 
    <item name="android:layout_width">wrap_content</item> 
    <item name="android:layout_height">wrap_content</item> 
</style> 

<style name="Label.XLarge"> 
    <item name="android:textSize">?attr/font_xlarge</item> 
</style> 

Y puede usarlo de esta manera:

<TextView style="@style/Label.XLarge" /> 

Espero que mi respuesta te ayude.

+0

Supongamos que ya tengo un tema configurado para mi actividad. Ahora quiero establecer FontStyle.Medium como predeterminado para todas las actividades. Si defino 'textSize ="? Attr/font_medium "', se bloquea porque la actividad no la conoce. Entonces, esto solo funciona si llamo a 'getTheme(). ApplyStyle()' ¿verdad? – Enigma

+0

Sí. Con declare-styleable declaras algunos atributos. En los estilos, defines valores para estos atributos. Y luego necesita aplicar uno de estos estilos al tema de actividad. Cuál se define por las preferencias guardadas. – mixel

+0

¿Se aplica "applyStyle" inmediatamente? ¿O extraño algo? – wangqi060934

6

Sí, es posible. Para ello es necesario:

  1. Declarar su propia clase que se extiende TextView
  2. uso en todos los cuadros de diálogo/actividades única que

igual:

public class SimpleTextView extends TextView 
{ 
    private static final float DEFAULT_TEXT_SIZE=12.0; 
    private static float textSize=DEFAULT_TEXT_SIZE; 

    public SimpleTextView(Context context) 
    { 
     super(context); 
     this.setTextSize(textSize); 
    } 

    public SimpleTextView(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
     this.setTextSize(textSize); 
    } 

    public SimpleTextView(Context context, AttributeSet attrs, int defStyle) 
    { 
     super(context, attrs, defStyle); 
     this.setTextSize(textSize); 
    } 

    public static void setGlobalSize(float size) 
    { 
     textSize=size; 
    } 

    public static float getGlobalSize() 
    { 
     return textSize; 
    } 
} 

Y ahora whereever usted puede cambiar globalmente todos los tamaños de texto a 20 en todas las textviews con solo llamar:

SimpleTextView.setGlobalTextSize(20); 
+4

Eso funciona para el texto que aparece en 'TextView's, pero ¿qué pasa con todas las subclases' TextView' como 'EditText',' Button', 'CheckedTextView', etc.? Básicamente necesitarías crear subclases de cada tipo de widget que usas ... –

+0

@Mayra: ese derecho - Me obligaron a hacerlo ... quiero decir que no es muy divertido, pero el resultado es fascinante :) – barmaley

+0

Esta solución requiere derivar de cualquier clase View con visualización de texto, y se necesita hacer más trabajo para agregar un factor de escala (para que pueda tener una escala de texto de 10sp y 20sp manteniendo la relación de tamaño 2x), pero veo hacia dónde se dirige Gracias. – ge0rg

1

disparar sin apuntar aquí es la idea a tener en cuenta (sin aplicación de Vista de Texto de encargo requiere)

  1. declarar bienes algo así como UNIVERSAL_FONT_SIZE con la idea de que se puede cambiar de configuración, pero se mantendrá entre invocaciones de aplicaciones
  2. En
  3. onCreate método para cada una de sus actividades logran un valor de dicha propiedad y guardar como un campo
  4. garantizar que utiliza el código que para cada componente de texto de tamaño variable
  5. Nada va a actuar ualmente le impiden crear varias propiedades como BUTTONS_TXT_SIZE, TEXT_SIZE, LIST_TXT_SIZE, etc. y luego tiene una lógica que toma, por ejemplo, el porcentaje de aumento de texto y los tamaños adecuados calculados para cada tipo de control (ya que puede tener diferentes tamaños para diferentes controles)

En la misma línea, supongamos que quiere que esto funcione dinámicamente. Crear una clase simple (digamos TextSetter) que mantiene lista interna y tienen 3 métodos: añadir, eliminar y setSize

  1. En Activity#onCreate identificar cada control que desea ajustar y utilizar TextSetter#set para añadirlo a la lista
  2. Cuando el usuario quiere aumentar/disminuir el tamaño de la fuente tal vez en el menú, cuando manipule que acaba de ejecutar TextSetter # setSize en el que se bucle a través de la lista de controles, detectar qué tipo es y ajustar el tamaño del texto en consecuencia
+0

Esto va en la dirección correcta. Ya traté de anular el ancho del sistema [escala de la fuente] (http://android.git.kernel.org/?p=platform/development.git; a = blob; f = aplicaciones/SpareParts/src/com/android/spare_parts/SpareParts.java; h = 099f27a9ba76e8a39accf36b45bb699e69d05b9c; hb = HEAD # l187), sin embargo, el 'ActivityManagerNative' parece ser solo utilizable desde el propio Android. La aplicación de ejemplo SpareParts, que proporciona el código vinculado, permite configurar la fuente de una manera global de la aplicación. No quiero utilizar trucos sucios para acceder a esa API, pero parece que no hay una solución realmente elegante para eso. – ge0rg

0

Para quienes tienen problemas con el inflado de vistas con atributos personalizados desde @mixels answer.

Si sus puntos de vista están fragmentados, debe aplicar FontStyle también en el fragmento onCreateView() o establecer los valores de estos atributos en el tema de la aplicación.

Para más detalles, vea mi aswer here.

Cuestiones relacionadas