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

我可以如何(如果可能)在我的资产文件夹中设置一个自定义字体在一个ActionBar标题文本(只有 – 不是标签文本)与一个字体? 我不想使用android:logo选项。

我同意这不是完全支持,但这是我做的。 您可以使用自定义视图作为您的操作栏(它将显示在您的图标和您的操作项目之间)。 我正在使用自定义视图,并禁用了原生标题。 我所有的活动都是从一个活动inheritance而来的,这个活动在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> 

您可以使用自定义的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); 

自定义的TypefaceSpan类将在您的assets/fonts目录中传递您的活动上下文和字体的名称。 它加载文件并在内存中caching一个新的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方法中实现它,如上所示。

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

书法库允许您通过应用程序主题设置自定义字体,这也适用于操作栏。

 <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 ,但是您可以通过在您的Application类中使用CalligraphyConfig.Builder初始化它来为path提供自己的自定义属性。 android:fontFamily已经被阻止了。

这是一个丑陋的黑客,但你可以这样做(因为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设备,但是这可以很容易地扩展到与操作栏Sherlock一起工作

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

 final int titleId = Resources.getSystem().getIdentifier("action_bar_title", "id", "android"); 

以下代码将适用于所有版本。 我在一个装有姜饼和软糖装置的设备上检查过

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

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

充气Textview不是一个好的select尝试Spannablestring生成器

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

如果你想在整个Activity中为所有的TextView设置字体,你可以使用下面的代码:

 public static void setTypefaceToAll(Activity activity) { View view = activity.findViewById(android.R.id.content).getRootView(); setTypefaceToAll(view); } public static void setTypefaceToAll(View view) { if (view instanceof ViewGroup) { ViewGroup g = (ViewGroup) view; int count = g.getChildCount(); for (int i = 0; i < count; i++) setTypefaceToAll(g.getChildAt(i)); } else if (view instanceof TextView) { TextView tv = (TextView) view; setTypeface(tv); } } public static void setTypeface(TextView tv) { TypefaceCache.setFont(tv, TypefaceCache.FONT_KOODAK); } 

和TypefaceCache:

 import java.util.TreeMap; import android.graphics.Typeface; import android.widget.TextView; public class TypefaceCache { //Font names from asset: public static final String FONT_ROBOTO_REGULAR = "fonts/Roboto-Regular.ttf"; public static final String FONT_KOODAK = "fonts/Koodak.ttf"; private static TreeMap<String, Typeface> fontCache = new TreeMap<String, Typeface>(); public static Typeface getFont(String fontName) { Typeface tf = fontCache.get(fontName); if(tf == null) { try { tf = Typeface.createFromAsset(MyApplication.getAppContext().getAssets(), fontName); } catch (Exception e) { return null; } fontCache.put(fontName, tf); } return tf; } public static void setFont(TextView tv, String fontName) { tv.setTypeface(getFont(fontName)); } } 

要添加到@ Sam_D的答案,我必须这样做,使其工作:

 this.setTitle("my title!"); ((TextView)v.findViewById(R.id.title)).setText(this.getTitle()); TextView title = ((TextView)v.findViewById(R.id.title)); title.setEllipsize(TextUtils.TruncateAt.MARQUEE); title.setMarqueeRepeatLimit(1); // in order to start strolling, it has to be focusable and focused title.setFocusable(true); title.setSingleLine(true); title.setFocusableInTouchMode(true); title.requestFocus(); 

这似乎是矫枉过正 – 引用v.findViewById(R.id.title))两次 – 但这是它让我这样做的唯一方法。

更新正确的答案。

首先:将标题设置为false,因为我们正在使用自定义视图

  actionBar.setDisplayShowTitleEnabled(false); 

其次:创buildtitleview.xml

 <?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" > <TextView 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> 

最后 :

 //font file must be in the phone db so you have to create download file code //check the code on the bottom part of the download file code. TypeFace font = Typeface.createFromFile("/storage/emulated/0/Android/data/" + BuildConfig.APPLICATION_ID + "/files/" + "font name" + ".ttf"); if(font != null) { LayoutInflater inflator = LayoutInflater.from(this); View v = inflator.inflate(R.layout.titleview, null); TextView titleTv = ((TextView) v.findViewById(R.id.title)); titleTv.setText(title); titleTv.setTypeface(font); actionBar.setCustomView(v); } else { actionBar.setDisplayShowTitleEnabled(true); actionBar.setTitle(" " + title); // Need to add a title } 

下载字体文件:因为我将文件存储到cloudinary,所以我有链接下载它。

 /**downloadFile*/ public void downloadFile(){ String DownloadUrl = //url here File file = new File("/storage/emulated/0/Android/data/" + BuildConfig.APPLICATION_ID + "/files/"); File[] list = file.listFiles(); if(list == null || list.length <= 0) { BroadcastReceiver onComplete = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { try{ showContentFragment(false); } catch (Exception e){ } } }; registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); DownloadManager.Request request = new DownloadManager.Request(Uri.parse(DownloadUrl)); request.setVisibleInDownloadsUi(false); request.setDestinationInExternalFilesDir(this, null, ModelManager.getInstance().getCurrentApp().getRegular_font_name() + ".ttf"); DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); manager.enqueue(request); } else { for (File files : list) { if (!files.getName().equals("font_name" + ".ttf")) { BroadcastReceiver onComplete = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { try{ showContentFragment(false); } catch (Exception e){ } } }; registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); DownloadManager.Request request = new DownloadManager.Request(Uri.parse(DownloadUrl)); request.setVisibleInDownloadsUi(false); request.setDestinationInExternalFilesDir(this, null, "font_name" + ".ttf"); DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); manager.enqueue(request); } else { showContentFragment(false); break; } } } } 

我只是在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”

我们需要使用reflection来实现这一点

 final int titleId = activity.getResources().getIdentifier("action_bar_title", "id", "android"); final TextView title; if (activity.findViewById(titleId) != null) { title = (TextView) activity.findViewById(titleId); title.setTextColor(Color.BLACK); title.setTextColor(configs().getColor(ColorKey.GENERAL_TEXT)); title.setTypeface(configs().getTypeface()); } else { try { Field f = bar.getClass().getDeclaredField("mTitleTextView"); f.setAccessible(true); title = (TextView) f.get(bar); title.setTextColor(Color.BLACK); title.setTypeface(configs().getTypeface()); } catch (NoSuchFieldException e) { } catch (IllegalAccessException e) { } } 

Android支持库v26 + Android Studio 3.0起,这个过程变得轻而易举!

请按照以下步骤更改工具栏标题的字体:

  1. 阅读可下载的字体,并从列表中select任何字体( 我的build议 )或加载一个自定义字体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"插入一个新行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. 享受自定义Actionbar标题字体造型!

尝试这个

 public void findAndSetFont(){ getActionBar().setTitle("SOME TEST TEXT"); scanForTextViewWithText(this,"SOME TEST TEXT",new SearchTextViewInterface(){ @Override public void found(TextView title) { } }); } public static void scanForTextViewWithText(Activity activity,String searchText, SearchTextViewInterface searchTextViewInterface){ if(activity == null|| searchText == null || searchTextViewInterface == null) return; View view = activity.findViewById(android.R.id.content).getRootView(); searchForTextViewWithTitle(view, searchText, searchTextViewInterface); } private static void searchForTextViewWithTitle(View view, String searchText, SearchTextViewInterface searchTextViewInterface) { if (view instanceof ViewGroup) { ViewGroup g = (ViewGroup) view; int count = g.getChildCount(); for (int i = 0; i < count; i++) searchForTextViewWithTitle(g.getChildAt(i), searchText, searchTextViewInterface); } else if (view instanceof TextView) { TextView textView = (TextView) view; if(textView.getText().toString().equals(searchText)) if(searchTextViewInterface!=null) searchTextViewInterface.found(textView); } } public interface SearchTextViewInterface { void found(TextView title); }