Я добавил файл пользовательского шрифта в папку с ресурсами / шрифтами. Как мне использовать его из моего XML?
Я могу использовать его из кода следующим образом:
TextView text = (TextView) findViewById(R.id.textview03);
Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/Molot.otf");
text.setTypeface(tf);
Разве я не могу сделать это из XML с помощью android:typeface="/fonts/Molot.otf"
атрибута?
Ответы:
Краткий ответ: Нет. Android не имеет встроенной поддержки для применения пользовательских шрифтов к текстовым виджетам через XML.
Однако есть обходной путь, который не так уж сложно реализовать.
Первый
Вам нужно будет определить свой собственный стиль. В папке / res / values откройте / создайте файл attrs.xml и добавьте объект с объявленным стилем, например:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="FontText"> <attr name="typefaceAsset" format="string"/> </declare-styleable> </resources>
Второй
Предполагая, что вы хотите часто использовать этот виджет, вам следует настроить простой кеш для загруженных
Typeface
объектов, поскольку загрузка их из памяти на лету может занять время. Что-то типа:public class FontManager { private static FontManager instance; private AssetManager mgr; private Map<String, Typeface> fonts; private FontManager(AssetManager _mgr) { mgr = _mgr; fonts = new HashMap<String, Typeface>(); } public static void init(AssetManager mgr) { instance = new FontManager(mgr); } public static FontManager getInstance() { if (instance == null) { // App.getContext() is just one way to get a Context here // getContext() is just a method in an Application subclass // that returns the application context AssetManager assetManager = App.getContext().getAssets(); init(assetManager); } return instance; } public Typeface getFont(String asset) { if (fonts.containsKey(asset)) return fonts.get(asset); Typeface font = null; try { font = Typeface.createFromAsset(mgr, asset); fonts.put(asset, font); } catch (Exception e) { } if (font == null) { try { String fixedAsset = fixAssetFilename(asset); font = Typeface.createFromAsset(mgr, fixedAsset); fonts.put(asset, font); fonts.put(fixedAsset, font); } catch (Exception e) { } } return font; } private String fixAssetFilename(String asset) { // Empty font filename? // Just return it. We can't help. if (TextUtils.isEmpty(asset)) return asset; // Make sure that the font ends in '.ttf' or '.ttc' if ((!asset.endsWith(".ttf")) && (!asset.endsWith(".ttc"))) asset = String.format("%s.ttf", asset); return asset; } }
Это позволит вам использовать расширения файлов .ttc, но не проверено.
Третий
Создайте новый класс, который является подклассом
TextView
. В этом конкретном примере учитывается определенный шрифт XML (bold
,italic
и т. Д.) И применяется к шрифту (при условии, что вы используете файл .ttc)./** * TextView subclass which allows the user to define a truetype font file to use as the view's typeface. */ public class FontText extends TextView { public FontText(Context context) { this(context, null); } public FontText(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FontText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); if (isInEditMode()) return; TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.FontText); if (ta != null) { String fontAsset = ta.getString(R.styleable.FontText_typefaceAsset); if (!TextUtils.isEmpty(fontAsset)) { Typeface tf = FontManager.getInstance().getFont(fontAsset); int style = Typeface.NORMAL; float size = getTextSize(); if (getTypeface() != null) style = getTypeface().getStyle(); if (tf != null) setTypeface(tf, style); else Log.d("FontText", String.format("Could not create a font from asset: %s", fontAsset)); } } } }
в заключение
Замените экземпляры
TextView
в вашем XML на полное имя класса. Объявите собственное пространство имен так же, как и пространство имен Android. Обратите внимание, что «typefaceAsset» должен указывать на файл .ttf или .ttc, содержащийся в вашем каталоге / assets.<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <com.example.FontText android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="This is a custom font text" custom:typefaceAsset="fonts/AvenirNext-Regular.ttf"/> </RelativeLayout>
источник
Вот пример кода, который это делает. У меня шрифт определен в статической конечной переменной, а файл шрифта находится в каталоге ресурсов.
public class TextViewWithFont extends TextView { public TextViewWithFont(Context context, AttributeSet attrs) { super(context, attrs); this.setTypeface(MainActivity.typeface); } public TextViewWithFont(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.setTypeface(MainActivity.typeface); } public TextViewWithFont(Context context) { super(context); this.setTypeface(MainActivity.typeface); } }
источник
Создайте свой собственный TextView, принадлежащий шрифту, который вы хотите использовать. В этом классе я использую статическое поле mTypeface для кеширования гарнитуры шрифта (для повышения производительности).
public class HeliVnTextView extends TextView { /* * Caches typefaces based on their file path and name, so that they don't have to be created every time when they are referenced. */ private static Typeface mTypeface; public HeliVnTextView(final Context context) { this(context, null); } public HeliVnTextView(final Context context, final AttributeSet attrs) { this(context, attrs, 0); } public HeliVnTextView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); if (mTypeface == null) { mTypeface = Typeface.createFromAsset(context.getAssets(), "HelveticaiDesignVnLt.ttf"); } setTypeface(mTypeface); } }
В xml файле:
<java.example.HeliVnTextView android:id="@+id/textView1" android:layout_width="0dp" ... />
В классе java:
HeliVnTextView title = new HeliVnTextView(getActivity()); title.setText(issue.getName());
источник
Activity реализует LayoutInflater.Factory2, который обеспечивает обратные вызовы для каждого созданного View. Можно стилизовать TextView с помощью настраиваемого атрибута Family font, загружать гарнитуры по запросу и автоматически вызывать setTypeface в созданных текстовых представлениях.
К сожалению, из-за архитектурной взаимосвязи экземпляров Inflater с Activity и Windows, самый простой подход к использованию пользовательских шрифтов в Android - кэширование загруженных шрифтов на уровне приложения.
База примеров кода находится здесь:
https://github.com/leok7v/android-textview-custom-fonts
<style name="Baroque" parent="@android:style/TextAppearance.Medium"> <item name="android:layout_width">fill_parent</item> <item name="android:layout_height">wrap_content</item> <item name="android:textColor">#F2BAD0</item> <item name="android:textSize">14pt</item> <item name="fontFamily">baroque_script</item> </style> <?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/custom.fonts" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView style="@style/Baroque" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/sample_text" />
приводит к
источник
Не рекомендуется использовать пользовательские шрифты в xml из-за того факта, что вы должны делать это программно, чтобы избежать утечки памяти!
источник
Может быть, вы можете использовать отражение для внедрения / взлома вашего шрифта в статический список доступных шрифтов при создании вашего приложения? Мне интересны отзывы других , действительно ли это плохая идея или отличное решение - похоже, это будет одна из этих крайностей ...
Мне удалось добавить свой собственный шрифт в список системных шрифтов с моим собственным именем семейства шрифтов, а затем указать это имя семейства пользовательских шрифтов ("brush-script") в качестве значения android: FontFamily в стандартном TextView, работавшем на моем LG G4 под управлением Android 6.0.
public class MyApplication extends android.app.Application { @Override public void onCreate() { super.onCreate(); Typeface font = Typeface.createFromAsset(this.getResources().getAssets(),"fonts/brush-script.ttf"); injectTypeface("brush-script", font); } private boolean injectTypeface(String fontFamily, Typeface typeface) { try { Field field = Typeface.class.getDeclaredField("sSystemFontMap"); field.setAccessible(true); Object fieldValue = field.get(null); Map<String, Typeface> map = (Map<String, Typeface>) fieldValue; map.put(fontFamily, typeface); return true; } catch (Exception e) { Log.e("Font-Injection", "Failed to inject typeface.", e); } return false; } }
В моем макете
<TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Fancy Text" android:fontFamily="brush-script"/>
источник
MyApplication
вызывать класс?public class CustomTextView extends TextView { private static final String TAG = "TextView"; public CustomTextView(Context context) { super(context); } public CustomTextView(Context context, AttributeSet attrs) { super(context, attrs); setCustomFont(context, attrs); } public CustomTextView(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.CustomTextView); String customFont = a.getString(R.styleable.CustomTextView_customFont); setCustomFont(ctx, customFont); a.recycle(); } public boolean setCustomFont(Context ctx, String fontName) { Typeface typeface = null; try { if(fontName == null){ fontName = Constants.DEFAULT_FONT_NAME; } typeface = Typeface.createFromAsset(ctx.getAssets(), "fonts/" + fontName); } catch (Exception e) { Log.e(TAG, "Unable to load typeface: "+e.getMessage()); return false; } setTypeface(typeface); return true; } }
и добавьте декларируемый объект в attrs.xml
<declare-styleable name="CustomTextView"> <attr name="customFont" format="string"/> </declare-styleable>
а затем добавьте свой собственный шрифт, например
app:customFont="arial.ttf"
источник
Я знаю, что это старый вопрос, но я нашел гораздо более простое решение.
Сначала объявите свой TextView в xml как обычно. Поместите свой шрифт (TTF или TTC) в папку с ресурсами
Затем просто установите шрифт для текстового представления в методе onCreate.
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_name); TextView textView = findViewById(R.id.my_textView); Typeface typeface = Typeface.createFromAsset(getAssets(), "fontName.ttf"); textView.setTypeface(typeface); }
Выполнено.
источник
Лучшее решение - использовать (наконец) введенную Google встроенную функцию пользовательского шрифта в XML. Но вы должны использовать API 26. Он поддерживает API 16+.
https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml
источник
вместо xmlns: custom = "schemas.android.com/tools"; вы должны использовать: xmlns: custom = "schemas.android.com/apk/res-auto"; чтобы использовать стилизуемые атрибуты. Я внес это изменение, и теперь оно работает.
источник