Как изменить шрифт в TextView?

289

Как изменить шрифт в a TextView, по умолчанию он отображается как Arial? Как изменить это на Helvetica?

Praveen
источник
1
Я думаю, что это повторный вопрос. Ищите здесь ответ stackoverflow.com/questions/2878882/android-develop-lcd-font/…
the100rabh
может быть, моя ссылка будет полезна для вас stackoverflow.com/questions/2376250/…
duggu

Ответы:

342

Во-первых, по умолчанию это не Arial. По умолчанию используется Droid Sans.

Во-вторых, чтобы перейти на другой встроенный шрифт, используйте android:typefaceв макете XML или setTypeface()в Java.

В-третьих, в Android нет шрифта Helvetica. Встроенный выбор: Droid Sans ( sans), Droid Sans Mono ( monospace) и Droid Serif ( serif). Хотя вы можете связать свои собственные шрифты с вашим приложением и использовать их через setTypeface(), имейте в виду, что файлы шрифтов большие и в некоторых случаях требуют лицензионных соглашений (например, Helvetica, шрифт Linotype ).

РЕДАКТИРОВАТЬ

Язык дизайна Android опирается на традиционные типографские инструменты, такие как масштаб, пространство, ритм и выравнивание с базовой сеткой. Успешное развертывание этих инструментов важно, чтобы помочь пользователям быстро понять экран информации. Чтобы поддержать такое использование типографики, Ice Cream Sandwich представила новое семейство шрифтов под названием Roboto, созданное специально для требований пользовательского интерфейса и экранов высокого разрешения.

Текущая структура TextView предлагает Roboto с тонкими, легкими, обычными и жирными весами, а также курсивом для каждого веса. Каркас также предлагает вариант Roboto Condensed с обычным и жирным весом, а также курсивом для каждого веса.

После ICS, Android включает в себя стиль шрифтов Roboto, Подробнее Roboto

РЕДАКТИРОВАТЬ 2

С появлением библиотеки поддержки 26 Android теперь поддерживает пользовательские шрифты по умолчанию. Вы можете вставить новые шрифты в res / шрифты, которые могут быть установлены для TextViews индивидуально или в XML или программно. Шрифт по умолчанию для всего приложения также может быть изменен путем определения его styles.xml документация для разработчиков Android имеет четкое руководство по этому вопросу здесь

CommonsWare
источник
6
Нет способа установить шрифты в XML? Зачем?
Джонни
5
@ Джонни Вы действительно можете. Вы создаете класс, который расширяет TextView и вызывает setTypeface из конструктора.
Марк Филипп
как это сделать в XML Layout?
М. Усман Хан
2
@usman: Вам понадобится сторонняя библиотека, например, «Каллиграфия»: github.com/chrisjenx/Calligraphy
CommonsWare
Настроить гарнитуру с помощью кода Java сложно из-за нескольких строк, я создал библиотеку для установки пользовательских шрифтов. Вы можете найти использование библиотеки в этом ответе stackoverflow.com/a/42001474/4446392
Чатура Джаянат
254

Сначала скачайте .ttfфайл нужного вам шрифта ( arial.ttf). Поместите это в assets папку. (Внутри папки assets создайте новую папку с именем fonts и поместите в нее.) Используйте следующий код, чтобы применить шрифт к вашему TextView:

Typeface type = Typeface.createFromAsset(getAssets(),"fonts/arial.ttf"); 
textView.setTypeface(type);
ХИК
источник
Уважаемый Mayur, Любая рекомендация о том, где взять эти .ttf файлы?
одиночка
3
Уважаемый @lonelearner, вы можете скачать бесплатные файлы шрифтов (.ttf) на 1001freefonts.com или просто гуглить "Бесплатные шрифты"
ymerdrengene
10
Если вы используете Android Studio и не можете найти папку «assets», посмотрите этот вопрос . Короткий ответ: src/main/assets/fonts/.
adamdport
51
Typeface tf = Typeface.createFromAsset(getAssets(),
        "fonts/DroidSansFallback.ttf");
