Пользовательские шрифты и макеты XML (Android) - PullRequest
173 голосов
/ 04 марта 2010

Я пытаюсь определить макет GUI, используя файлы XML в Android. Насколько я могу судить, нет никакого способа указать, что ваши виджеты должны использовать пользовательский шрифт (например, тот, который вы поместили в assets / font /) в XML-файлах, и вы можете использовать только системные шрифты.

Я знаю, что в коде Java я мог изменить шрифт каждого виджета вручную, используя уникальные идентификаторы. В качестве альтернативы я мог бы перебрать все виджеты в Java, чтобы внести это изменение, но это, вероятно, будет очень медленным.

Какие еще есть варианты? Есть ли лучшие способы сделать виджеты, которые имеют индивидуальный вид? Я не особо хочу вручную менять шрифт для каждого нового виджета, который я добавляю.

Ответы [ 18 ]

220 голосов
/ 26 августа 2011

Вы можете расширить TextView для установки пользовательских шрифтов, как я узнал здесь .

TextViewPlus.java:

package com.example;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;

public class TextViewPlus extends TextView {
    private static final String TAG = "TextView";

    public TextViewPlus(Context context) {
        super(context);
    }

    public TextViewPlus(Context context, AttributeSet attrs) {
        super(context, attrs);
        setCustomFont(context, attrs);
    }

    public TextViewPlus(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.TextViewPlus);
        String customFont = a.getString(R.styleable.TextViewPlus_customFont);
        setCustomFont(ctx, customFont);
        a.recycle();
    }

    public boolean setCustomFont(Context ctx, String asset) {
        Typeface tf = null;
        try {
        tf = Typeface.createFromAsset(ctx.getAssets(), asset);  
        } catch (Exception e) {
            Log.e(TAG, "Could not get typeface: "+e.getMessage());
            return false;
        }

        setTypeface(tf);  
        return true;
    }

}

attrs.xml: (в рез / значениях)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="TextViewPlus">
        <attr name="customFont" format="string"/>
    </declare-styleable>
</resources>

main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:foo="http://schemas.android.com/apk/res/com.example"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <com.example.TextViewPlus
        android:id="@+id/textViewPlus1"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:text="@string/showingOffTheNewTypeface"
        foo:customFont="saxmono.ttf">
    </com.example.TextViewPlus>
</LinearLayout>

Вы должны поместить "saxmono.ttf" в папку assets .

ОБНОВЛЕНИЕ 8/1/13

При использовании этого метода возникают серьезные проблемы с памятью. См. комментарий чедабоба ниже.

35 голосов
/ 09 мая 2013

Я опоздал на вечеринку на 3 года :( Однако это может быть полезно для тех, кто может наткнуться на этот пост.

Я написал библиотеку, которая кэширует гарнитуры, а также позволяет указывать пользовательские гарнитуры прямо из XML. Вы можете найти библиотеку здесь .

Вот как будет выглядеть ваш XML-макет, когда вы его используете.

<com.mobsandgeeks.ui.TypefaceTextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world"
    geekui:customTypeface="fonts/custom_font.ttf" />
18 голосов
/ 22 апреля 2013

Это может быть немного поздно, но вам нужно создать одноэлементный класс, который возвращает пользовательский шрифт, чтобы избежать утечек памяти.

Класс TypeFace:

public class OpenSans {

private static OpenSans instance;
private static Typeface typeface;

public static OpenSans getInstance(Context context) {
    synchronized (OpenSans.class) {
        if (instance == null) {
            instance = new OpenSans();
            typeface = Typeface.createFromAsset(context.getResources().getAssets(), "open_sans.ttf");
        }
        return instance;
    }
}

public Typeface getTypeFace() {
    return typeface;
}
}

Пользовательский TextView:

public class NativelyCustomTextView extends TextView {

    public NativelyCustomTextView(Context context) {
        super(context);
        setTypeface(OpenSans.getInstance(context).getTypeFace());
    }

    public NativelyCustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setTypeface(OpenSans.getInstance(context).getTypeFace());
    }

    public NativelyCustomTextView(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
        setTypeface(OpenSans.getInstance(context).getTypeFace());
    }

}

По xml:

<com.yourpackage.views.NativelyCustomTextView
            android:id="@+id/natively_text_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_margin="20dp"
            android:text="@string/natively"
            android:textSize="30sp" /> 

Программный:

TextView programmaticallyTextView = (TextView) 
       findViewById(R.id.programmatically_text_view);

programmaticallyTextView.setTypeface(OpenSans.getInstance(this)
                .getTypeFace());
13 голосов
/ 01 мая 2014

Старый вопрос, но я уверен, что хотел бы прочитать этот ответ здесь, прежде чем я начну свой собственный поиск хорошего решения. Каллиграфия расширяет атрибут android:fontFamily, добавляя поддержку пользовательских шрифтов в папку ресурсов, например:

