美文网首页
Toolbar的title使用自定义字体

Toolbar的title使用自定义字体

作者: 风雪守候 | 来源:发表于2018-02-28 11:41 被阅读108次

    ToolBar并没有提供类似于TextView的setTypeface()方法来修改字体。但是如果我们需要对ToolBar的title设置自定义的字体怎么办呢?
    1.不使用ToolBar控件,自己去实现一个titleBar。
    2.在ToolBar中放置一个TextView,使用该TextView来显示title
    3.使用SpannableString来设置title,在SpannableString中对title设置自定义的字体,下面详细介绍一下这种实现方式。
    通过了解发现SpannableString设置字体的方式如下:

    SpannableString string = new SpannableString("test");
    string.setSpan(new TypefaceSpan("monospace"),0,4,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    

    但是这种方法只支持系统的几种字体(如:monospace,serif等),如果需要设置自己想要的字体就需要自定义类了,首先对TypefaceSpan进行研究。

    /*
     * Copyright (C) 2006 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package android.text.style;
    
    import android.graphics.Paint;
    import android.graphics.Typeface;
    import android.os.Parcel;
    import android.text.ParcelableSpan;
    import android.text.TextPaint;
    import android.text.TextUtils;
    
    /**
     * Changes the typeface family of the text to which the span is attached.
     */
    public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan {
        private final String mFamily;
    
        /**
         * @param family The font family for this typeface.  Examples include
         * "monospace", "serif", and "sans-serif".
         */
        public TypefaceSpan(String family) {
            mFamily = family;
        }
    
        public TypefaceSpan(Parcel src) {
            mFamily = src.readString();
        }
        
        public int getSpanTypeId() {
            return getSpanTypeIdInternal();
        }
    
        /** @hide */
        public int getSpanTypeIdInternal() {
            return TextUtils.TYPEFACE_SPAN;
        }
        
        public int describeContents() {
            return 0;
        }
    
        public void writeToParcel(Parcel dest, int flags) {
            writeToParcelInternal(dest, flags);
        }
    
        /** @hide */
        public void writeToParcelInternal(Parcel dest, int flags) {
            dest.writeString(mFamily);
        }
    
        /**
         * Returns the font family name.
         */
        public String getFamily() {
            return mFamily;
        }
    
        @Override
        public void updateDrawState(TextPaint ds) {
            apply(ds, mFamily);
        }
    
        @Override
        public void updateMeasureState(TextPaint paint) {
            apply(paint, mFamily);
        }
        //设置字体的关键方法
        private static void apply(Paint paint, String family) {
            int oldStyle;
    
            Typeface old = paint.getTypeface();
            if (old == null) {
                oldStyle = 0;
            } else {
                oldStyle = old.getStyle();
            }
    
            Typeface tf = Typeface.create(family, oldStyle);
            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);
        }
    }
    

    通过源码发现TypefaceSpan是继承了MetricAffectingSpan类,然后在updateMeasureState和updateDrawState方法中调用了apply方法。
    在apply方法发现以下语句

    Typeface tf = Typeface.create(family, oldStyle);
    
           .....
    
    paint.setTypeface(tf);
    

    所以我们只要在apply方法中使用paint.setTypeface();即可。而且我们自定义的类中可以直接传入一个Typeface作为参数。
    实现代码如下:

    package com.cxample.test;
    
    import android.graphics.Paint;
    import android.graphics.Typeface;
    import android.text.TextPaint;
    import android.text.style.MetricAffectingSpan;
    
    public class TestTypefaceSpan extends MetricAffectingSpan {
    
        private final Typeface typeface;
    
        public TestTypefaceSpan(final Typeface typeface) {
            this.typeface = typeface;
        }
    
        @Override
        public void updateDrawState(final TextPaint drawState) {
            apply(drawState);
        }
    
        @Override
        public void updateMeasureState(final TextPaint paint) {
            apply(paint);
        }
    
        private void apply(final Paint paint) {
            final Typeface oldTypeface = paint.getTypeface();
            final int oldStyle = oldTypeface != null ? oldTypeface.getStyle() : 0;
            final int fakeStyle = oldStyle & ~typeface.getStyle();
            if ((fakeStyle & Typeface.BOLD) != 0) {
                paint.setFakeBoldText(true);
            }
            if ((fakeStyle & Typeface.ITALIC) != 0) {
                paint.setTextSkewX(-0.25f);
            }
            paint.setTypeface(typeface);
        }
    
    }
    

    然后和普通的TypefaceSpan使用相同,如:

    mToolbar.setTitle(getTitleSpannable(mTitleText));
    
    private SpannableString getTitleSpannable(String title) {
            SpannableString titleSpannable = new SpannableString(title);
            titleSpannable.setSpan(new TestTypefaceSpan(mTypeface), 0, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            return titleSpannable;
    }
    

    其中mTypeface是自己创建的字体类型,如:

    mTypeface = Typeface.createFromAsset(context.getAssets(), "BebasNeue.ttf");
    

    参考来源:https://www.cnblogs.com/dongweiq/p/4648085.html

    相关文章

      网友评论

          本文标题:Toolbar的title使用自定义字体

          本文链接:https://www.haomeiwen.com/subject/lndbxftx.html