¿Es posible configurar una fuente personalizada en una aplicación de Android?
Probé lo que se publica aquí , pero no sé dónde está mi extends Application
clase ...
¿Alguna ayuda?
EDITAR:
Intenté lo siguiente:
- Agregue una carpeta de activos e inserte la fuente dentro como se ve aquí:
Agregue una nueva clase que se extienda desde
Application
Llame a esta nueva clase de mi
AndroidManifest.xml
.Fui a mi estilo y lo agregué.
MyApp.java:
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
FontsOverride.setDefaultFont(this, "DEFAULT", "raleway_regular.ttf");
// This FontsOverride comes from the example I posted above
}
}
AndroidManifest.xml:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:name=".MyApp"
android:theme="@style/AppTheme">
....
styles.xml:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:fontFamily">default</item>
</style>
Pero mi fuente todavía no cambia ... ¿alguna idea?
Entonces MyApp
se llama a la clase. Pero ningún efecto en mis fuentes ...
EDIT2: Me di cuenta de que mis botones aplican la fuente personalizada después de establecer un estilo personalizado para mis botones. Aquí está mi estilo de botón personalizado:
<style name="MyButtonStyle" parent="Widget.AppCompat.Button">
<item name="textAllCaps">false</item>
<item name="android:textAllCaps">false</item>
</style>
Y así es como se ve ahora:
Entonces: mi botón está aplicando el estilo, pero no el TextView
. ¿Alguna idea de por qué mi fuente personalizada no se aplica a todos los elementos de la aplicación?
fuente
Respuestas:
Escribe una clase
public class MyApp extends Application{ // Put the onCreate code as you obtained from the post link you reffered }
ahora lo siguiente es en AndroidManifest.xml para que la etiqueta de la aplicación dé nombre a su clase de aplicación. En este caso es MyApp
<application android:name=".MyApp" ... > ... </application>
Entonces, cada vez que se abre la aplicación, se invoca el método onCreate de la clase MyApp y se establece la fuente.
Actualizar Coloque el archivo de fuente en assets / fonts / your_font_file.ttf
Ponga esta línea debajo del método onCreate de su clase de aplicación (MyApp)
TypefaceUtil.overrideFont(getApplicationContext(), "SERIF", "fonts/your_font_file.ttf");
Archivo fuente para TypefaceUtil
public class TypefaceUtil { /** * Using reflection to override default typeface * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE OVERRIDDEN * * @param context to work with assets * @param defaultFontNameToOverride for example "monospace" * @param customFontFileNameInAssets file name of the font from assets */ public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) { final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Map<String, Typeface> newMap = new HashMap<String, Typeface>(); newMap.put("serif", customFontTypeface); try { final Field staticField = Typeface.class .getDeclaredField("sSystemFontMap"); staticField.setAccessible(true); staticField.set(null, newMap); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } else { try { final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride); defaultFontTypefaceField.setAccessible(true); defaultFontTypefaceField.set(null, customFontTypeface); } catch (Exception e) { Log.e(TypefaceUtil.class.getSimpleName(), "Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride); } } } }
Ahora actualice su archivo style.xml
ponga la línea de abajo su estilo que se incluye para su actividad en el archivo de manifiesto
<item name="android:typeface">serif</item>
Espero que esto ayude
fuente
EDITAR
uk.co.chrisjenx:calligraphy
Lib no se mantiene más para la última versión de Android alternativa ahora es https://github.com/InflationX/Calligraphydependencies { implementation 'io.github.inflationx:calligraphy3:3.1.1' implementation 'io.github.inflationx:viewpump:2.0.3' }
Agregue sus fuentes personalizadas a los activos /
Uso
Para fuente predeterminada
Defina su fuente predeterminada usando CalligraphyConfig, en su clase Application en el método #onCreate () y páselo al CalligraphyInterceptor que agrega a su constructor ViewPump.
@Override public void onCreate() { super.onCreate(); ViewPump.init(ViewPump.builder() .addInterceptor(new CalligraphyInterceptor( new CalligraphyConfig.Builder() .setDefaultFontPath("fonts/Roboto-RobotoRegular.ttf") .setFontAttrId(R.attr.fontPath) .build())) .build()); //.... }
Inyectar en el contexto: envolver el contexto de la actividad:
@Override protected void attachBaseContext(Context newBase) { super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase)); }
Estilo personalizado
<style name="TextViewCustomFont"> <item name="fontPath">fonts/RobotoCondensed-Regular.ttf</item> </style>
Por tema
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar"> <item name="android:textViewStyle">@style/AppTheme.Widget.TextView</item> </style> <style name="AppTheme.Widget"/> <style name="AppTheme.Widget.TextView" parent="android:Widget.Holo.Light.TextView"> <item name="fontPath">fonts/Roboto-ThinItalic.ttf</item> </style>
No más mantenido por desarrolladores debajo de la solución
Hay una gran biblioteca para fuentes personalizadas en Android: Caligrafía
Aquí hay una muestra de cómo usarlo.
En Gradle, debe poner esta línea en el archivo build.gradle de su aplicación:
dependencies { compile 'uk.co.chrisjenx:calligraphy:2.2.0' }
Y luego crea una clase que amplíe Application y escribe este código:
public class App extends Application { @Override public void onCreate() { super.onCreate(); CalligraphyConfig.initDefault(new CalligraphyConfig.Builder() .setDefaultFontPath("your font path") .setFontAttrId(R.attr.fontPath) .build() ); } }
Debería haber hecho en assets / un "Nuevo directorio" "fuentes" (ver más abajo), por lo que en ese código "su ruta de fuente" debe ser "fuentes / SourceSansPro-Regular.ttf". (Son solo "fuentes ..." no "/ fuentes ..." o "recursos ...")
Y en la clase de actividad ponga este método antes de onCreate:
@Override protected void attachBaseContext(Context newBase) { super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase)); }
Y la última cosa que su archivo de manifiesto debería verse así:
<application . . . android:name=".App">
¡Y cambiará toda la actividad a tu fuente! ¡es simple y limpio!
En Activos, debe hacer clic con el botón derecho en Nuevo directorio, llamarlo "fuentes". En el buscador, coloque los
.ttf
archivos de fuentes allí.Además, no olvide agregar debajo de dos líneas en attrs.xml, si no tiene el archivo attrs.xml, cree un nuevo archivo en values.xml
<attr format="string" name="fontPath"/> <item name="calligraphy_tag_id" type="id"/>
fuente
attachBaseContext(..)
se implementa, y luego todas las clases de actividad de mi proyecto (donde quiero esa fuente personalizada) extienden esa clase baseTodo lo que hice fue:
1: Se agregó "nuevo directorio de recursos" a la carpeta RES, se seleccionó el TIPO DE RECURSO como "fuente" en el menú desplegable, se denominó "fuente" al nuevo directorio y se guardó.
2: Agregué mi "custom_font.ttf" a la carpeta FONT recién creada.
3: Agregué mi fuente personalizada en el tema base de la aplicación en STYLES.XML
HECHO.
fuente
Puede hacerlo con el SDK de Android ahora, ya que el canal oficial de YouTube para desarrolladores de Android publicado en set / 2017 aquí .
Requiere API nivel 26 (Android 8 Oreo) y superior.
Solo necesita poner su archivo de fuente en la
res/font
carpeta y hacer referencia a ellos en suTextView
caso que necesite uno específico con elandroid:fontFamily
atributo.Si desea una fuente base en toda su aplicación, simplemente coloque
<item name="android:fontFamily">@font/yourfontname</item>
en tus
styles.xml
Puede descargar una fuente personalizada desde Android Studio y sobre la marcha si lo desea también. Todo esto lo puedes encontrar con detalles en el video de arriba.
fuente
Android ofrece las mejores y más sencillas soluciones que son compatibles con el nivel de API 14 por Support Library 26+. Fuentes en XML También admite la opción de familia de fuentes . Importación requerida:
implementation "com.android.support:support-compat:<26+ version>"
Siga estos sencillos pasos y la familia de fuentes se aplicará en su aplicación sin ningún obstáculo:
O use a continuación para configurar el tipo de letra mediante programación
view.setTypeface(ResourcesCompat.getFont(context, R.font.opensans));
fuente
Parece que está usando en
android:fontFamily
lugar deandroid:typeface
en sustyles.xml
.Intenta reemplazar
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="android:fontFamily">default</item> </style>
con
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="android:typeface">default</item> </style>
fuente
Application
, simplemente está creando una subclase de la clase de su aplicaciónApplication
. Entonces, no es necesario que lo conectes.<item name="android:typeface">default</item>
línea dentro<style name="AppTheme" parent="AppBaseTheme">
delres -> values -> styles.xml
archivo de su aplicación como se sugiere en la misma publicación SO?Si sigue el primer tema, esto debería funcionar: Aquí
Sí, con reflexión. Esto funciona ( basado en esta respuesta ):
(Nota: esta es una solución debido a la falta de soporte para fuentes personalizadas, por lo que si desea cambiar esta situación, marque para votar el problema de Android aquí). Nota: No dejes comentarios de "yo también" sobre ese tema, todos los que lo han mirado recibirán un correo electrónico cuando lo hagas. Así que sólo "destaque" por favor.
import java.lang.reflect.Field; import android.content.Context; import android.graphics.Typeface; public final class FontsOverride { public static void setDefaultFont(Context context, String staticTypefaceFieldName, String fontAssetName) { final Typeface regular = Typeface.createFromAsset(context.getAssets(), fontAssetName); replaceFont(staticTypefaceFieldName, regular); } protected static void replaceFont(String staticTypefaceFieldName, final Typeface newTypeface) { try { final Field staticField = Typeface.class .getDeclaredField(staticTypefaceFieldName); staticField.setAccessible(true); staticField.set(null, newTypeface); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
Luego necesita sobrecargar las pocas fuentes predeterminadas, por ejemplo, en una clase de aplicación:
public final class Application extends android.app.Application { @Override public void onCreate() { super.onCreate(); FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf"); FontsOverride.setDefaultFont(this, "MONOSPACE", "MyFontAsset2.ttf"); FontsOverride.setDefaultFont(this, "SERIF", "MyFontAsset3.ttf"); FontsOverride.setDefaultFont(this, "SANS_SERIF", "MyFontAsset4.ttf"); } }
Por supuesto, si está utilizando el mismo archivo de fuente, puede mejorarlo para cargarlo solo una vez.
Sin embargo, tiendo a anular uno, decir "MONOSPACIO", luego configurar un estilo para forzar que la aplicación de tipo de letra sea amplia:
<resources> <style name="AppBaseTheme" parent="android:Theme.Light"> </style> <!-- Application theme. --> <style name="AppTheme" parent="AppBaseTheme"> <item name="android:typeface">monospace</item> </style> </resources>
API 21 Android 5.0
Investigué los informes en los comentarios de que no funciona y parece ser incompatible con el tema Android: Theme.Material.Light.
Si ese tema no es importante para usted, use un tema más antiguo, por ejemplo:
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar"> <item name="android:typeface">monospace</item> </style>
fuente
Cree la carpeta de activos en la carpeta principal, agregue la carpeta de fuentes en ella. agregue su archivo .ttf en la carpeta de fuentes.
Agregue lo siguiente en el tema de su aplicación:
<item name="android:fontFamily">@font/roboto_regular</item> <item name="fontFamily">@font/roboto_regular</item>
Crear clase como TypefaceUtil
import android.content.Context; import android.graphics.Typeface; import android.util.Log; import java.lang.reflect.Field; public class TypefaceUtil { /** * Using reflection to override default typeface * NOTICE: DO NOT FORGET TO SET TYPEFACE FOR APP THEME AS DEFAULT TYPEFACE WHICH WILL BE OVERRIDDEN * @param context to work with assets * @param defaultFontNameToOverride for example "monospace" * @param customFontFileNameInAssets file name of the font from assets */ public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) { try { final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets); final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride); defaultFontTypefaceField.setAccessible(true); defaultFontTypefaceField.set(null, customFontTypeface); } catch (Exception e) { Log.e("Can not set","Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride); } } }
Llámalo en la clase de aplicación o en la actividad del Lanzador.
TypefaceUtil.overrideFont(getApplicationContext(), "fonts/roboto_regular.ttf", "fonts/roboto_regular.ttf"); // font from assets: "assets/fonts/Roboto-Regular.ttf
fuente
res
luego de lanew
opción elegirAndroid Resource Directory
y seleccionarfont
formularioResource type
y presionar OK, esto creará un directorio de fuentes para colocar sus fuentes en él..ttf
archivos de fuentes ahí.Vaya al archivo de estilo del proyecto que existe en la siguiente ruta
res/values/styles.xml
y agregue estilos como ese:<style name="SansSerifFont"> <item name="android:fontFamily">sans-serif</item> </style> <style name="OpenSansFont"> <item name="android:fontFamily">@font/open_sans</item> </style> <style name="IranianSansFont"> <item name="android:fontFamily">@font/iranian_sans</item> </style> <style name="BYekanFont"> <item name="android:fontFamily">@font/b_yekan</item> </style> <style name="DroidArabicFont"> <item name="android:fontFamily">@font/droid_arabic</item> </style>
Vaya a su código y escriba una clase como esta para cambiar la fuente de toda la aplicación:
public class AppFontManager { private AppCompatActivity appCompatActivity; public static final String SANS_SERIF_APP_FONT = "sans_serif"; public static final String B_YEKAN_APP_FONT = "b_yekan"; public static final String DROID_ARABIC_APP_FONT = "droid_arabic"; public static final String IRANIAN_SANS_APP_FONT = "iranian_sans"; public static final String OPEN_SANS_APP_FONT = "open_sans"; public AppAppearanceManager(AppCompatActivity appCompatActivity) { this.appCompatActivity = appCompatActivity; } public void setFont(String fontName){ switch (fontName){ case SANS_SERIF_APP_FONT:{ appCompatActivity.getTheme().applyStyle(R.style.SansSerifFont, true); break; } case B_YEKAN_APP_FONT:{ appCompatActivity.getTheme().applyStyle(R.style.BYekanFont, true); break; } case DROID_ARABIC_APP_FONT:{ appCompatActivity.getTheme().applyStyle(R.style.DroidArabicFont, true); break; } case IRANIAN_SANS_APP_FONT:{ appCompatActivity.getTheme().applyStyle(R.style.IranianSansFont, true); break; } case OPEN_SANS_APP_FONT:{ appCompatActivity.getTheme().applyStyle(R.style.OpenSansFont, true); break; } } } }
Debido a que las fuentes deben establecerse por separado para cada actividad, prefiero escribir una clase para un código más limpio.
Luego llame al método de clase antes de la actividad onCreate
super.onCreate(savedInstanceState)
:@Override protected void onCreate(Bundle savedInstanceState) { new AppAppearanceManager(this).setFont(APP_DEFAULT_FONT); super.onCreate(savedInstanceState); // Do you stuff there... }
Recuerde que si desea cambiar la fuente durante el tiempo de ejecución , escriba una fuente elegida en
SharedPreferences
o etc, luego pase la fuente elegida a todas las actividadessetFont
como arriba.fuente
Primero, cree una nueva clase que anule cualquier Vista que desee personalizar. (por ejemplo, ¿quieres un botón con un tipo de letra personalizado? Ampliar
Button
). Por ejemplo:public class CustomButton extends Button { private final static int ROBOTO = 0; private final static int ROBOTO_CONDENSED = 1; public CustomButton(Context context) { super(context); } public CustomButton(Context context, AttributeSet attrs) { super(context, attrs); parseAttributes(context, attrs); //I'll explain this method later } public CustomButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); parseAttributes(context, attrs); } }
Ahora, si no tiene uno, agregue un documento XML debajo
res/values/attrs.xml
y agregue:<resources> <!-- Define the values for the attribute --> <attr name="typeface" format="enum"> <enum name="roboto" value="0"/> <enum name="robotoCondensed" value="1"/> </attr> <!-- Tell Android that the class "CustomButton" can be styled, and which attributes it supports --> <declare-styleable name="CustomButton"> <attr name="typeface"/> </declare-styleable> </resources>
Bien, con eso fuera del camino, volvamos al
parseAttributes()
método de antes:private void parseAttributes(Context context, AttributeSet attrs) { TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.CustomButton); //The value 0 is a default, but shouldn't ever be used since the attr is an enum int typeface = values.getInt(R.styleable.CustomButton_typeface, 0); switch(typeface) { case ROBOTO: default: //You can instantiate your typeface anywhere, I would suggest as a //singleton somewhere to avoid unnecessary copies setTypeface(roboto); break; case ROBOTO_CONDENSED: setTypeface(robotoCondensed); break; } values.recycle(); }
Ahora estás listo. Puede agregar más atributos para casi cualquier cosa (podría agregar otro para typefaceStyle: negrita, cursiva, etc.) pero ahora veamos cómo usarlo:
<?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/com.yourpackage.name" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.yourpackage.name.CustomButton android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Click Me!" custom:typeface="roboto" /> </LinearLayout>
La
xmlns:custom
línea realmente puede ser cualquier cosa, pero la convención es lo que se muestra arriba. Lo que importa es que es único y por eso se usa el nombre del paquete. Ahora solo usa elcustom:
prefijo para tus atributos y elandroid:
prefijo para los atributos de Android.Una última cosa: si quiere utilizar esto en un estilo (
res/values/styles.xml
), debe no agregar laxmlns:custom
línea. Simplemente haga referencia al nombre del atributo sin prefijo:<style name="MyStyle> <item name="typeface">roboto</item> </style>
fuente
También probé la anulación de fuentes, pero al final no es una solución confiable, lamentablemente las fuentes anuladas requieren más que eso. Puede esperar a que aparezca Android O con fuente personalizada o usar una biblioteca de terceros.
La última solución que encontré fue esta biblioteca de Caligrafía , que fue fácil de iniciar y te permitió usar tantas fuentes como quieras. Mientras revisaba su código fuente, entendí por qué simplemente anular las fuentes no funcionaría, así que incluso si no planea usarlo, le recomiendo leerlo una vez.
Buena suerte
fuente
Pruebe el siguiente código, funciona para mí, espero que también lo ayude.
public class BaseActivity extends AppCompatActivity { private Typeface typeace; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); typeace = Typeface.createFromAsset(getAssets(), getResources().getString(R.string.font_name)); } @Override protected void onStart() { // TODO Auto-generated method stub super.onStart(); overrideFonts(this,getWindow().getDecorView()); } private void overrideFonts(final Context context, final View v) { try { if (v instanceof ViewGroup) { ViewGroup vg = (ViewGroup) v; for (int i = 0; i < vg.getChildCount(); i++) { View child = vg.getChildAt(i); overrideFonts(context, child); } } else if (v instanceof TextView) { ((TextView) v).setTypeface(typeace); } else if (v instanceof EditText ) { ((EditText) v).setTypeface(typeace); } else if (v instanceof Button) { ((Button) v).setTypeface(typeace); } } catch (Exception e) { } } }
Ahora extienda esta BaseActivity a cualquiera de sus actividades o puede crear la misma clase para el fragmento si está usando.
Nota: - Si desea configurar algunos de los tipos de letra de vista diferentes, debe configurarlos mediante programación como se muestra a continuación
private Typeface typeface; typeface = Typeface.createFromAsset(getAssets(), getResources().getString(R.string.font_name_bold)); tvUserName.setTypeface(typeface);
Así que pruébalo y avísame, si puedo ayudarte más
fuente
Un trabajo alternativo para Kotlin será este
Resumen de la solución https://gist.github.com/Johnyoat/040ca5224071d01b3f3dfc6cd4d026f7
Paso uno
Coloque el archivo de fuente en assets / fonts / your_font_file.ttf y cree una clase kotlin llamada TypeFaceUtil
class TypefaceUtil{ fun overridefonts(context: Context, defaultFontToOverride:String, customFontFileNameInAssets:String){ try { val customTypeface = Typeface.createFromAsset(context.assets,customFontFileNameInAssets) val defaultTypefaceField = Typeface::class.java.getDeclaredField(defaultFontToOverride) defaultTypefaceField.isAccessible = true defaultTypefaceField.set(null,customTypeface) }catch (e:Exception){ Timber.e("Cannot set font $customFontFileNameInAssets instead of $defaultFontToOverride") } } }
Paso dos Luego en tu
onCreate
val typefaceUtil = TypefaceUtil() typefaceUtil.overridefonts(this,"SERIF","fonts/font_file.ttf")
Paso tres
agrega esto a tu estilo
<item name="android:typeface">serif</item>
fuente
Los nombres de las fuentes deben estar en minúsculas para que se muestren en la aplicación y el trabajo.
fuente