安卓字体样式设置java.lang.NoSuchMethodErrorNo direct method <init>(Landroid/graphics/Typeface;)

正常设置字体样式如下:

SpannableString sStr = new SpannableString("这个是设置字体样式的")
sStr.setSpan(new TypefaceSpan("default"), 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
sStr.setSpan(new TypefaceSpan("default-bold"), 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
		sStr.setSpan(new TypefaceSpan("monospace"), 4, 6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

在TypefaceSpan源码中(如下)
public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan {

    @Nullable
    private final String mFamily;

    @Nullable
    private final Typeface mTypeface;

    /**
     * Constructs a {@link TypefaceSpan} based on the font family. The previous style of the
     * TextPaint is kept. If the font family is null, the text paint is not modified.
     *
     * @param family The font family for this typeface.  Examples include
     *               "monospace", "serif", and "sans-serif"
     */
    public TypefaceSpan(@Nullable String family) {
        this(family, null);
    }

    /**
     * Constructs a {@link TypefaceSpan} from a {@link Typeface}. The previous style of the
     * TextPaint is overridden and the style of the typeface is used.
     *
     * @param typeface the typeface
     */
    public TypefaceSpan(@NonNull Typeface typeface) {
        this(null, typeface);
    }

    /**
     * Constructs a {@link TypefaceSpan} from a  parcel.
     */
    public TypefaceSpan(@NonNull Parcel src) {
        mFamily = src.readString();
        mTypeface = LeakyTypefaceStorage.readTypefaceFromParcel(src);
    }

    private TypefaceSpan(@Nullable String family, @Nullable Typeface typeface) {
        mFamily = family;
        mTypeface = typeface;
    }

    @Override
    public int getSpanTypeId() {
        return getSpanTypeIdInternal();
    }

    /** @hide */
    @Override
    public int getSpanTypeIdInternal() {
        return TextUtils.TYPEFACE_SPAN;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        writeToParcelInternal(dest, flags);
    }

    /** @hide */
    @Override
    public void writeToParcelInternal(@NonNull Parcel dest, int flags) {
        dest.writeString(mFamily);
        LeakyTypefaceStorage.writeTypefaceToParcel(mTypeface, dest);
    }

    /**
     * Returns the font family name set in the span.
     *
     * @return the font family name
     * @see #TypefaceSpan(String)
     */
    @Nullable
    public String getFamily() {
        return mFamily;
    }

    /**
     * Returns the typeface set in the span.
     *
     * @return the typeface set
     * @see #TypefaceSpan(Typeface)
     */
    @Nullable
    public Typeface getTypeface() {
        return mTypeface;
    }

    @Override
    public void updateDrawState(@NonNull TextPaint ds) {
        updateTypeface(ds);
    }

    @Override
    public void updateMeasureState(@NonNull TextPaint paint) {
        updateTypeface(paint);
    }

    private void updateTypeface(@NonNull Paint paint) {
        if (mTypeface != null) {
            paint.setTypeface(mTypeface);
        } else if (mFamily != null) {
            applyFontFamily(paint, mFamily);
        }
    }

    private void applyFontFamily(@NonNull Paint paint, @NonNull String family) {
        int style;
        Typeface old = paint.getTypeface();
        if (old == null) {
            style = Typeface.NORMAL;
        } else {
            style = old.getStyle();
        }
        final Typeface styledTypeface = Typeface.create(family, style);
        int fake = style & ~styledTypeface.getStyle();

        if ((fake & Typeface.BOLD) != 0) {
            paint.setFakeBoldText(true);
        }

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

构造函数中参数可以传String family和Typeface typeface  family相当于如上的default ,default-default-bold 等 而typeface可以设置自定义下载的字体,比如
  Typeface tf = Typeface.createFromAsset(getAssets(), "test字体.ttf");
  sStr.setSpan(new TypefaceSpan("tf"), 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
在实际开发项目中如上设置 new TypefaceSpan("tf") 字体样式时,在Android 9.0以下时会如下报错
java.lang.NoSuchMethodError
No direct method <init>(Landroid/graphics/Typeface;)V in class Landroid/text/style/TypefaceSpan; 
or its super classes (declaration of 'android.text.style.TypefaceSpan' appears in /system/framework/framework.jar!classes2.dex)
提示framework.jar 中没有发现直接调用new TypefaceSpan("tf") 这个方法。需要自定义CustomTypefaceSpan :如下
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) {
        setCustomTypeFace(ds, newType);
    }

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

    private void setCustomTypeFace(Paint paint, Typeface tf) {
        if (tf == null || paint == null)return;
        paint.setTypeface(tf);
    }
}

设置字体样式改成如下:
  Typeface tf = Typeface.createFromAsset(getAssets(), "test字体.ttf");
  sStr.setSpan(new CustomTypefaceSpan("tf"), 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

通过不同的安卓版本测试 未报如上错误日志;

 当前问题基于应用内遇到的处理方法,以上方式如果存在缺陷或者兼容性问题,欢迎一起讨论并完善。谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值