<TextView 
  android:text="@string/hello_world"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:fontFamily="fonts/Roboto-Bold.ttf"/>

Единственное, что вам нужно сделать, чтобы активировать его, это привязать его к контексту действия, которое вы используете:

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(new CalligraphyContextWrapper(newBase));
}

Вы также можете указать свой собственный атрибут для замены android:fontFamily

Он также работает в темах, включая AppTheme.

8 голосов
/ 03 сентября 2015

Использование Привязка данных :

@BindingAdapter({"bind:font"})
public static void setFont(TextView textView, String fontName){
 textView.setTypeface(Typeface.createFromAsset(textView.getContext().getAssets(), "fonts/" + fontName));
}

В XML:

<TextView
app:font="@{`Source-Sans-Pro-Regular.ttf`}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Файл шрифта

должен быть в assets/fonts/

7 голосов
/ 02 мая 2012

Если у вас есть только одна гарнитура, которую вы хотите добавить, и вы хотите писать меньше кода, вы можете создать выделенный TextView для вашего конкретного шрифта. Смотрите код ниже.

package com.yourpackage;
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;

public class FontTextView extends TextView {
    public static Typeface FONT_NAME;


    public FontTextView(Context context) {
        super(context);
        if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "fonts/FontName.otf");
        this.setTypeface(FONT_NAME);
    }
    public FontTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "fonts/FontName.otf");
        this.setTypeface(FONT_NAME);
    }
    public FontTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        if(FONT_NAME == null) FONT_NAME = Typeface.createFromAsset(context.getAssets(), "fonts/FontName.otf");
        this.setTypeface(FONT_NAME);
    }
}

В main.xml теперь вы можете добавить свой textView так:

<com.yourpackage.FontTextView
    android:id="@+id/tvTimer"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="" />
7 голосов
/ 28 марта 2017

Лучший способ сделать это из предварительной версии Android O - это
1.) Щелкните правой кнопкой мыши папку res и перейдите в New> Каталог ресурсов Android . Новый
Откроется окно каталога ресурсов.
2.) В списке Тип ресурса выберите шрифт и нажмите кнопку ОК.
3.) Добавьте файлы шрифтов в папку шрифтов . Структура папок ниже генерирует R.font.dancing_script, R.font.la_la и R.font.ba_ba.
4.) Дважды щелкните файл шрифта, чтобы просмотреть шрифты файла в редакторе.

Далее мы должны создать семейство шрифтов

1.) Щелкните правой кнопкой мыши папку шрифтов и выберите Создать> Файл ресурса шрифта . Откроется окно «Новый файл ресурсов».
2.) Введите имя файла и нажмите кнопку ОК . Новый ресурс шрифта XML открывается в редакторе.
3.) Включите каждый файл шрифта, стиль и атрибут веса в элемент тега шрифта. Следующий XML-код иллюстрирует добавление атрибутов, связанных со шрифтом, в XML-ресурс шрифта:

<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android">
    <font
    android:fontStyle="normal"
    android:fontWeight="400"
    android:font="@font/hey_regular" />
    <font
    android:fontStyle="italic"
    android:fontWeight="400"
    android:font="@font/hey_bababa" />
</font-family>

Добавление шрифтов в TextView:

   <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    **android:fontFamily="@font/ba_ba"**/>

Начиная с документации

Работа со шрифтами

все шаги верны.

5 голосов
/ 24 февраля 2011

Расширьте TextView и дайте ему собственный атрибут или просто используйте атрибут тега android: для передачи строки того шрифта, который вы хотите использовать. Вам нужно будет выбрать соглашение и придерживаться его, так как я положу все свои шрифты в папку res / assets / fonts /, чтобы ваш класс TextView знал, где их найти. Затем в конструкторе вы просто устанавливаете шрифт вручную после супер вызова.

4 голосов
/ 06 марта 2010

Единственный способ использовать пользовательские шрифты - через исходный код.

Просто помните, что Android работает на устройствах с очень ограниченными ресурсами, и шрифты могут потребовать достаточного количества оперативной памяти. Встроенные шрифты Droid сделаны специально, и, если вы заметили, многие символы и декорации отсутствуют.

2 голосов
/ 13 декабря 2013

У меня может быть простой ответ на вопрос без расширения TextView и реализации длинного кода.

Код:

 TextView tv = (TextView) findViewById(R.id.textview1);
    tv.setTypeface(Typeface.createFromAsset(getAssets(), "font.ttf"));

Поместите файл пользовательского шрифта в папку ресурсов как обычно и попробуйте это. Меня устраивает. Я просто не понимаю, почему Питер дал такой огромный код для этой простой вещи или он дал свой ответ в старой версии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...