TextView tv = (TextView) findViewById(R.id.CustomFontText);
tv.setTypeface(tf);
Android Girl
источник
33

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

Сделать что-то вроде:

public class CustomFontsLoader {

public static final int FONT_NAME_1 =   0;
public static final int FONT_NAME_2 =   1;
public static final int FONT_NAME_3 =   2;

private static final int NUM_OF_CUSTOM_FONTS = 3;

private static boolean fontsLoaded = false;

private static Typeface[] fonts = new Typeface[3];

private static String[] fontPath = {
    "fonts/FONT_NAME_1.ttf",
    "fonts/FONT_NAME_2.ttf",
    "fonts/FONT_NAME_3.ttf"
};


/**
 * Returns a loaded custom font based on it's identifier. 
 * 
 * @param context - the current context
 * @param fontIdentifier = the identifier of the requested font
 * 
 * @return Typeface object of the requested font.
 */
public static Typeface getTypeface(Context context, int fontIdentifier) {
    if (!fontsLoaded) {
        loadFonts(context);
    }
    return fonts[fontIdentifier];
}


private static void loadFonts(Context context) {
    for (int i = 0; i < NUM_OF_CUSTOM_FONTS; i++) {
        fonts[i] = Typeface.createFromAsset(context.getAssets(), fontPath[i]);
    }
    fontsLoaded = true;

}
}

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

Даниэль Л.
источник
1
Классно, чувак! Это красота ООП. Отличная работа! :)
Джошуа Майкл Ваггонер
Как я могу использовать этот класс?
Джек
Вам нужно поместить этот код в свой проект, адаптировать его к своим шрифтам, а затем использовать статический метод getTypeface (..) из любого места в вашем приложении.
Даниэль Л.
Я использовал подобное решение, но добавил кеширование для повышения производительности .... В любом случае, вы сталкивались с ситуацией, когда шрифт работает на некоторых телефонах, а на других нет?
RJFares
20

Лучшая практика когда-либо

TextViewPlus.java:

public class TextViewPlus extends TextView {
    private static final String TAG = "TextView";

    public TextViewPlus(Context context) {
        super(context);
    }

    public TextViewPlus(Context context, AttributeSet attrs) {
        super(context, attrs);
        setCustomFont(context, attrs);
    }

    public TextViewPlus(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.TextViewPlus);
        String customFont = a.getString(R.styleable.TextViewPlus_customFont);
        setCustomFont(ctx, customFont);
        a.recycle();
    }

    public boolean setCustomFont(Context ctx, String asset) {
        Typeface typeface = null;
        try {
            typeface = Typeface.createFromAsset(ctx.getAssets(), asset);
        } catch (Exception e) {
            Log.e(TAG, "Unable to load typeface: "+e.getMessage());
            return false;
        }

        setTypeface(typeface);
        return true;
    }
}

attrs.xml: (где размещать res / values )

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="TextViewPlus">
        <attr name="customFont" format="string"/>
    </declare-styleable>
</resources>

Как пользоваться:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:foo="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <com.mypackage.TextViewPlus
        android:id="@+id/textViewPlus1"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:text="@string/showingOffTheNewTypeface"
        foo:customFont="my_font_name_regular.otf">
    </com.mypackage.TextViewPlus>
</LinearLayout>

Надеюсь, что это поможет вам.

Хирен Патель
источник
1
Почему создание подклассов TextView - лучшая практика?
Стелс Раввин
@Stealth Rabbi, здесь мы можем передавать пользовательский шрифт только в формате XML, не нужно писать специальный код Java для каждого текстового представления.
Хирен Патель
Для этого есть библиотека. Просто добавьте ваш шрифт в папку активов и объявите его в XML. github.com/febaisi/CustomTextView
febaisi
Ваша библиотека выглядит нормально, но единственная проблема в том, что она для Android 21+
loloof64
@febaisi, как я видел в вашем примере с библиотекой raw.githubusercontent.com/febaisi/CustomTextView/master/wiki/…
Mr.Q
17

