Java 如何通过Spanable方法使用自定义字体设置所选文本的字体样式

Java 如何通过Spanable方法使用自定义字体设置所选文本的字体样式,java,android,android-edittext,spannable,Java,Android,Android Edittext,Spannable,我想使用自定义字体将样式设置为EditText中选定的文本。我在编译时遇到以下错误构造函数样式span(字体)未定义 下面是我申请的代码 int start=editbox.getSelectionStart(); int end=editbox.getSelectionEnd(); Spannable span=(Spannable)editbox.getText(); StyleSpan f = new StyleSpan( Type

我想使用自定义字体将样式设置为
EditText
中选定的文本。我在编译时遇到以下错误<代码>构造函数样式span(字体)未定义

下面是我申请的代码

int start=editbox.getSelectionStart();
int end=editbox.getSelectionEnd();
Spannable span=(Spannable)editbox.getText();
StyleSpan f = new StyleSpan( 
                            Typeface.createFromAsset(getAssets(),
                             "fonts/genbkbasr.ttf"));
span.setSpan(f, start,end, 0);

谢谢。

记录了此构造函数的可接受值


值应该是样式常量,如
字体。粗体

记录了此构造函数的可接受值


值应该是样式常量,比如
Typeface.BOLD

我写了一个类来解决这个限制。它似乎在有限的测试中工作,但我还没有编写我需要它的应用程序。请注意,它假定自定义字体作为资产可用,并进行静态调用以检索应用程序的上下文(它需要该上下文来访问资源)。更好的方法是将上下文传递给构造函数

import android.content.Context;

public class TypefaceResourceSpan extends MetricAffectingSpan implements ParcelableSpan {

private String resourceName_;
private Typeface tf_;

public TypefaceResourceSpan(String resourceName) {
    super();
    resourceName_=resourceName;
    tf_=createTypeface(resourceName_);
}

public TypefaceResourceSpan(Parcel src) {
    resourceName_ = src.readString();
    tf_=createTypeface(resourceName_);
}

private Typeface createTypeface(String resourceName) {
    Typeface result=null;
    Context c=TikunKorimMain.getAppContext();
    if (c==null) {
        Log.e("TypefaceResourceSpan", "Application context is null!");
    }
    AssetManager am=c.getAssets();
    if (am==null) {
        Log.e("TypefaceResourceSpan", "AssetManager is null!");
    }
    result=Typeface.createFromAsset(am, resourceName);
    return result;
}

public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(resourceName_);
}

@Override
public void updateMeasureState(TextPaint p) {
    Typeface old=p.getTypeface();
    if ( old != null && !old.isBold() && tf_.isBold() ) {
        p.setFakeBoldText(true);
    }
    if ( old != null && !old.isItalic() && tf_.isItalic() ) {
        p.setTextSkewX(-0.25f);
    }
    p.setTypeface(tf_);
}

@Override
public void updateDrawState(TextPaint tp) {
    Typeface old=tp.getTypeface();
    if ( old != null && !old.isBold() && tf_.isBold() ) {
        tp.setFakeBoldText(true);
    }
    if ( old != null && !old.isItalic() && tf_.isItalic() ) {
        tp.setTextSkewX(-0.25f);
    }
    tp.setTypeface(tf_);
}

public int getSpanTypeId() {
    // TODO does this work???!?
    return 123456;
}

public int describeContents() {
    return 0;
}
}

我写了一个类来解决这个限制。它似乎在有限的测试中工作,但我还没有编写我需要它的应用程序。请注意,它假定自定义字体作为资产可用,并进行静态调用以检索应用程序的上下文(它需要该上下文来访问资源)。更好的方法是将上下文传递给构造函数

import android.content.Context;

