2015-11-25 4 views
37

Возможно ли установить пользовательский шрифт в приложении для Android?Как настроить пользовательский шрифт для всего приложения на Android?

Я пытался что отправил here, но я не знаю, где мой extends Application класс ...

Любая помощь?

EDIT:

Я попытался следующие:

  • Добавить папку активов и вставить шрифт внутри, как показано здесь:

enter image description here

  • Объявление d новый класс, который простирается от Application

  • Назовите этот новый класс от моего AndroidManifest.xml.

  • Я пошел в свой стиль и добавил его.

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> 

Но мой шрифт все еще не меняется ... любая идея?

Затем вызывается класс MyApp. Но никакого влияния на мои шрифты ...

EDIT2: Я понял, что мои кнопки применяют пользовательский шрифт после того, как я установил индивидуальный стиль для своих кнопок. Вот мой пользовательский стиль кнопки:

<style name="MyButtonStyle" parent="Widget.AppCompat.Button"> 
    <item name="textAllCaps">false</item> 
    <item name="android:textAllCaps">false</item> 
</style> 

А вот как это выглядит сейчас:

enter image description here

Итак: моя кнопка применяет стиль, но не в TextView. Любая идея о том, почему мой пользовательский шрифт не применяется ко всем элементам приложения?

+0

ссылка, предоставленная вами, действительно полезна для вашей проблемы. – Androider

+0

Я знаю, я думаю, что мое решение есть ... Но когда я создаю класс, который простирается от Приложения, я не могу заставить его работать, поскольку он говорит, что мой класс никогда не используется ... – Sonhja

+0

checkout еще несколько ссылок в моем ответе , кажется полезным, еще одна вещь, моя первая ссылка действительно лучше, спасибо – Androider

ответ

37

Написать класс

public class MyApp extends Application{ 
// Put the onCreate code as you obtained from the post link you reffered 
} 

Теперь следующая вещь находится в AndroidManifest.xml для тега приложения дать имя для своего класса приложения. В этом случае MyApp

<application 
android:name=".MyApp" 
... 
> 
... 
</application> 

Так всякий раз, когда приложение открыто, OnCreate метод класса MyApp будет вызван, и шрифт будет установлен.

Update Поместите файл шрифта под активы/шрифты/your_font_file.ttf

Поместите эту линию по методу OnCreate вашего класса приложения (MyApp)

TypefaceUtil.overrideFont(getApplicationContext(), "SERIF", "fonts/your_font_file.ttf"); 

Исходный файл для 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); 
      } 
     } 
    } 
} 

Теперь обновите файл style.xml

поместить следующую строку своего стиль, который включен для вашей деятельности в файле манифеста

<item name="android:typeface">serif</item> 

Надеется, что это помогает

+0

Пожалуйста, дайте мне знать вашу версию ОС Android, на которой вы тестируете.Я наблюдал в леденец, мы должны сделать еще больше tweeks –

+0

Пожалуйста, смотрите обновление –

+1

, не работающее в поле Edittext of password. – NarendraJi

1

Похоже, вы используете android:fontFamily вместо android:typeface в своем styles.xml.

Попробуйте заменить

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> 
    <item name="android:fontFamily">default</item> 
</style> 

с

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> 
    <item name="android:typeface">default</item> 
</style> 
+1

И как мне подключить ее к моему приложению? Кто простирается от этого? – Sonhja

+0

Ну, расширив 'Приложение', вы просто создаете подкласс класса' Application' вашего приложения. Таким образом, вам не нужно его подключать. – Suhas

+0

В нем говорится, что он никогда не использовался ... – Sonhja

0

Во-первыхам, создать новый класс, который переопределяет любые View вы хотите настроить. (например, хотите кнопку с пользовательским шрифтом? Extend Button). Например:

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); 
    } 
} 

Теперь, если у вас нет, добавить документ XML под res/values/attrs.xml и добавьте:

<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> 

Хорошо, так что с этим из пути, давайте вернемся к parseAttributes() методе из ранее:

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(); 
} 

Теперь вы все готовы. Вы можете добавить больше атрибутов ни о чем (можно добавить еще один для typefaceStyle - полужирный, курсив и т.д.), но теперь давайте посмотрим, как использовать его:

<?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> 

xmlns:custom линия действительно может быть что угодно, но конвенция - это то, что показано выше. Важно то, что он уникален, и именно поэтому используется имя пакета. Теперь вы просто используете префикс custom: для своих атрибутов и префикс android: для атрибутов android.

последнее: если вы хотите использовать это в стиле (res/values/styles.xml), вы должны не добавить xmlns:custom линию.Просто указать имя атрибута, без префикса:

<style name="MyStyle> 
    <item name="typeface">roboto</item> 
</style> 
+1

Вы сделали копию решения ... – Sonhja

1

Если следовать первой теме, это должно работать: Here