Ответы выше верны. Просто убедитесь, что вы создаете подпапку с именем «шрифты» в папке «активы», если вы используете этот кусок кода.

VJ Vélan Solutions
источник
1
Ваш комментарий излишний. Приведенное выше объяснение говорит именно то, что вы сказали, и многое другое ...
Джошуа Майкл Ваггонер
14

Еще один способ объединить создание шрифтов ...

public class Font {
  public static final Font  PROXIMA_NOVA    = new Font("ProximaNovaRegular.otf");
  public static final Font  FRANKLIN_GOTHIC = new Font("FranklinGothicURWBoo.ttf");
  private final String      assetName;
  private volatile Typeface typeface;

  private Font(String assetName) {
    this.assetName = assetName;
  }

  public void apply(Context context, TextView textView) {
    if (typeface == null) {
      synchronized (this) {
        if (typeface == null) {
          typeface = Typeface.createFromAsset(context.getAssets(), assetName);
        }
      }
    }
    textView.setTypeface(typeface);
  }
}

А потом использовать в своей деятельности ...

myTextView = (TextView) findViewById(R.id.myTextView);
Font.PROXIMA_NOVA.apply(this, myTextView);

Имейте в виду, эта идиома двойной проверки с изменяемым полем корректно работает только с моделью памяти, используемой в Java 1.5+.

Крис Эйтчисон
источник
Почему в этом ответе только 1 ответ, а в ответе выше 15? Что делает другого лучше? Мне кажется, это более прямолинейный принцип синглтона ...?
Koen Demonie
Просто видел, что у вас есть ваш конструктор публично, я бы сделал его приватным, так как вам не нужен доступ к нему. В любом случае вы используете свой внутренний шрифт шрифтов ...
Koen Demonie
Абсолютно должен быть частный конструктор. Хорошо заметили :) Буду редактировать!
Крис Эйтчисон
12

Рекомендуется использовать библиотеку поддержки Android версии 26.0.0 или выше.

ШАГ 1: добавить файл шрифта

  1. В папке res создайте новый словарь ресурсов шрифта
  2. Добавить файл шрифта ( .ttf , .orf )

Например, когда файл шрифта будет helvetica_neue.ttf, который будет генерировать R.font.helvetica_neue

ШАГ 2: создать семейство шрифтов

  1. В папке шрифтов добавьте новый файл ресурсов
  2. Вложите каждый элемент шрифта, стиль и вес в элемент.

Например:

<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android">
    <font
        android:fontStyle="normal"
        android:fontWeight="400"
        android:font="@font/helvetica_neue" />
</font-family>

ШАГ 3: используйте его

В макетах XML:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:fontFamily="@font/my_font"/>

Или добавьте шрифты в стиль:

<style name="customfontstyle" parent="@android:style/TextAppearance.Small">
    <item name="android:fontFamily">@font/lobster</item>
</style>

Для большего количества примеров вы можете следовать документации:

Работа со шрифтами

Марек Жижничек
источник
7

Это немного старый, но я немного улучшил класс CustomFontLoader, и я хотел поделиться им, чтобы он мог быть полезным. Просто создайте новый класс с этим кодом.

 import android.content.Context;
 import android.graphics.Typeface;

public enum FontLoader {

ARIAL("arial"),
TIMES("times"),
VERDANA("verdana"),
TREBUCHET("trbuchet"),
GEORGIA("georgia"),
GENEVA("geneva"),
SANS("sans"),
COURIER("courier"),
TAHOMA("tahoma"),
LUCIDA("lucida");   


private final String name;
private Typeface typeFace;


private FontLoader(final String name) {
    this.name = name;

    typeFace=null;  
}

public static Typeface getTypeFace(Context context,String name){
    try {
        FontLoader item=FontLoader.valueOf(name.toUpperCase(Locale.getDefault()));
        if(item.typeFace==null){                
            item.typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+item.name+".ttf");                 
        }           
        return item.typeFace;
    } catch (Exception e) {         
        return null;
    }                   
}
public static Typeface getTypeFace(Context context,int id){
    FontLoader myArray[]= FontLoader.values();
    if(!(id<myArray.length)){           
        return null;
    } 
    try {
        if(myArray[id].typeFace==null){     
            myArray[id].typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+myArray[id].name+".ttf");                       
        }       
        return myArray[id].typeFace;    
    }catch (Exception e) {          
        return null;
    }   

}

