如何在ActionBar标题中设置自定义字体?

252 fonts android android-actionbar

如何(如果可能的话)我可以在我的资产文件夹中使用字体在ActionBar标题文本中设置自定义字体(仅限 - 而不是标签文本)?我不想使用android:logo选项.

twa*_*ton 420

您可以使用自定义TypefaceSpan类来完成此操作.它优于customView上面指出的方法,因为在使用其他Action Bar元素(如扩展操作视图)时它不会中断.

使用这样的类看起来像这样:

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);
Run Code Online (Sandbox Code Playgroud)

自定义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);
    }
}
Run Code Online (Sandbox Code Playgroud)

只需将上述类复制到您的项目中,并在您的activity onCreate方法中实现它,如上所示.

  • 很好的答案.值得一看的是,您还展示了一种缓存字体元素的方法. (20认同)
  • 这应该是公认的答案.谢谢! (12认同)
  • 这很棒.一个问题 - 如果`textAllCaps`属性在底层TextView上设置为true(例如通过主题),则不会出现自定义字体.当我将此技术应用于操作栏选项卡项时,这对我来说是一个问题. (6认同)
  • 请注意,该类的实现假定您将字体文件放在`assets/fonts /`中.如果您只是将.ttf/.otf文件放在资源下而不是子文件夹中,则应相应地修改以下代码行:`String.format("fonts /%s",typefaceName)`.我失去了好十分钟试图解决它.如果不这样做,您将得到`java.lang.RuntimeException:无法启动活动ComponentInfo {com.your.pckage}:java.lang.RuntimeException:无法生成本机字体 (4认同)
  • 这真太了不起了.谢谢. (2认同)
  • @artworkadシ哦,但你可以!https://gist.github.com/twaddington/8035951 (2认同)
  • 这是一个很好的答案,帮了我一大堆.我要添加的一个改进是将缓存机制移动到TypefaceSpan之外的自己的类中.我遇到了其他情况,我使用没有跨度的字体,这使我在这些情况下也可以利用缓存. (2认同)

Sam*_*zor 208

我同意这不完全支持,但这就是我所做的.您可以为操作栏使用自定义视图(它将显示在您的图标和操作项之间).我正在使用自定义视图,我禁用了本机标题.我的所有活动都继承自单个活动,该活动在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);
Run Code Online (Sandbox Code Playgroud)

我的布局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>
Run Code Online (Sandbox Code Playgroud)

  • 好的解决方案 如果您需要一个允许以XML格式指定字体的自定义文本视图类,请尝试我的!http://github.com/tom-dignan/nifty - 非常简单. (2认同)
  • 这是有效的,但它是很多工作的方式.另外:你失去了标准标题的一些功能,比如单击图标时突出显示...自定义标题不能用于重新创建标准标题布局而只是更改字体... (2认同)

Dig*_*git 150

int titleId = getResources().getIdentifier("action_bar_title", "id",
            "android");
    TextView yourTextView = (TextView) findViewById(titleId);
    yourTextView.setTextColor(getResources().getColor(R.color.black));
    yourTextView.setTypeface(face);
Run Code Online (Sandbox Code Playgroud)

  • 如果较新版本的Android开发人员将资源ID从"action_bar_title"更改为其他名称,那么这一切都无效.这就是为什么它没有被投票. (19认同)
  • @Digit:这对于"Holo Theme"非常有用,但不适用于"Material Theme"(android L).找到titleId,但textview为null ..任何想法如何解决这个问题?谢谢! (11认同)
  • 适用于api> 3.0但不适用于2.x for appcompat (6认同)
  • 为什么这个解决方案没有投了很多?????? 它的工作原理非常简单.谢谢Vazeer (3认同)
  • 这应该是问题的首选答案.效果很好,也有"action_bar_subtitle"!谢谢! (2认同)

Moh*_*tar 30

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>
    
    Run Code Online (Sandbox Code Playgroud)
  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"/>
    
    Run Code Online (Sandbox Code Playgroud)
  4. 享受自定义操作栏标题字体样式!

  • 这非常适合工具栏。有什么方法可以在应用程序范围内执行此操作,例如当您在新活动中使用默认应用程序栏时? (3认同)

tho*_*ers 13

书法库让我们通过你的应用程序的主题,这也将适用于操作栏设置自定义字体.

<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>
Run Code Online (Sandbox Code Playgroud)

激活书法所需要的只是将其附加到您的活动上下文:

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(new CalligraphyContextWrapper(newBase));
}
Run Code Online (Sandbox Code Playgroud)

默认的自定义属性是fontPath,但您可以通过在Application类中初始化它来为路径提供自己的自定义属性CalligraphyConfig.Builder.的使用android:fontFamily已经气馁.


Bos*_*one 11

这是一个丑陋的黑客,但你可以这样做(因为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");
    }
Run Code Online (Sandbox Code Playgroud)

此代码适用于GINGERBREAD后设备,但这可以很容易地扩展到与Actionbar Sherlock一起使用

PS基于@pjv评论有更好的方法来查找操作栏标题ID

final int titleId = 
    Resources.getSystem().getIdentifier("action_bar_title", "id", "android");
Run Code Online (Sandbox Code Playgroud)

  • 我更喜欢dtmilano在http://stackoverflow.com/questions/10779037/set-activity-title-ellipse-to-middle中的答案.这是类似但稍微更具未来的证据. (4认同)

Nap*_*ean 8

以下代码适用于所有版本.我用姜饼和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);
        }
    }
Run Code Online (Sandbox Code Playgroud)


Jin*_*inu 8

在支持库中使用新工具栏将您的操作栏设计为您自己的或使用下面的代码

膨胀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);
Run Code Online (Sandbox Code Playgroud)

复制到课堂下面

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);
    }

}
Run Code Online (Sandbox Code Playgroud)


kap*_*sid 5

    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);
Run Code Online (Sandbox Code Playgroud)