Apply two different font styles to a TextView

2019-01-08 09:10发布

问题:

I want to apply two different font styles to a text in a single TextView.

My case is same as Android - two sentences, two styles, one TextView. The only difference is that I want to set a Custom Font on the whole text. I have included Helvetica Font as an assets in my project and want to apply that font to the TextView with first part of the text will be Helvetica BOLD and remaining part Helvetica NORMAL. Any suggestions how it can be done ?

Text needed in following format. Custom text with different styles and single textview.

回答1:

One way to do this is to extend TypefaceSpan:

import android.graphics.Paint;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.text.style.TypefaceSpan;

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

Then when you want to use two different typefaces call:

String firstWord = "first ";
String secondWord = "second";

// Create a new spannable with the two strings
Spannable spannable = new SpannableString(firstWord+secondWord);

// Set the custom typeface to span over a section of the spannable object
spannable.setSpan( new CustomTypefaceSpan("sans-serif",CUSTOM_TYPEFACE), 0, firstWord.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan( new CustomTypefaceSpan("sans-serif",SECOND_CUSTOM_TYPEFACE), firstWord.length(), firstWord.length() + secondWord.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

// Set the text of a textView with the spannable object
textView.setText( spannable );


回答2:

Here is a solution more straightforward, you can use HTML to set different styles on the same TextView.

For example:

// Styled label
String styledText = "<big><b><font color='#333333'>title</font></b></big> <small><b><font color='#CC5490'>subtitle</font></b></small>";

// Apply the styled label on the TextView
textView.setText(Html.fromHtml(styledText));

You need the following import:

import android.text.Html;


回答3:

This may work - create your own custom TextView and then use a StyleSpan on one part of it:

public class CustomTextView extends TextView {

    public CustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void setTypeface(Typeface tf, int style) {
        if (style == 1){
            //replace "HelveticaBOLD.otf" with the name of your bold font
            tf = Typeface.createFromAsset(getContext().getApplicationContext().getAssets(), "HelveticaBOLD.otf");
        }else{
            //replace "HelveticaNORMAL.otf" with the name of your normal font
            tf = Typeface.createFromAsset(getContext().getApplicationContext().getAssets(), "HelveticaNORMAL.otf");
        }
        super.setTypeface(tf, 0);
    }
}

And then you can do something like:

int index1 = 0; //wherever bold should begin
int index2 = 5; //wherever bold should end

Spannable span = new SpannableString("some string");
span.setSpan(new StyleSpan(Typeface.BOLD),index1, index2,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

((CustomTextView)findViewById(R.id.yourTextView)).setText(span);


回答4:

You can create a custom view and render your text with Two Paint objects using canvas.drawText method



回答5:

I use this approach

class FooClass {
    void Foo() {
        textViewSetText(R.id.photo_title, "Title: ", photo.getTitle());
        textViewSetText(R.id.photo_tags, "Tags: ", photo.getTags());
        textViewSetText(R.id.photo_author, "Author: ", photo.getAuthor());
    }

    private void textViewSetText(int resourceId, String prefix, String text) {
        TextView textView = (TextView) findViewById(resourceId);
        SpannableString styledText = new SpannableString(prefix);
        styledText.setSpan(new StyleSpan(Typeface.BOLD), 0, prefix.length(), 0);
        textView.setText(null);
        textView.append(styledText);
        textView.append(text);
    }
}

As you can see "Author", "Title" and "Tags" are set to BOLD

Screenshot http://image.prntscr.com/image/dd60bb4a335445c2adca8a4596d7fb32.png



回答6:

did you try setting a custom typeface on the TextView before applying spanable text ?

Typeface face = Typeface.createFromAsset(ctx.getAssets(), "fonts/boost.ttf")
TextView tv = (TextView) ctx.findViewById(id);
tv.setTypeface(face);

and then apply SpannableStringBuilder as from the linked question - I'm only assuming that if your ttf supports 'normal' and 'bold' it would render accordingly :)