public static Typeface getTypeFaceByName(Context context,String name){      
    for(FontLoader item: FontLoader.values()){              
        if(name.equalsIgnoreCase(item.name)){
            if(item.typeFace==null){
                try{
                    item.typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+item.name+".ttf");     
                }catch (Exception e) {          
                    return null;
                }   
            }
            return item.typeFace;
        }               
    }
    return null;
}   

public static void loadAllFonts(Context context){       
    for(FontLoader item: FontLoader.values()){              
        if(item.typeFace==null){
            try{
                item.typeFace=Typeface.createFromAsset(context.getAssets(), "fonts/"+item.name+".ttf");     
            }catch (Exception e) {
                item.typeFace=null;
            }   
        }                
    }       
}   
}

Тогда просто используйте этот код на вашем textview:

 Typeface typeFace=FontLoader.getTypeFace(context,"arial");  
 if(typeFace!=null) myTextView.setTypeface(typeFace);
Алан
источник
5

Я наконец получил очень простое решение для этого.

  1. использовать эти библиотеки поддержки на уровне приложения ,

    compile 'com.android.support:appcompat-v7:26.0.2'
    compile 'com.android.support:support-v4:26.0.2'
  2. затем создайте каталог с именем "font" внутри папки res

  3. поместите файлы шрифтов (ttf) в этот каталог шрифтов, помните о соглашениях по именованию [egname не должен содержать никаких специальных символов, символов верхнего регистра и пробела или табуляции]
  4. После этого ссылаться на этот шрифт из XML, как это

            <Button
            android:id="@+id/btn_choose_employee"
            android:layout_width="140dp"
            android:layout_height="40dp"
            android:layout_centerInParent="true"
            android:background="@drawable/rounded_red_btn"
            android:onClick="btnEmployeeClickedAction"
            android:text="@string/searching_jobs"
            android:textAllCaps="false"
            android:textColor="@color/white"
            android:fontFamily="@font/times_new_roman_test"
            />

В этом примере times_new_roman_test является файлом ttf шрифта из этого каталога шрифтов.

Шамсул Арефин Саджиб
источник
4
import java.lang.ref.WeakReference;
import java.util.HashMap;

import android.content.Context;
import android.graphics.Typeface;

public class FontsManager {

    private static FontsManager instance;

    private static HashMap<String, WeakReference<Typeface>> typefaces = new HashMap<String, WeakReference<Typeface>>();

    private static Context context;

    private FontsManager(final Context ctx) {
        if (context == null) {
            context = ctx;
        }
    }

    public static FontsManager getInstance(final Context appContext) {
        if (instance == null) {
            instance = new FontsManager(appContext);
        }
        return instance;
    }

    public static FontsManager getInstance() {
        if (instance == null) {
            throw new RuntimeException(
                    "Call getInstance(Context context) at least once to init the singleton properly");
        }
        return instance;
    }

    public Typeface getFont(final String assetName) {
        final WeakReference<Typeface> tfReference = typefaces.get(assetName);
        if (tfReference == null || tfReference.get() == null) {
            final Typeface tf = Typeface.createFromAsset(context.getResources().getAssets(),
                    assetName);
            typefaces.put(assetName, new WeakReference<Typeface>(tf));
            return tf;
        }
        return tfReference.get();
    }

}

Таким образом, вы можете создать View, который наследуется от TextView и вызывает setTypeface для своего конструктора.

Charlie-Blake
источник
1
Здравствуйте, почему вы используете WeakReference для хранения объекта TypeFace?
Ленивый
3

