Использование пользовательского шрифта в Android TextView с использованием xml
Я добавил файл пользовательского шрифта в свою папку assets / fonts. Как мне использовать его из моего 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"
атрибут?
Переведено автоматически
Ответ 1
Краткий ответ: Нет. 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>
Ответ 2
Вот пример кода, который делает это. У меня есть шрифт, определенный в статической конечной переменной, а файл шрифта находится в каталоге assets.
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);
}
}
Ответ 3
Создайте свой пользовательский 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());
Ответ 4
Activity реализует LayoutInflater.Factory2, который обеспечивает обратные вызовы для каждого созданного представления. Можно стилизовать TextView с помощью атрибута пользовательского семейства шрифтов, загружать шрифты по запросу и автоматически вызывать setTypeface для созданных текстовых представлений.
К сожалению, из-за архитектурной взаимосвязи экземпляров Inflater относительно Activities и 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"
/>
приводит к