Как изменить шрифт семьи TextView в Android
Итак, я хотел бы изменить android:fontFamily на Android, но я не вижу никаких предустановленных шрифтов в Android. Как выбрать один из предопределенных? Мне не нужно определять собственный TypeFace, но все, что мне нужно, это нечто отличное от того, что оно показывает прямо сейчас.
Кажется, что я сделал, там не будет работать! BTW android:fontFamily=»Arial» была глупой попыткой!
Tarik 26 авг. 2012, в 07:13
Поделиться
проверить эту ссылку stackoverflow.com/questions/2376250/…
duggu 06 фев. 2018, в 11:47
Поделиться:
android-textview
android-layout
27 ответов
Лучший ответ
От android 4.1/4.2/5.0 доступны следующие семейства Roboto:
android:fontFamily="sans-serif" // roboto regular android:fontFamily="sans-serif-light" // roboto light android:fontFamily="sans-serif-condensed" // roboto condensed android:fontFamily="sans-serif-black" // roboto black android:fontFamily="sans-serif-thin" // roboto thin (android 4.2) android:fontFamily="sans-serif-medium" // roboto medium (android 5.0)
android:textStyle="normal|bold|italic"
возможны 16 вариантов:
- Roboto Regular
- Roboto italic
- Roboto bold
- Робото выделено курсивом
- Roboto-Light
- Робото-свет курсивом
- Roboto-Thin
- Roboto-Thin italic
- Roboto-Condensed
- Roboto-Condensed italic
- Roboto-Condensed bold
- Roboto-Condensed жирным курсивом
- Roboto-Black
- Робото-черный курсив
- Roboto-Medium
- Roboto-medium italic
sans-serif-light sans-serif-medium sans-serif sans-serif-condensed sans-serif-black sans-serif-thin
Jakob Eriksson 11 нояб. 2012, в 09:51
Поделиться
Не забудьте об этом: android: fontFamily = «sans-serif-thin» // роботизированный файл
Sam Lu 12 фев. 2013, в 09:15
Сэм Лу прав, «без засечек» был добавлен в Android 4.2
Alexander Mironov 20 март 2013, в 08:14
Я видел вариант под названием «черные маленькие шапочки» в книге образцов робото , но мне не удается его использовать. Использование android:fontFamily=»sans-serif-black-small-caps» не работает. Кто-нибудь знает?
tbruyelle 29 май 2013, в 13:44
Я не могу найти ни одного из этих семейств шрифтов, которые вы здесь напечатали. Я не могу найти «без засечек» вместе.
Unknown 16 авг. 2013, в 04:10
Это хороший список. У кого-нибудь есть ссылка на источник этой информации? Было бы хорошо, если бы Google имел это в своей документации в легко android:fontFamily месте, скажем, для документации android:fontFamily в TextView.
Christopher Perry 30 окт. 2013, в 17:53
Любая подсказка, каков источник информации этого ответа? Я хотел бы читать дальше об этом
Christian García 03 дек. 2013, в 10:55
Это было бы отличной информацией, о, я не знаю, как насчет Javadocs API TextView . Просто говорю’. Видимо это единственная официальная ссылка .
Adam Mackler 21 фев. 2014, в 23:54
Точно ли сказать, что fontFamily typeface ? Разве мы больше не можем использовать засечек или моноширин? Я не думаю, что typeface формально устарела, просто игнорируется, когда также присутствует fontFamily .
Rad Haring 06 март 2014, в 15:03
Я обновил этот ответ, android:fontFamily детали, откуда исходит источник этой информации и как получить окончательный список значений android:fontFamily , даже вендора, с ваших устройств. Это просто ожидание на экспертной оценке.
Simon 09 апр. 2014, в 10:12
Полный список шрифтов можно найти в файле system_fonts.xml, как описано здесь.
Newtonx 06 июнь 2014, в 01:17
Просто быстрый вопрос, если я использую android: fontFamily в версиях, предшествующих (<4.1) Jelly Bean, произойдет ли сбой моего приложения или его просто проигнорируют?
Sandra 03 сен. 2014, в 14:55
@ Сандра будет игнорироваться, так что это безопасно для использования
Jakob Eriksson 04 сен. 2014, в 12:42
Где я могу найти в документации о доступных семействах шрифтов?
android developer 05 нояб. 2014, в 15:16
«Sans-Serif» (обычный робот) по умолчанию, верно?
android developer 22 янв. 2015, в 08:45
Как я могу использовать роботизированный конденсированный свет? Спасибо
Ricardo 08 фев. 2015, в 21:48
@Ricardo Лучший способ — взглянуть на источник: android.googlesource.com/platform/frameworks/base/+/… and android.googlesource.com/platform/frameworks/base/+/master/data/… , что означает, что вы хочу использовать «без засечек-конденсированный свет»
android developer 23 апр. 2015, в 21:41
Что если вы используете sans-serif-thin на Android 4.1? По умолчанию это будет sans-serif-light, sans-serif или DroidSans?
Jelle Fresen 28 июль 2015, в 14:05
с 5.0 можно выложить пример отдельным ответом
gor 24 нояб. 2015, в 21:34
Для использования Roboto API уровня 16 требуется иначе, вы получите ошибку.
Din Islam Milon 26 март 2016, в 14:33
Итак, я думаю, что единственный шрифт, который я не могу получить (без использования библиотеки RobotoTextView), — это сжатый свет? право?
Demigod 03 авг. 2016, в 16:05
Как насчет семьи Ното? Я не могу найти способ заставить мое приложение использовать Noto в качестве семейства шрифтов по умолчанию
KasparTr 08 авг. 2016, в 19:03
Список также доступен здесь: androidxref.com/6.0.1_r10/xref/frameworks/base/data/fonts/…
scorpiodawg 19 янв. 2017, в 19:17
Вы можете проверить этот проект, чтобы проверить совместимость шрифтов в TextViews и в WebViews на разных версиях платформы github.com/JeppeLeth/android_font_compat_tester
Jeppe Leth 12 апр. 2017, в 06:54
sans-serif-medium не доступен в моем случае
Akshatha Srinivas 23 авг. 2017, в 11:08
Настройки устройства мешают этому работать
ericn 28 июль 2018, в 13:49
Пожалуйста, измените свой ответ — добавьте android: fontFamily = «sans-serif-bold», что соответствует Roboto-bold. Спасибо
Anton Kizema 24 окт. 2018, в 16:20
Ну, это не работает для CJK 🙁 Есть другие идеи?
Tsung Goh 06 нояб. 2018, в 19:32
Показать ещё 25 комментариев
Это способ программно установить шрифт:
TextView tv = (TextView) findViewById(R.id.appname); Typeface face = Typeface.createFromAsset(getAssets(), "fonts/epimodem.ttf"); tv.setTypeface(face);
поместите файл шрифта в папку с вашими ресурсами. В моем случае я создал подкаталог под названием fonts.
РЕДАКТИРОВАТЬ: Если вы задаетесь вопросом, где находится папка ваших активов, см. этот вопрос
Stefan Beike 26 авг. 2012, в 09:19
Поделиться
Хотя это работает, обратите внимание, что это может привести к утечке памяти . Это можно исправить с помощью этого ответа .
Charles Madere 06 март 2014, в 18:54
@ScootrNova я получаю эту ошибку, когда я использую ваше решение. Ошибка: ресурс шрифта не найден gothic.ttf
Sagar Devanga 30 дек. 2014, в 08:24
@ScootrNova gothic.ttf или gothic.TTF . Позаботься о чувствительности к делу .
Stefan Beike 30 дек. 2014, в 10:54
Как применить это ко всему приложению? Прямо сейчас в примере вы применяете его только на на просмотр текста
Pritish Joshi 06 фев. 2016, в 09:54
Показать ещё 2 комментария
Мне пришлось анализировать /system/etc/fonts.xml в недавнем проекте. Вот текущие семейства шрифтов как Lollipop:
╔════╦════════════════════════════╦═════════════════════════════╗ ║ ║ FONT FAMILY ║ TTF FILE ║ ╠════╬════════════════════════════╬═════════════════════════════╣ ║ 1 ║ casual ║ ComingSoon.ttf ║ ║ 2 ║ cursive ║ DancingScript-Regular.ttf ║ ║ 3 ║ monospace ║ DroidSansMono.ttf ║ ║ 4 ║ sans-serif ║ Roboto-Regular.ttf ║ ║ 5 ║ sans-serif-black ║ Roboto-Black.ttf ║ ║ 6 ║ sans-serif-condensed ║ RobotoCondensed-Regular.ttf ║ ║ 7 ║ sans-serif-condensed-light ║ RobotoCondensed-Light.ttf ║ ║ 8 ║ sans-serif-light ║ Roboto-Light.ttf ║ ║ 9 ║ sans-serif-medium ║ Roboto-Medium.ttf ║ ║ 10 ║ sans-serif-smallcaps ║ CarroisGothicSC-Regular.ttf ║ ║ 11 ║ sans-serif-thin ║ Roboto-Thin.ttf ║ ║ 12 ║ serif ║ NotoSerif-Regular.ttf ║ ║ 13 ║ serif-monospace ║ CutiveMono.ttf ║ ╚════╩════════════════════════════╩═════════════════════════════╝
Вот синтаксический анализатор (на основе FontListParser):
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import android.util.Xml; /** * Helper class to get the current font families on an Android device. * * Usage: fonts = FontListParser.safelyGetSystemFonts();> */ public final class FontListParser < private static final File FONTS_XML = new File("/system/etc/fonts.xml"); private static final File SYSTEM_FONTS_XML = new File("/system/etc/system_fonts.xml"); public static ListgetSystemFonts() throws Exception < String fontsXml; if (FONTS_XML.exists()) < fontsXml = FONTS_XML.getAbsolutePath(); >else if (SYSTEM_FONTS_XML.exists()) < fontsXml = SYSTEM_FONTS_XML.getAbsolutePath(); >else < throw new RuntimeException("fonts.xml does not exist on this system"); >Config parser = parse(new FileInputStream(fontsXml)); List fonts = new ArrayList<>(); for (Family family : parser.families) < if (family.name != null) < Font font = null; for (Font f : family.fonts) < font = f; if (f.weight == 400) < break; >> SystemFont systemFont = new SystemFont(family.name, font.fontName); if (fonts.contains(systemFont)) < continue; >fonts.add(new SystemFont(family.name, font.fontName)); > > for (Alias alias : parser.aliases) < if (alias.name == null || alias.toName == null || alias.weight == 0) < continue; >for (Family family : parser.families) < if (family.name == null || !family.name.equals(alias.toName)) < continue; >for (Font font : family.fonts) < if (font.weight == alias.weight) < fonts.add(new SystemFont(alias.name, font.fontName)); break; >> > > if (fonts.isEmpty()) < throw new Exception("No system fonts found."); >Collections.sort(fonts, new Comparator() < @Override public int compare(SystemFont font1, SystemFont font2) < return font1.name.compareToIgnoreCase(font2.name); >>); return fonts; > public static List safelyGetSystemFonts() < try < return getSystemFonts(); >catch (Exception e) < String[][] defaultSystemFonts = < < "cursive", "DancingScript-Regular.ttf" >, < "monospace", "DroidSansMono.ttf" >, < "sans-serif", "Roboto-Regular.ttf" >, < "sans-serif-light", "Roboto-Light.ttf" >, < "sans-serif-medium", "Roboto-Medium.ttf" >, < "sans-serif-black", "Roboto-Black.ttf" >, < "sans-serif-condensed", "RobotoCondensed-Regular.ttf" >, < "sans-serif-thin", "Roboto-Thin.ttf" >, < "serif", "NotoSerif-Regular.ttf" >>; List fonts = new ArrayList<>(); for (String[] names : defaultSystemFonts) < File file = new File("/system/fonts", names[1]); if (file.exists()) < fonts.add(new SystemFont(names[0], file.getAbsolutePath())); >> return fonts; > > /* Parse fallback list (no names) */ public static Config parse(InputStream in) throws XmlPullParserException, IOException < try < XmlPullParser parser = Xml.newPullParser(); parser.setInput(in, null); parser.nextTag(); return readFamilies(parser); >finally < in.close(); >> private static Alias readAlias(XmlPullParser parser) throws XmlPullParserException, IOException < Alias alias = new Alias(); alias.name = parser.getAttributeValue(null, "name"); alias.toName = parser.getAttributeValue(null, "to"); String weightStr = parser.getAttributeValue(null, "weight"); if (weightStr == null) < alias.weight = 0; >else < alias.weight = Integer.parseInt(weightStr); >skip(parser); // alias tag is empty, ignore any contents and consume end tag return alias; > private static Config readFamilies(XmlPullParser parser) throws XmlPullParserException, IOException < Config config = new Config(); parser.require(XmlPullParser.START_TAG, null, "familyset"); while (parser.next() != XmlPullParser.END_TAG) < if (parser.getEventType() != XmlPullParser.START_TAG) < continue; >if (parser.getName().equals("family")) < config.families.add(readFamily(parser)); >else if (parser.getName().equals("alias")) < config.aliases.add(readAlias(parser)); >else < skip(parser); >> return config; > private static Family readFamily(XmlPullParser parser) throws XmlPullParserException, IOException < String name = parser.getAttributeValue(null, "name"); String lang = parser.getAttributeValue(null, "lang"); String variant = parser.getAttributeValue(null, "variant"); Listfonts = new ArrayList(); while (parser.next() != XmlPullParser.END_TAG) < if (parser.getEventType() != XmlPullParser.START_TAG) < continue; >String tag = parser.getName(); if (tag.equals("font")) < String weightStr = parser.getAttributeValue(null, "weight"); int weight = weightStr == null ? 400 : Integer.parseInt(weightStr); boolean isItalic = "italic".equals(parser.getAttributeValue(null, "style")); String filename = parser.nextText(); String fullFilename = "/system/fonts/" + filename; fonts.add(new Font(fullFilename, weight, isItalic)); >else < skip(parser); >> return new Family(name, fonts, lang, variant); > private static void skip(XmlPullParser parser) throws XmlPullParserException, IOException < int depth = 1; while (depth >0) < switch (parser.next()) < case XmlPullParser.START_TAG: depth++; break; case XmlPullParser.END_TAG: depth--; break; >> > private FontListParser() < >public static class Alias < public String name; public String toName; public int weight; >public static class Config < public Listaliases; public List families; Config() < families = new ArrayList(); aliases = new ArrayList(); > > public static class Family < public Listfonts; public String lang; public String name; public String variant; public Family(String name, List fonts, String lang, String variant) < this.name = name; this.fonts = fonts; this.lang = lang; this.variant = variant; >> public static class Font < public String fontName; public boolean isItalic; public int weight; Font(String fontName, int weight, boolean isItalic) < this.fontName = fontName; this.weight = weight; this.isItalic = isItalic; >> public static class SystemFont < public String name; public String path; public SystemFont(String name, String path) < this.name = name; this.path = path; >> >
Не стесняйтесь использовать вышеуказанный класс в своем проекте. Например, вы можете дать своим пользователям выбор семейств шрифтов и установить шрифт на основе их предпочтений.
Небольшой неполный пример:
final List fonts = FontListParser.safelyGetSystemFonts(); String[] items = new String[fonts.size()]; for (int i = 0; i < fonts.size(); i++) < items[i] = fonts.get(i).name; >new AlertDialog.Builder(this).setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() < @Override public void onClick(DialogInterface dialog, int which) < FontListParser.SystemFont selectedFont = fonts.get(which); // TODO: do something with the font Toast.makeText(getApplicationContext(), selectedFont.path, Toast.LENGTH_LONG).show(); >>).show();
How to change fontFamily of TextView in Android
So I’d like to change the android:fontFamily in Android but I don’t see any pre-defined fonts in Android. How do I select one of the pre-defined ones? I don’t really need to define my own TypeFace but all I need is something different from what it shows right now.
It seems what I did up there won’t really work! BTW android:fontFamily=»Arial» was a stupid attempt!
7,019 4 4 gold badges 25 25 silver badges 38 38 bronze badges
asked Aug 26, 2012 at 7:19
80k 83 83 gold badges 236 236 silver badges 349 349 bronze badges
check out this link stackoverflow.com/questions/2376250/…
Feb 6, 2018 at 11:47
39 Answers 39
From android 4.1 / 4.2 / 5.0, the following Roboto font families are available:
android:fontFamily="sans-serif" // roboto regular android:fontFamily="sans-serif-light" // roboto light android:fontFamily="sans-serif-condensed" // roboto condensed android:fontFamily="sans-serif-black" // roboto black android:fontFamily="sans-serif-thin" // roboto thin (android 4.2) android:fontFamily="sans-serif-medium" // roboto medium (android 5.0)