Когда ваш шрифт хранится внутри, res/asset/fonts/Helvetica.ttfиспользуйте следующее:

Typeface tf = Typeface.createFromAsset(getAssets(),"fonts/Helvetica.ttf"); 
txt.setTypeface(tf);

Или, если ваш файл шрифтов хранится внутри, res/font/helvetica.ttfиспользуйте следующее:

Typeface tf = ResourcesCompat.getFont(this,R.font.helvetica);
txt.setTypeface(tf);
Панкадж Лилан
источник
2
Спасибо, искали ту часть, где она была у вас в папке res!
Миккель Ларсен
2

получить шрифт из ресурса и установить для всех детей

public static 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(Typeface.createFromAsset(context.getAssets(),"DroidNaskh.ttf"));// "BKOODB.TTF"));
        }
    } catch (Exception e) {
 }
 } 
Маниан Резаи
источник
2
  1. добавить класс FontTextView.java:


public class FontTextView extends TextView {
    String fonts[] = {"HelveticaNeue.ttf", "HelveticaNeueLight.ttf", "motschcc.ttf", "symbol.ttf"};

    public FontTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(attrs);
    }

    public FontTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        if (!isInEditMode()) {
            init(attrs);
        }

    }

    public FontTextView(Context context) {
        super(context);
        if (!isInEditMode()) {
            init(null);
        }
    }

    private void init(AttributeSet attrs) {
        if (attrs != null) {
            TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.FontTextView);
            if (a.getString(R.styleable.FontTextView_font_type) != null) {
                String fontName = fonts[Integer.valueOf(a.getString(R.styleable.FontTextView_font_type))];

                if (fontName != null) {
                    Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/" + fontName);
                    setTypeface(myTypeface);
                }
                a.recycle();
            }
        }
    }
}


  1. добавить в библиотеку шрифт ресурсов
    введите описание изображения здесь


  1. добавить в attrs.xml, числа должны быть в порядке в классе массива.

    <declare-styleable name="FontTextView">
    <attr name="font_type" format="enum">
        <enum name="HelveticaNeue" value="0"/>
        <enum name="HelveticaNeueLight" value="1"/>
        <enum name="motschcc" value="2"/>
        <enum name="symbol" value="3"/>
    </attr>


  1. Выберите шрифт из списка
    введите описание изображения здесь
Дэвид
источник
Вам нужно создать экземпляр этого класса в MainActivity? Потому что это ничего не меняет для меня.
Тобиас Майр
1

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

Проверьте ссылку ниже, чтобы проверить шрифты робота:

Как использовать Roboto в XML-макете

Возвращаясь к вашему вопросу, если вы хотите изменить шрифт для всех TextView / Button в вашем приложении , попробуйте добавить следующий код в файл styles.xml, чтобы использовать шрифт Roboto-light :

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    ......
    <item name="android:buttonStyle">@style/MyButton</item>
    <item name="android:textViewStyle">@style/MyTextView</item>
</style>

<style name="MyButton" parent="@style/Widget.AppCompat.Button">
    <item name="android:textAllCaps">false</item>
    <item name="android:fontFamily">sans-serif-light</item>
</style>

<style name="MyTextView" parent="@style/TextAppearance.AppCompat">
    <item name="android:fontFamily">sans-serif-light</item>
</style>

И не забудьте использовать «AppTheme» в вашем AndroidManifest.xml

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    ......
</application>
лавочник
источник
0

Может быть, что-то немного проще:

public class Fonts {
  public static HashSet<String,Typeface> fonts = new HashSet<>();

  public static Typeface get(Context context, String file) {
    if (! fonts.contains(file)) {
      synchronized (this) {
        Typeface typeface = Typeface.createFromAsset(context.getAssets(), name);
        fonts.put(name, typeface);
      }
    }
    return fonts.get(file);
  }
}

// Usage
Typeface myFont = Fonts.get("arial.ttf");

(Обратите внимание, что этот код не проверен, но в целом этот подход должен работать хорошо.)

транс
источник