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.

<TextView
    android:id="@+id/HeaderText"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="52dp"
    android:gravity="center"
    android:text="CallerBlocker"
    android:textSize="40dp"
    android:fontFamily="Arial"
 />

It seems what I did up there won't really work! BTW android:fontFamily="Arial" was a stupid attempt!


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
  • fonts.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="font_family_light">sans-serif-light</string>
        <string name="font_family_medium">sans-serif-medium</string>
        <string name="font_family_regular">sans-serif</string>
        <string name="font_family_condensed">sans-serif-condensed</string>
        <string name="font_family_black">sans-serif-black</string>
        <string name="font_family_thin">sans-serif-thin</string>
    </resources>
    

    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


    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.</p>
     * 
     * Usage:</p> {@code List<SystemFont> fonts = FontListParser.safelyGetSystemFonts();}</p>
     */
    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 List<SystemFont> getSystemFonts() 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<SystemFont> 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<SystemFont>() {
    
                @Override
                public int compare(SystemFont font1, SystemFont font2) {
                    return font1.name.compareToIgnoreCase(font2.name);
                }
    
            });
    
            return fonts;
        }
    
        public static List<SystemFont> 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<SystemFont> 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");
            List<Font> fonts = new ArrayList<Font>();
            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 List<Alias> aliases;
    
            public List<Family> families;
    
            Config() {
                families = new ArrayList<Family>();
                aliases = new ArrayList<Alias>();
            }
    
        }
    
        public static class Family {
    
            public List<Font> fonts;
    
            public String lang;
    
            public String name;
    
            public String variant;
    
            public Family(String name, List<Font> 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<FontListParser.SystemFont> 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();
    
    链接地址: http://www.djcxy.com/p/13004.html

    上一篇: ViewPager - 如何在每个页面上启动不同的定时器?

    下一篇: 如何在Android中更改TextView的fontFamily