С некоторыми разновидностями Android (Samsung, LG, HTC), похоже, можно установить системный шрифт по умолчанию без укорачивания . У меня нет одного из этих устройств для тестирования (у меня есть старый планшет Lenovo), но мне интересно следующее:
EDIT: Я добавляю способ, который, как я думал, может работать, но на самом деле это не так: сравнение Typeface.DEFAULT с объектами Typeface, созданными из файлов в каталогах /system/fonts
, /system/font
и /data/fonts
. Это не ответ, но это может помочь кому-то придумать. Также обратите внимание, что класс TTFAnalyzer не мой. Код следует:
private String getDefaultFont() { String[] fontdirs = { "/system/fonts", "/system/font", "/data/fonts" }; TTFAnalyzer analyzer = new TTFAnalyzer(); Typeface tfDefault = Typeface.DEFAULT; Typeface tfTemp = null; String defaultFontName = ""; System.out.println("getDefaultFont(): entry"); System.out.println("tfDefault: " + tfDefault.toString()); for ( String fontdir : fontdirs ) { File dir = new File( fontdir ); if ( !dir.exists() ) continue; File[] files = dir.listFiles(); if ( files == null ) continue; for ( File file : files ) { String fontname = analyzer.getTtfFontName( file.getAbsolutePath() ); if ( fontname != null ) { System.out.println("found font: " + fontname); tfTemp = Typeface.createFromFile(file); System.out.println("tfTemp: " + tfTemp.toString()); //** THIS SHOULD BE WORKING? **// if (tfTemp.equals(tfDefault)) { System.out.println("Found default font: " + fontname); defaultFontName = fontname; } } } } return defaultFontName; } // The class which loads the TTF file, parses it and returns the TTF font name class TTFAnalyzer { // This function parses the TTF file and returns the font name specified in the file public String getTtfFontName( String fontFilename ) { try { // Parses the TTF file format. // See http://developer.apple.com/fonts/ttrefman/rm06/Chap6.html m_file = new RandomAccessFile( fontFilename, "r" ); // Read the version first int version = readDword(); // The version must be either 'true' (0x74727565) or 0x00010000 if ( version != 0x74727565 && version != 0x00010000 ) return null; // The TTF file consist of several sections called "tables", and we need to know how many of them are there. int numTables = readWord(); // Skip the rest in the header readWord(); // skip searchRange readWord(); // skip entrySelector readWord(); // skip rangeShift // Now we can read the tables for ( int i = 0; i < numTables; i++ ) { // Read the table entry int tag = readDword(); readDword(); // skip checksum int offset = readDword(); int length = readDword(); // Now here' the trick. 'name' field actually contains the textual string name. // So the 'name' string in characters equals to 0x6E616D65 if ( tag == 0x6E616D65 ) { // Here's the name section. Read it completely into the allocated buffer byte[] table = new byte[ length ]; m_file.seek( offset ); read( table ); // This is also a table. See http://developer.apple.com/fonts/ttrefman/rm06/Chap6name.html // According to Table 36, the total number of table records is stored in the second word, at the offset 2. // Getting the count and string offset - remembering it's big endian. int count = getWord( table, 2 ); int string_offset = getWord( table, 4 ); // Record starts from offset 6 for ( int record = 0; record < count; record++ ) { // Table 37 tells us that each record is 6 words -> 12 bytes, and that the nameID is 4th word so its offset is 6. // We also need to account for the first 6 bytes of the header above (Table 36), so... int nameid_offset = record * 12 + 6; int platformID = getWord( table, nameid_offset ); int nameid_value = getWord( table, nameid_offset + 6 ); // Table 42 lists the valid name Identifiers. We're interested in 4 but not in Unicode encoding (for simplicity). // The encoding is stored as PlatformID and we're interested in Mac encoding if ( nameid_value == 4 && platformID == 1 ) { // We need the string offset and length, which are the word 6 and 5 respectively int name_length = getWord( table, nameid_offset + 8 ); int name_offset = getWord( table, nameid_offset + 10 ); // The real name string offset is calculated by adding the string_offset name_offset = name_offset + string_offset; // Make sure it is inside the array if ( name_offset >= 0 && name_offset + name_length < table.length ) return new String( table, name_offset, name_length ); } } } } return null; } catch (FileNotFoundException e) { // Permissions? return null; } catch (IOException e) { // Most likely a corrupted font file return null; } } // Font file; must be seekable private RandomAccessFile m_file = null; // Helper I/O functions private int readByte() throws IOException { return m_file.read() & 0xFF; } private int readWord() throws IOException { int b1 = readByte(); int b2 = readByte(); return b1 << 8 | b2; } private int readDword() throws IOException { int b1 = readByte(); int b2 = readByte(); int b3 = readByte(); int b4 = readByte(); return b1 << 24 | b2 << 16 | b3 << 8 | b4; } private void read( byte [] array ) throws IOException { if ( m_file.read( array ) != array.length ) throw new IOException(); } // Helper private int getWord( byte [] array, int offset ) { int b1 = array[ offset ] & 0xFF; int b2 = array[ offset + 1 ] & 0xFF; return b1 << 8 | b2; } }
РЕДАКТИРОВАТЬ 2: еще немного информации о том, что ты купишь мой планшет Lenovo. В /system/etc
есть несколько интересных XML-файлов:
system_fonts.xml
– похоже, что он имеет шрифты по умолчанию для регулярного / курсивного / полужирного шрифта в качестве первой записи семейства fallback_fonts.xml
– у которого есть шрифты, которые Android должен отступить, если он не может найти глиф в текущем шрифте (например, тайские символы). Возможно, стоит разобрать этот файл system_fonts и вернуть имя шрифта по умолчанию, но я не знаю, правильно ли это сделать.
Хорошо, вот что я думаю, что работает. Что касается одобрения Android, ну, это хакки. Это решение предполагает несколько вещей:
/system/etc/system_fonts.xml
содержит список шрифтов на устройстве. <file>
в этом файле system_fonts.xml
является шрифтом по умолчанию для устройства. /system/fonts
. Эти предположения связаны с просмотром файла класса Typeface
с Android 5.x, но я тестировал еще пару других версий, и решение, похоже, тоже работает там. Код следует (при условии, что класс TTFAnalyzer, указанный выше):
import android.util.Xml; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; public String getDefaultFont() { System.out.println("getFontList(): entry"); File configFilename = new File("/system/etc/system_fonts.xml"); String defaultFontName = ""; TTFAnalyzer analyzer = new TTFAnalyzer(); try { FileInputStream fontsIn = new FileInputStream(configFilename); XmlPullParser parser = Xml.newPullParser(); parser.setInput(fontsIn, null); Boolean done = false; Boolean getTheText = false; int eventType; String defaultFont = ""; while (!done) { eventType = parser.next(); if (eventType == parser.START_TAG && parser.getName().equalsIgnoreCase("file")) { // the text is next up -- pull it getTheText = true; } if (eventType == parser.TEXT && getTheText == true) { // first name defaultFont = parser.getText(); System.out.println("text for file tag:" + defaultFont); done = true; } if (eventType == parser.END_DOCUMENT) { System.out.println("hit end of system_fonts.xml document"); done = true; } } if (defaultFont.length() > 0) { // found the font filename, most likely in /system/fonts. Now pull out the human-readable // string from the font file System.out.println("Figuring out default Font info"); String fontname = analyzer.getTtfFontName("/system/fonts/" + defaultFont); if ( fontname != null ) { System.out.println("found font info: " + fontname); defaultFontName = fontname; } } } catch (RuntimeException e) { System.err.println("Didn't create default family (most likely, non-Minikin build)"); // TODO: normal in non-Minikin case, remove or make error when Minikin-only } catch (FileNotFoundException e) { System.err.println("GetDefaultFont: config file Not found"); } catch (IOException e) { System.err.println("GetDefaultFont: IO exception: " + e.getMessage()); } catch (XmlPullParserException e) { System.err.println("getDefaultFont: XML parse exception " + e.getMessage()); } return defaultFontName; }
String fontName=Typeface.Default;
Это вернет имя шрифта в строке
Typeface.defaultFromStyle(int style).
Возвращает шрифт из определенного стиля.
https://developer.android.com/reference/android/graphics/Typeface.html