Да с отражением. Это работает (based on this answer)

(Примечание: это временное решение из-за отсутствия поддержки пользовательских шрифтов, поэтому, если вы хотите изменить эту ситуацию, пожалуйста, сделайте это, чтобы проголосовать за проблему с андроидом здесь). Примечание. Не оставляйте комментарии «я тоже» по этой проблеме, каждый, кто уставился на это, получает электронное письмо, когда вы это делаете. Так что просто «звезда», пожалуйста.

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(); 
    } 
} 
} 

Затем нужно перегружать несколько шрифтов по умолчанию, например, в классе приложения:

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"); 
    } 
} 

Или, конечно, если вы используете один и тот же файл шрифта, вы можете улучшить это, чтобы загрузить его только раз.

Однако я, как правило, просто переопределить один, скажем, «MONOSPACE», а затем создать стиль, чтобы заставить этот шрифт шрифт приложения широкий:

<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

Я исследовал отчеты в комментариях, что он не работает и кажется несовместимым с темой android: Theme.Material.Light.

Если эта тема не важна для вас, используйте старую тему, например .:

<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar"> 
    <item name="android:typeface">monospace</item> 
</style> 
36

Существует большая библиотека для пользовательских шрифтов в андроиде: Каллиграфия
Вот пример, как использовать его.

В Gradle вам нужно поместить эту строку в файл build.gradle вашего приложения:

 dependencies { 
      compile 'uk.co.chrisjenx:calligraphy:2.2.0' 
     } 

А затем сделать класс, который расширяет приложение и написать этот код:

 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() 
       ); 
      } 
     } 

Вы должны иметь сделанные по активам/«Шрифты« Новый каталог »(см. ниже), поэтому в этом коде« ваш путь к шрифту »должен быть« шрифтами/SourceSansPro-Regular.ttf ». (Это просто «шрифты ...» не «/ шрифты ..» или «активы ..»)

А в классе деятельности ставят этот метод перед OnCreate:

 @Override 
     protected void attachBaseContext(Context newBase) { 
      super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase)); 
     } 

И последнее, что ваши файл манифеста должен выглядеть так:

 <application 
      . 
      . 
      . 
      android:name=".App"> 

И это изменит всю деятельность на ваш шрифт! это просто и чисто!

В разделе «Активы» вы должны щелкнуть правой кнопкой мыши «Новый каталог», назовите его «шрифты». В Finder поместите файлы шрифта .ttf.

enter image description here

Также Dont забыл добавить ниже двух линий в attrs.xml, если вы не имеете attrs.xml файл, создать новый файл в values.xml

<attr format="string" name="fontPath"/> 
    <item name="calligraphy_tag_id" type="id"/> 
+0

его работа для всех версий –

+1

это, кажется, современное решение! – Fattie

+0

Я используя ttf, но я почти уверен, что .otf также будет работать и лучше всего разместить его в папке с ресурсами. –

0

Я попытался переопределить шрифт тоже, но в конце это не надежное решение, грустно переопределяющие шрифты занимают больше, чем это. Вы можете либо дождаться выхода Android O с помощью специального шрифта, либо использовать стороннюю библиотеку.

Последнее решение, с которым я столкнулся, это эта библиотека Caligraphy, которая была легко инициирована и позволяла использовать столько шрифтов, сколько вы хотите. Во время проверки его исходный код, я понял, почему только переопределяете шрифты не будут работать, так что даже если вы не планируете использовать его, я рекомендую читать через это один раз ..

Успехов

+0

Я думаю, что вам нужно использовать каллиграфию, и об этом ... – Fattie

+0

Да, может быть. В любом случае сообщите нам, если вы нашли причину этой проблемы, действительно бы это оценили. Я не мог найти решение даже для чтения базовых кодов. –

0

Try ниже код, он работает для меня, надеюсь, это вам тоже поможет.

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) { 
} 
} 
} 

Теперь распространите эту BaseActivity на любую вашу деятельность или вы можете создать тот же класс для фрагмента, если вы используете.

Примечание: - Если вы хотите установить некоторые представления другого шрифта, то вы должны установить, что программно, как показано ниже

private Typeface typeface; 
typeface = Typeface.createFromAsset(getAssets(), getResources().getString(R.string.font_name_bold)); 
tvUserName.setTypeface(typeface); 

Так дайте ему попробовать и дайте мне знать, если я мог бы помочь вы далее

1

Все, что я сделал:

1: Добавлен «новый каталог ресурсов» в папку RES, выбранный ресурс TYPE «шрифт» из раскрывающегося списка данного, назвал новый каталог «шрифт» и сохранены. NEW RESOURCE DIRECTORY

2: Добавлен мой «custom_font.ttf» в только что созданную папку FONT.

3: Добавлен мой пользовательский шрифт в базовой темы приложения в styles.xml

STYLES.XML

DONE.

Смежные вопросы