首页 文章

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

提问于
浏览
241

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

16 回答

  • 2

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

    您可以使用自定义 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 类将传递您的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 方法中实现它,如上所示 .

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

    Android Support Library v26 + Android Studio 3.0 开始,这个过程变得简单轻松!

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

    • 阅读Downloadable Fonts并从列表中选择任何字体(我的推荐)或按照Fonts in XML将自定义字体加载到 res > font

    • 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>
    
    • 在工具栏属性 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"/>
    
    • 享受自定义操作栏 Headers 字体样式!!
  • 11

    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 在Application类中初始化它来为路径提供自己的自定义属性 . 不鼓励使用 android:fontFamily .

  • 8

    这是一个丑陋的黑客,但你可以这样做(因为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一起使用

    附:基于@pjv评论,有一种更好的方法来查找操作栏 Headers ID

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

    以下代码适用于所有版本 . 我确实用姜饼和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);
            }
        }
    
  • -1

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

    膨胀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);
        }
    
    }
    
  • 1

    我只是在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"中使用新添加的字体

  • 8

    如果要为整个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));
        }
    }
    
  • 15
    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);
    
  • 1

    要添加到@ 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)) - 但这是让我这么做的唯一方法 .

  • 3

    要更新正确答案 .

    首先:将 Headers 设置为false,因为我们使用的是自定义视图

    actionBar.setDisplayShowTitleEnabled(false);
    

    其次:创建titleview.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;
                }
            }
        }
    }
    
  • 416

    无需自定义textview!

    首先,在java代码中禁用toobar中的 Headers :getSupportActionBar() . setDisplayShowTitleEnabled(false);

    然后,只需在工具栏中添加TextView:

    <android.support.v7.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/app_name"
            android:textSize="18sp"
            android:fontFamily="@font/roboto" />
    
        </android.support.v7.widget.Toolbar>
    
  • 1

    我们需要使用反射来实现这一目标

    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) {
            }
        }
    
  • 0

    试试这个

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

相关问题