in combination with
android:textStyle="normal|bold|italic"
this 16 variants are possible:
- Roboto regular
- Roboto italic
- Roboto bold
- Roboto bold italic
- Roboto-Light
- Roboto-Light italic
- Roboto-Thin
- Roboto-Thin italic
- Roboto-Condensed
- Roboto-Condensed italic
- Roboto-Condensed bold
- Roboto-Condensed bold italic
- Roboto-Black
- Roboto-Black italic
- Roboto-Medium
- Roboto-Medium italic
sans-serif-light sans-serif-medium sans-serif sans-serif-condensed sans-serif-black sans-serif-thin
870 10 10 silver badges 11 11 bronze badges
answered Nov 11, 2012 at 9:22
Jakob Eriksson Jakob Eriksson
18.6k 1 1 gold badge 26 26 silver badges 34 34 bronze badges
Don’t forget this: android:fontFamily=»sans-serif-thin» // roboto thin
Feb 12, 2013 at 9:15
I saw a variant called «black small caps» in the roboto specimen book, but I don’t manage to use it. Using android:fontFamily=»sans-serif-black-small-caps» doesnt work. Does someone know?
May 29, 2013 at 13:44
i am not able to find any of these font-family what have you typed here .i am not able to find «sans-serif» together.
Aug 16, 2013 at 4:10
This is a nice list. Does anyone have a link to where this information comes from? It would be nice if Google had this in their documentation in an easy to find place, say for the documentation of android:fontFamily on TextView.
Oct 30, 2013 at 17:53
The definitive list of fonts can be found in system_fonts.xml as explained here
Jun 6, 2014 at 1:17
Starting from Android-Studio 3.0 its very easy to change font family
Using support library 26, it will work on devices running Android API version 16 and higher
Create a folder font under res directory .Download the font which ever you want and paste it inside font folder. The structure should be some thing like below

