Uso de la fuente personalizada en Android TextView utilizando xml
He añadido un archivo de fuentes personalizadas a mi carpeta de recursos / fuentes. ¿Cómo lo uso desde mi XML?
Puedo usarlo del código de la siguiente manera:
- ¿Cómo puedo obtener nodos específicos de XML usando XPath en Java?
- ¿cómo puedo crear este tipo de diseño de chat en mi aplicación?
- ¿Cómo puedo editar las dimensiones de un elemento de menú PopUp en Android?
- Android hdpi / mdpi / ldpi para la carpeta Valores?
- Manejando espacios de nombres Xml con XmlPullParser
TextView text = (TextView) findViewById(R.id.textview03); Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/Molot.otf"); text.setTypeface(tf);
¿No puedo hacerlo desde XML usando un atributo android:typeface="/fonts/Molot.otf"
?
- ¿Establecer un fondo a los botones en un diálogo?
- ¿Es posible guardar layout_weight en un xml?
- Android: Qué práctica es mejor para usar CoordinatorLayout
- Análisis de un XML HttpResponse
- Disposición de Android: coloca una vista entre dos vistas
- Lista de lecturas <Item> con retrofit de XML API
- Visualización de la variable en pantalla usando Android por TextViews
- Cargar valor desde dimens.xml y hacer negativo
Respuesta corta: No. Android no tiene soporte incorporado para aplicar fuentes personalizadas a widgets de texto a través de XML.
Sin embargo, hay una solución que no es terriblemente difícil de implementar.
primero
Tendrá que definir su propio estilo. En su carpeta / res / values, abra / cree el archivo attrs.xml y añada un objeto declarable como:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="FontText"> <attr name="typefaceAsset" format="string"/> </declare-styleable> </resources>
Segundo
Suponiendo que desee utilizar este widget a menudo, debe configurar una caché simple para los objetos de tipo de Typeface
cargados, ya que cargarlos de memoria en marcha puede llevar tiempo. Algo como:
public class FontManager { private static FontManager instance; private AssetManager mgr; private Map<String, Typeface> fonts; private FontManager(AssetManager _mgr) { mgr = _mgr; fonts = new HashMap<String, Typeface>(); } public static void init(AssetManager mgr) { instance = new FontManager(mgr); } public static FontManager getInstance() { return instance; } public Typeface getFont(String asset) { if (fonts.containsKey(asset)) return fonts.get(asset); Typeface font = null; try { font = Typeface.createFromAsset(mgr, asset); fonts.put(asset, font); } catch (Exception e) { } if (font == null) { try { String fixedAsset = fixAssetFilename(asset); font = Typeface.createFromAsset(mgr, fixedAsset); fonts.put(asset, font); fonts.put(fixedAsset, font); } catch (Exception e) { } } return font; } private String fixAssetFilename(String asset) { // Empty font filename? // Just return it. We can't help. if (StringUtils.isEmpty(asset)) return asset; // Make sure that the font ends in '.ttf' or '.ttc' if ((!asset.endsWith(".ttf")) && (!asset.endsWith(".ttc"))) asset = String.format("%s.ttf", asset); return asset; } }
Éste le permitirá usar las extensiones de archivo .ttc, pero no ha sido probado.
Tercero
Cree una nueva clase que subclases TextView
. Este ejemplo particular toma en cuenta el tipo de letra XML definido ( bold
, italic
, etc.) y lo aplica a la fuente (suponiendo que esté utilizando un archivo .ttc).
/** * TextView subclass which allows the user to define a truetype font file to use as the view's typeface. */ public class FontText extends TextView { public FontText(Context context) { this(context, null); } public FontText(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FontText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); if (isInEditMode()) return; TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.FontText); if (ta != null) { String fontAsset = ta.getString(R.styleable.FontText_typefaceAsset); if (!StringUtils.isEmpty(fontAsset)) { Typeface tf = FontManager.getInstance().getFont(fontAsset); int style = Typeface.NORMAL; float size = getTextSize(); if (getTypeface() != null) style = getTypeface().getStyle(); if (tf != null) setTypeface(tf, style); else Log.d("FontText", String.format("Could not create a font from asset: %s", fontAsset)); } } } }
Finalmente
Reemplace las instancias de TextView
en su XML con el nombre de clase totalmente calificado. Declare su espacio de nombres personalizado como lo haría con el espacio de nombres de Android. Tenga en cuenta que el "typefaceAsset" debe apuntar a un archivo .ttf o .ttc contenido en su directorio / assets.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <com.example.FontText android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="This is a custom font text" custom:typefaceAsset="fonts/AvenirNext-Regular.ttf"/> </RelativeLayout>
Aquí está un código de ejemplo que hace esto. Tengo la fuente definida en una variable final estática y el archivo de fuente está en el directorio de activos.
public class TextViewWithFont extends TextView { public TextViewWithFont(Context context, AttributeSet attrs) { super(context, attrs); this.setTypeface(MainActivity.typeface); } public TextViewWithFont(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.setTypeface(MainActivity.typeface); } public TextViewWithFont(Context context) { super(context); this.setTypeface(MainActivity.typeface); } }
La actividad implementa LayoutInflater.Factory2 que proporciona devoluciones de llamada en cada vista creada. Es posible diseñar el TextView con el atributo fontFamily personalizado, cargar los tipos de letra a petición y llamar a setTypeface a las vistas de texto instanciadas automáticamente.
Desafortunadamente debido a la relación arquitectónica de las instancias de Inflater en relación con las actividades y Windows, el enfoque más sencillo es almacenar en caché las fuentes cargadas en el nivel de aplicación.
La base de código de ejemplo está aquí:
https://github.com/leok7v/android-textview-custom-fonts
<style name="Baroque" parent="@android:style/TextAppearance.Medium"> <item name="android:layout_width">fill_parent</item> <item name="android:layout_height">wrap_content</item> <item name="android:textColor">#F2BAD0</item> <item name="android:textSize">14pt</item> <item name="fontFamily">baroque_script</item> </style> <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res/custom.fonts" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView style="@style/Baroque" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/sample_text" />
Resulta en
Cree su TextView personalizado pertenezca a la fuente que desea utilizar. En esta clase, utilizo un campo mTypeface estático para almacenar en caché el Typeface (para un mejor rendimiento)
public class HeliVnTextView extends TextView { /* * Caches typefaces based on their file path and name, so that they don't have to be created every time when they are referenced. */ private static Typeface mTypeface; public HeliVnTextView(final Context context) { this(context, null); } public HeliVnTextView(final Context context, final AttributeSet attrs) { this(context, attrs, 0); } public HeliVnTextView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); if (mTypeface == null) { mTypeface = Typeface.createFromAsset(context.getAssets(), "HelveticaiDesignVnLt.ttf"); } setTypeface(mTypeface); } }
En el archivo xml:
<java.example.HeliVnTextView android:id="@+id/textView1" android:layout_width="0dp" ... />
En clase java:
HeliVnTextView title = new HeliVnTextView(getActivity()); title.setText(issue.getName());
No es una buena idea utilizar fuentes personalizadas en xml debido a este hecho que es, hay que hacerlo mediante programación para evitar la pérdida de memoria!
UPDATE: https://github.com/chrisjenx/Caligraphy parece ser una solución superior a esto.
¿Tal vez usted puede utilizar la reflexión para inyectar / cortar su fuente en la lista estática de fuentes disponibles cuando se crea su aplicación? Estoy interesado en la retroalimentación de los demás si esto es una idea realmente, muy mala o si esto es una gran solución – parece que va a ser uno de esos extremos …
Fui capaz de inyectar mi tipo de letra personalizado en la lista de tipos de letra de sistema con mi propio nombre de familia de fuente, a continuación, especificando que el nombre de familia de la fuente personalizada ("brush-script") como el valor de android: FontFamily en un TextView estándar trabajó en mi LG G4 con Android 6.0.
public class MyApplication extends android.app.Application { @Override public void onCreate() { super.onCreate(); Typeface font = Typeface.createFromAsset(this.getResources().getAssets(),"fonts/brush-script.ttf"); injectTypeface("brush-script", font); } private boolean injectTypeface(String fontFamily, Typeface typeface) { try { Field field = Typeface.class.getDeclaredField("sSystemFontMap"); field.setAccessible(true); Object fieldValue = field.get(null); Map<String, Typeface> map = (Map<String, Typeface>) fieldValue; map.put(fontFamily, typeface); return true; } catch (Exception e) { Log.e("Font-Injection", "Failed to inject typeface.", e); } return false; } }
En mi diseño
<TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Fancy Text" android:fontFamily="brush-script"/>
En lugar de xmlns: custom = "schemas.android.com/tools"; Usted debe usar: xmlns: custom = "schemas.android.com/apk/res-auto"; Con el fin de utilizar atributos con estilo. Hice este cambio y ahora está funcionando.
Cree una carpeta de fuentes en los recursos y agregue todos los tipos de letra necesarios allí.
public class CustomTextView extends TextView { private static final String TAG = "TextView"; public CustomTextView(Context context) { super(context); } public CustomTextView(Context context, AttributeSet attrs) { super(context, attrs); setCustomFont(context, attrs); } public CustomTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setCustomFont(context, attrs); } private void setCustomFont(Context ctx, AttributeSet attrs) { TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.CustomTextView); String customFont = a.getString(R.styleable.CustomTextView_customFont); setCustomFont(ctx, customFont); a.recycle(); } public boolean setCustomFont(Context ctx, String fontName) { Typeface typeface = null; try { if(fontName == null){ fontName = Constants.DEFAULT_FONT_NAME; } typeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/" + fontName); } catch (Exception e) { Log.e(TAG, "Unable to load typeface: "+e.getMessage()); return false; } setTypeface(typeface); return true; } }
Y añadir un declarable en attrs.xml
<declare-styleable name="CustomTextView"> <attr name="customFont" format="string"/> </declare-styleable>
Y luego agrega tu customFont como
app:customFont="arial.ttf"
- OnActivityResult () no se llama en el nuevo API de fragmentos anidados
- API para cargar automáticamente apk en Google Play?