Как установить пользовательский шрифт в заголовке ActionBar? - PullRequest
248 голосов
/ 22 декабря 2011

Как (если возможно) я могу установить собственный шрифт в тексте заголовка ActionBar (только - не текст вкладки) со шрифтом в моей папке ресурсов?Я не хочу использовать вариант Android: логотип.

Ответы [ 18 ]

419 голосов
/ 03 марта 2013

Вы можете сделать это, используя пользовательский класс TypefaceSpan. Он превосходит описанный выше подход customView, потому что он не ломается при использовании других элементов панели действий, таких как расширение видов действий.

Использование такого класса будет выглядеть примерно так:

SpannableString s = new SpannableString("My Title");
s.setSpan(new TypefaceSpan(this, "MyTypeface.otf"), 0, s.length(),
        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

// Update the action bar title with the TypefaceSpan instance
ActionBar actionBar = getActionBar();
actionBar.setTitle(s);

Пользовательскому классу TypefaceSpan передается ваш контекст Activity и имя гарнитуры в вашем каталоге assets/fonts. Он загружает файл и кэширует новый экземпляр Typeface в памяти. Полная реализация TypefaceSpan удивительно проста:

/**
 * Style a {@link Spannable} with a custom {@link Typeface}.
 * 
 * @author Tristan Waddington
 */
public class TypefaceSpan extends MetricAffectingSpan {
      /** An <code>LruCache</code> for previously loaded typefaces. */
    private static LruCache<String, Typeface> sTypefaceCache =
            new LruCache<String, Typeface>(12);

    private Typeface mTypeface;

    /**
     * Load the {@link Typeface} and apply to a {@link Spannable}.
     */
    public TypefaceSpan(Context context, String typefaceName) {
        mTypeface = sTypefaceCache.get(typefaceName);

        if (mTypeface == null) {
            mTypeface = Typeface.createFromAsset(context.getApplicationContext()
                    .getAssets(), String.format("fonts/%s", typefaceName));

            // Cache the loaded Typeface
            sTypefaceCache.put(typefaceName, mTypeface);
        }
    }

    @Override
    public void updateMeasureState(TextPaint p) {
        p.setTypeface(mTypeface);

        // Note: This flag is required for proper typeface rendering
        p.setFlags(p.getFlags() | Paint.SUBPIXEL_TEXT_FLAG);
    }

    @Override
    public void updateDrawState(TextPaint tp) {
        tp.setTypeface(mTypeface);

        // Note: This flag is required for proper typeface rendering
        tp.setFlags(tp.getFlags() | Paint.SUBPIXEL_TEXT_FLAG);
    }
}

Просто скопируйте приведенный выше класс в свой проект и внедрите его в метод onCreate вашей деятельности, как показано выше.

207 голосов
/ 05 января 2012

Я согласен, что это не полностью поддерживается, но вот что я сделал.Вы можете использовать пользовательский вид для своей панели действий (она будет отображаться между вашим значком и вашими элементами действий).Я использую пользовательский вид, и у меня отключен собственный заголовок.Все мои действия наследуются от одного действия, которое имеет следующий код в onCreate:

this.getActionBar().setDisplayShowCustomEnabled(true);
this.getActionBar().setDisplayShowTitleEnabled(false);

LayoutInflater inflator = LayoutInflater.from(this);
View v = inflator.inflate(R.layout.titleview, null);

//if you need to customize anything else about the text, do it here.
//I'm using a custom TextView with a custom font in my layout xml so all I need to do is set title
((TextView)v.findViewById(R.id.title)).setText(this.getTitle());

//assign the view to the actionbar
this.getActionBar().setCustomView(v);

И мой макет XML (R.layout.titleview в приведенном выше коде) выглядит следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent" >

<com.your.package.CustomTextView
        android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="10dp"
            android:textSize="20dp"
            android:maxLines="1"
            android:ellipsize="end"
            android:text="" />
</RelativeLayout>
149 голосов
/ 11 декабря 2013
int titleId = getResources().getIdentifier("action_bar_title", "id",
            "android");
    TextView yourTextView = (TextView) findViewById(titleId);
    yourTextView.setTextColor(getResources().getColor(R.color.black));
    yourTextView.setTypeface(face);
25 голосов
/ 13 ноября 2017

Начиная с Библиотека поддержки Android v26 + Android Studio 3.0 и далее, этот процесс стал простым делом !!

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

  1. Читать Загружаемые шрифты и выбрать любой шрифт из списка ( моя рекомендация ) или загрузить собственный шрифт в res > font согласно Шрифты в XML
  2. В res > values > styles вставьте следующее ( используйте здесь свое воображение! )

    <style name="TitleBarTextAppearance" parent="android:TextAppearance">
        <item name="android:fontFamily">@font/your_desired_font</item>
        <item name="android:textSize">23sp</item>
        <item name="android:textStyle">bold</item>
        <item name="android:textColor">@android:color/white</item>
    </style>
    
  3. Вставьте новую строку в свойствах панели инструментов app:titleTextAppearance="@style/TextAppearance.TabsFont", как показано ниже

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:titleTextAppearance="@style/TitleBarTextAppearance"
        app:popupTheme="@style/AppTheme.PopupOverlay"/>
    
  4. Наслаждайтесь пользовательским стилем шрифта заголовка панели действий !!

13 голосов
/ 01 мая 2014

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

<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<item name="android:textViewStyle">@style/AppTheme.Widget.TextView</item>
</style>

<style name="AppTheme.Widget"/>

<style name="AppTheme.Widget.TextView" parent="android:Widget.Holo.Light.TextView">
   <item name="fontPath">fonts/Roboto-ThinItalic.ttf</item>
</style>

Все, что требуется для активации каллиграфии, - это привязать ее к контексту вашей деятельности:

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

Настраиваемый атрибут по умолчанию - fontPath, но вы можете указать свой собственный атрибут для пути, инициализировав его в классе приложения с помощью CalligraphyConfig.Builder. Использование android:fontFamily не рекомендуется.

11 голосов
/ 05 января 2013

Это ужасный хак, но вы можете сделать это следующим образом (поскольку action_bar_title скрыт):

    try {
        Integer titleId = (Integer) Class.forName("com.android.internal.R$id")
                .getField("action_bar_title").get(null);
        TextView title = (TextView) getWindow().findViewById(titleId);
        // check for null and manipulate the title as see fit
    } catch (Exception e) {
        Log.e(TAG, "Failed to obtain action bar title reference");
    }

Этот код предназначен для устройств после GINGERBREAD, но его можно легко расширить и для работы с Actionbar Sherlock

P.S. На основе комментария @pjv есть лучший способ найти идентификатор заголовка панели действий

final int titleId = 
    Resources.getSystem().getIdentifier("action_bar_title", "id", "android");
8 голосов
/ 29 сентября 2014

используйте новую панель инструментов в библиотеке поддержки. Создайте свою панель действий как свою собственную или используйте приведенный ниже код

Раздувание Textview не является хорошим вариантом, попробуйте Spannable String builder

Typeface font2 = Typeface.createFromAsset(getAssets(), "fonts/<your font in assets folder>");   
SpannableStringBuilder SS = new SpannableStringBuilder("MY Actionbar Tittle");
SS.setSpan (new CustomTypefaceSpan("", font2), 0, SS.length(),Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
actionBar.setTitle(ss);

копия ниже класса

public class CustomTypefaceSpan extends TypefaceSpan{

    private final Typeface newType;

    public CustomTypefaceSpan(String family, Typeface type) {
        super(family);
        newType = type;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        applyCustomTypeFace(ds, newType);
    }

    @Override
    public void updateMeasureState(TextPaint paint) {
        applyCustomTypeFace(paint, newType);
    }

    private static void applyCustomTypeFace(Paint paint, Typeface tf) {
        int oldStyle;
        Typeface old = paint.getTypeface();
        if (old == null) {
            oldStyle = 0;
        } else {
            oldStyle = old.getStyle();
        }

        int fake = oldStyle & ~tf.getStyle();
        if ((fake & Typeface.BOLD) != 0) {
            paint.setFakeBoldText(true);
        }

        if ((fake & Typeface.ITALIC) != 0) {
            paint.setTextSkewX(-0.25f);
        }

        paint.setTypeface(tf);
    }

}
8 голосов
/ 01 апреля 2014

Следующий код будет работать для всех версий.Я проверял это на устройстве с пряниками, а также на устройстве JellyBean

 private void actionBarIdForAll()
    {
        int titleId = 0;

        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB)
        {
            titleId = getResources().getIdentifier("action_bar_title", "id", "android");
        }
        else
        {
          // This is the id is from your app's generated R class when ActionBarActivity is used for SupportActionBar

            titleId = R.id.action_bar_title;
        }

        if(titleId>0)
        {
            // Do whatever you want ? It will work for all the versions.

            // 1. Customize your fonts
            // 2. Infact, customize your whole title TextView

            TextView titleView = (TextView)findViewById(titleId);
            titleView.setText("RedoApp");
            titleView.setTextColor(Color.CYAN);
        }
    }
5 голосов
/ 31 июля 2018
    ActionBar actionBar = getSupportActionBar();
    TextView tv = new TextView(getApplicationContext());
    Typeface typeface = ResourcesCompat.getFont(this, R.font.monotype_corsiva);
    RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.MATCH_PARENT, // Width of TextView
            RelativeLayout.LayoutParams.WRAP_CONTENT); // Height of TextView
    tv.setLayoutParams(lp);
    tv.setText("Your Text"); // ActionBar title text
    tv.setTextSize(25);
    tv.setTextColor(Color.WHITE);
    tv.setTypeface(typeface, typeface.ITALIC);
    actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
    actionBar.setCustomView(tv);
3 голосов
/ 26 октября 2017

Я только что сделал следующее внутри функции onCreate ():

TypefaceSpan typefaceSpan = new TypefaceSpan("font_to_be_used");
SpannableString str = new SpannableString("toolbar_text");
str.setSpan(typefaceSpan,0, str.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
getSupportActionBar().setTitle(str);

Я использую библиотеки поддержки, если вы их не используете, я думаю, вам следует переключиться на getActionBar () вместо getSupportActionBar ().

В Android Studio 3 вы можете добавить пользовательские шрифты, следуя этой инструкции https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html, а затем использовать только что добавленный шрифт в "font_to_be_used"

...