public class TypefaceResourceSpan extends MetricAffectingSpan implements ParcelableSpan {

private String resourceName_;
private Typeface tf_;

public TypefaceResourceSpan(String resourceName) {
    super();
    resourceName_=resourceName;
    tf_=createTypeface(resourceName_);
}

public TypefaceResourceSpan(Parcel src) {
    resourceName_ = src.readString();
    tf_=createTypeface(resourceName_);
}

private Typeface createTypeface(String resourceName) {
    Typeface result=null;
    Context c=TikunKorimMain.getAppContext();
    if (c==null) {
        Log.e("TypefaceResourceSpan", "Application context is null!");
    }
    AssetManager am=c.getAssets();
    if (am==null) {
        Log.e("TypefaceResourceSpan", "AssetManager is null!");
    }
    result=Typeface.createFromAsset(am, resourceName);
    return result;
}

public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(resourceName_);
}

@Override
public void updateMeasureState(TextPaint p) {
    Typeface old=p.getTypeface();
    if ( old != null && !old.isBold() && tf_.isBold() ) {
        p.setFakeBoldText(true);
    }
    if ( old != null && !old.isItalic() && tf_.isItalic() ) {
        p.setTextSkewX(-0.25f);
    }
    p.setTypeface(tf_);
}

@Override
public void updateDrawState(TextPaint tp) {
    Typeface old=tp.getTypeface();
    if ( old != null && !old.isBold() && tf_.isBold() ) {
        tp.setFakeBoldText(true);
    }
    if ( old != null && !old.isItalic() && tf_.isItalic() ) {
        tp.setTextSkewX(-0.25f);
    }
    tp.setTypeface(tf_);
}

public int getSpanTypeId() {
    // TODO does this work???!?
    return 123456;
}

public int describeContents() {
    return 0;
}
}


这意味着span只能与粗体斜体下划线一起使用?如果是这样,是否有其他方法可以从asset Folder更改edittext选定部分的字体?是的,StyleSpan不能更改文本单个部分的字体,它仅用于更改样式(粗体、斜体等)。TextView只能有一种字体。这意味着span只能与粗体斜体下划线一起使用?如果是这样,是否有其他方法可以从资源文件夹更改edittext选定部分的字体?是的,StyleSpan不能更改文本单个部分的字体,它仅用于更改样式(粗体、斜体等)。TextView只能有一种字体。您看过或吗?有人对此问题有答案吗?Alin-这些问题和答案不是使用资产文件夹中的自定义字体解决的。嗨,AamirKhan,请帮助我如何解决此问题。我尝试了选定的答案,但没有成功。@mukesh我接受了此答案,因为这是一个很好的答案,但很抱歉它对我也不起作用,我最终将字体样式应用于整个文本,而不是文本的选定部分,现在我不接受这个答案,谢谢。谢谢AamirKhan。有没有办法在字符串上设置字体,而不是textview或editview。你看过了吗?有人对这个问题有答案吗?Alin-这些问题和答案不是使用资产文件夹中的自定义字体解决的。嗨,AamirKhan,请帮助我如何解决此问题。我尝试了选定的答案,但没有成功。@mukesh我接受了此答案,因为这是一个很好的答案,但很抱歉它对我也不起作用,我最终将字体样式应用于整个文本,而不是文本的选定部分,现在我不接受这个答案,谢谢。谢谢AamirKhan。有没有办法在字符串上设置字体而不是textview或editview.Mr。shmuelp,请告诉我如何修改getSpanTypeId()方法,以便在editview.mukesh的选定文本上设置自定义字体,我不知道该方法的作用,但继承MetricAffectingSpan的其他类似乎提供了该方法。像我上面所做的那样返回占位符值似乎是可行的。你应该为你的字体实现一个缓存,特别是当你每次添加跨距时都要创建它们的时候。这里有一个实现:KMDev,感谢您的建议和实现!在概念验证中,我从未使用过上面的代码,但我希望很快能重新开始。shmuelp,请告诉我如何修改getSpanTypeId()方法,以便在editview.mukesh的选定文本上设置自定义字体,我不知道该方法的作用,但继承MetricAffectingSpan的其他类似乎提供了该方法。像我上面所做的那样返回占位符值似乎是可行的。你应该为你的字体实现一个缓存,特别是当你每次添加跨距时都要创建它们的时候。这里有一个实现:KMDev,感谢您的建议和实现!我从未在概念验证中使用过上面的代码,但我希望很快能回到这一工作中来。