Note: As of Android Support Library 26.0, you must declare both sets of attributes ( android: and app: ) to ensure your fonts load on devices running Api 26 or lower.
Now you can change font in layout using
To change Programatically
Typeface typeface = getResources().getFont(R.font.myfont); //or to support all versions use Typeface typeface = ResourcesCompat.getFont(context, R.font.myfont); textView.setTypeface(typeface);
To change font using styles.xml create a style
and apply this style to TextView
you can also Create your own font family
— Right-click the font folder and go to New > Font resource file. The New Resource File window appears.
— Enter the file name, and then click OK. The new font resource XML opens in the editor.
Write your own font family here , for example
this is simply a mapping of a specific fontStyle and fontWeight to the font resource which will be used to render that specific variant. Valid values for fontStyle are normal or italic; and fontWeight conforms to the CSS font-weight specification
1. To change fontfamily in layout you can write
2. To Change Programmatically
Typeface typeface = getResources().getFont(R.font.lobster); //or to support all versions use Typeface typeface = ResourcesCompat.getFont(context, R.font.lobster); textView.setTypeface(typeface);
To change font of entire App Add these two lines in AppTheme
answered Mar 23, 2017 at 12:51
22.4k 9 9 gold badges 110 110 silver badges 146 146 bronze badges
NB: This currently only works in Android Studio 3.0 Preview. It did not work for me on Android Studio 2.3.3. Hope that saves someone some time!
Jun 26, 2017 at 14:51
How could you get the font from within a fragment since you can’t just do getResources() ? EDIT: This line at the end of your answer worked for me: Typeface typeface = ResourcesCompat.getFont(context, R.font.myfont);
Feb 11, 2018 at 22:29
Somehow it made font look corrupted in my case, comparing to Caligtraphy. Also fontWeight doesn’t do anything
May 3, 2018 at 11:16
@LeoDroidcoder it does work , make sure you used both android:fontWeight and app:fontWeight
May 3, 2018 at 12:30
Right-click main, select ‘New’, select ‘Android Resource File’. In popup window type ‘font’ for name, select ‘Font’ from drop-down ‘Resource Type’ list. Click ‘OK’.
May 17, 2021 at 15:12
This is the way to set the font programmatically:
TextView tv = (TextView) findViewById(R.id.appname); Typeface face = Typeface.createFromAsset(getAssets(), "fonts/epimodem.ttf"); tv.setTypeface(face);
put the font file in your assets folder. In my case I created a subdirectory called fonts.
EDIT: If you wonder where is your assets folder see this question
1 1 1 silver badge
answered Aug 26, 2012 at 7:38
12.4k 8 8 gold badges 55 55 silver badges 83 83 bronze badges
While this does work, please note that this can create a memory leak. It can be fixed using this answer.
Mar 6, 2014 at 18:54
@ScootrNova i get this error when i use your solution. Error : Font asset not found gothic.ttf
Dec 30, 2014 at 8:24
How to apply this to whole app? Right now in example you are applying it only on on textview
Feb 6, 2016 at 9:54
I had to parse /system/etc/fonts.xml in a recent project. Here are the current font families as of Lollipop:
╔════╦════════════════════════════╦═════════════════════════════╗ ║ ║ FONT FAMILY ║ TTF FILE ║ ╠════╬════════════════════════════╬═════════════════════════════╣ ║ 1 ║ casual ║ ComingSoon.ttf ║ ║ 2 ║ cursive ║ DancingScript-Regular.ttf ║ ║ 3 ║ monospace ║ DroidSansMono.ttf ║ ║ 4 ║ sans-serif ║ Roboto-Regular.ttf ║ ║ 5 ║ sans-serif-black ║ Roboto-Black.ttf ║ ║ 6 ║ sans-serif-condensed ║ RobotoCondensed-Regular.ttf ║ ║ 7 ║ sans-serif-condensed-light ║ RobotoCondensed-Light.ttf ║ ║ 8 ║ sans-serif-light ║ Roboto-Light.ttf ║ ║ 9 ║ sans-serif-medium ║ Roboto-Medium.ttf ║ ║ 10 ║ sans-serif-smallcaps ║ CarroisGothicSC-Regular.ttf ║ ║ 11 ║ sans-serif-thin ║ Roboto-Thin.ttf ║ ║ 12 ║ serif ║ NotoSerif-Regular.ttf ║ ║ 13 ║ serif-monospace ║ CutiveMono.ttf ║ ╚════╩════════════════════════════╩═════════════════════════════╝
Here is the parser (based off FontListParser):
import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import android.util.Xml; /** * Helper class to get the current font families on an Android device. * * Usage: fonts = FontListParser.safelyGetSystemFonts();> */ public final class FontListParser < private static final File FONTS_XML = new File("/system/etc/fonts.xml"); private static final File SYSTEM_FONTS_XML = new File("/system/etc/system_fonts.xml"); public static ListgetSystemFonts() throws Exception < String fontsXml; if (FONTS_XML.exists()) < fontsXml = FONTS_XML.getAbsolutePath(); >else if (SYSTEM_FONTS_XML.exists()) < fontsXml = SYSTEM_FONTS_XML.getAbsolutePath(); >else < throw new RuntimeException("fonts.xml does not exist on this system"); >Config parser = parse(new FileInputStream(fontsXml)); List fonts = new ArrayList<>(); for (Family family : parser.families) < if (family.name != null) < Font font = null; for (Font f : family.fonts) < font = f; if (f.weight == 400) < break; >> SystemFont systemFont = new SystemFont(family.name, font.fontName); if (fonts.contains(systemFont)) < continue; >fonts.add(new SystemFont(family.name, font.fontName)); > > for (Alias alias : parser.aliases) < if (alias.name == null || alias.toName == null || alias.weight == 0) < continue; >for (Family family : parser.families) < if (family.name == null || !family.name.equals(alias.toName)) < continue; >for (Font font : family.fonts) < if (font.weight == alias.weight) < fonts.add(new SystemFont(alias.name, font.fontName)); break; >> > > if (fonts.isEmpty()) < throw new Exception("No system fonts found."); >Collections.sort(fonts, new Comparator() < @Override public int compare(SystemFont font1, SystemFont font2) < return font1.name.compareToIgnoreCase(font2.name); >>); return fonts; > public static List safelyGetSystemFonts() < try < return getSystemFonts(); >catch (Exception e) < String[][] defaultSystemFonts = < < "cursive", "DancingScript-Regular.ttf" >, < "monospace", "DroidSansMono.ttf" >, < "sans-serif", "Roboto-Regular.ttf" >, < "sans-serif-light", "Roboto-Light.ttf" >, < "sans-serif-medium", "Roboto-Medium.ttf" >, < "sans-serif-black", "Roboto-Black.ttf" >, < "sans-serif-condensed", "RobotoCondensed-Regular.ttf" >, < "sans-serif-thin", "Roboto-Thin.ttf" >, < "serif", "NotoSerif-Regular.ttf" >>; List fonts = new ArrayList<>(); for (String[] names : defaultSystemFonts) < File file = new File("/system/fonts", names[1]); if (file.exists()) < fonts.add(new SystemFont(names[0], file.getAbsolutePath())); >> return fonts; > > /* Parse fallback list (no names) */ public static Config parse(InputStream in) throws XmlPullParserException, IOException < try < XmlPullParser parser = Xml.newPullParser(); parser.setInput(in, null); parser.nextTag(); return readFamilies(parser); >finally < in.close(); >> private static Alias readAlias(XmlPullParser parser) throws XmlPullParserException, IOException < Alias alias = new Alias(); alias.name = parser.getAttributeValue(null, "name"); alias.toName = parser.getAttributeValue(null, "to"); String weightStr = parser.getAttributeValue(null, "weight"); if (weightStr == null) < alias.weight = 0; >else < alias.weight = Integer.parseInt(weightStr); >skip(parser); // alias tag is empty, ignore any contents and consume end tag return alias; > private static Config readFamilies(XmlPullParser parser) throws XmlPullParserException, IOException < Config config = new Config(); parser.require(XmlPullParser.START_TAG, null, "familyset"); while (parser.next() != XmlPullParser.END_TAG) < if (parser.getEventType() != XmlPullParser.START_TAG) < continue; >if (parser.getName().equals("family")) < config.families.add(readFamily(parser)); >else if (parser.getName().equals("alias")) < config.aliases.add(readAlias(parser)); >else < skip(parser); >> return config; > private static Family readFamily(XmlPullParser parser) throws XmlPullParserException, IOException < String name = parser.getAttributeValue(null, "name"); String lang = parser.getAttributeValue(null, "lang"); String variant = parser.getAttributeValue(null, "variant"); Listfonts = new ArrayList(); while (parser.next() != XmlPullParser.END_TAG) < if (parser.getEventType() != XmlPullParser.START_TAG) < continue; >String tag = parser.getName(); if (tag.equals("font")) < String weightStr = parser.getAttributeValue(null, "weight"); int weight = weightStr == null ? 400 : Integer.parseInt(weightStr); boolean isItalic = "italic".equals(parser.getAttributeValue(null, "style")); String filename = parser.nextText(); String fullFilename = "/system/fonts/" + filename; fonts.add(new Font(fullFilename, weight, isItalic)); >else < skip(parser); >> return new Family(name, fonts, lang, variant); > private static void skip(XmlPullParser parser) throws XmlPullParserException, IOException < int depth = 1; while (depth >0) < switch (parser.next()) < case XmlPullParser.START_TAG: depth++; break; case XmlPullParser.END_TAG: depth--; break; >> > private FontListParser() < >public static class Alias < public String name; public String toName; public int weight; >public static class Config < public Listaliases; public List families; Config() < families = new ArrayList(); aliases = new ArrayList(); > > public static class Family < public Listfonts; public String lang; public String name; public String variant; public Family(String name, List fonts, String lang, String variant) < this.name = name; this.fonts = fonts; this.lang = lang; this.variant = variant; >> public static class Font < public String fontName; public boolean isItalic; public int weight; Font(String fontName, int weight, boolean isItalic) < this.fontName = fontName; this.weight = weight; this.isItalic = isItalic; >> public static class SystemFont < public String name; public String path; public SystemFont(String name, String path) < this.name = name; this.path = path; >> >
Feel free to use the above class in your project. For example, you could give your users a selection of font families and set the typeface based on their preference.
A small incomplete example:
final List fonts = FontListParser.safelyGetSystemFonts(); String[] items = new String[fonts.size()]; for (int i = 0; i < fonts.size(); i++) < items[i] = fonts.get(i).name; >new AlertDialog.Builder(this).setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() < @Override public void onClick(DialogInterface dialog, int which) < FontListParser.SystemFont selectedFont = fonts.get(which); // TODO: do something with the font Toast.makeText(getApplicationContext(), selectedFont.path, Toast.LENGTH_LONG).show(); >>).show();
