Natalie
Natalie

Reputation: 163

StyleSpan is not applied on SpannableString in TextView

I want to make specific substring's font BOLD.

Here is my code:

 String fullName = "some name";
 String searchFreeText = "some";
 SpannableString wordToSpan = new SpannableString(fullName);

Typeface helvticaBoldTypeface = Typeface.createFromAsset(context.getAssets(), FONT_HELVETICA_BOLD);
int startPosition = fullName.toLowerCase().indexOf(searchFreeText.toLowerCase());
StyleSpan bold = new StyleSpan(helvticaBoldTypeface.getStyle());
                    wordToSpan.setSpan(bold, startPosition, startPosition + searchFreeText.length(), 0);
 firstLineTextView.setText(wordToSpan, BufferType.SPANNABLE);

The text remains not bold. If I change the code to:

firstLineTextView.setTypeface(helvticaBoldTypeface, Typeface.BOLD);

and remove

 StyleSpan bold = new StyleSpan(helvticaBoldTypeface.getStyle());
                    wordToSpan.setSpan(bold, startPosition, startPosition + searchFreeText.length(), 0);

then all the text is bold, and that's ok, but not what i want. I need to make bold only specific text. I expect to see this: some name.

What is the problem? Thanks

Upvotes: 4

Views: 3244

Answers (2)

Harsh Sharma
Harsh Sharma

Reputation: 898

I noticed one thing: You are using FONT_HELVETICA_BOLD (Which is already bold so nothing special gonna happen to your text cuz it is already bold just change it to some regular font)

You can find some fonts here

For making specific text bold and colored you can try the following code

SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(textToBeSpannedWithBold);

StyleSpan styleSpan = new StyleSpan(android.graphics.Typeface.BOLD);

spannableStringBuilder.setSpan(styleSpan,
        positionOfSearchedText,
        positionOfSearchedText + searchTextToBeBold.length(),
        Spannable.SPAN_INCLUSIVE_INCLUSIVE);

//Use this if you wanna make specific text bold
SpannableString uncolouredSpan = new SpannableString(spannableStringBuilder);
textViewToBeBoldSpanned.setText(uncolouredSpan);

//Use this if you wanna make specific text bold plus coloured
SpannableString coloredSpan = giveMeColoredSpan(
        new SpannableString(spannableStringBuilder),
        ContextCompat.getColor(getContext(), R.color.your_specific_colour));

textViewToBeBoldSpannedAndColoured.setText(coloredSpan);


public static SpannableString giveMeColoredSpan(SpannableString spannableString, int color) {
    spannableString.setSpan(
            new ForegroundColorSpan(color), 0, spannableString.length(), 0);
    return spannableString;
}

If Still somehow you are stuck with your problem for that i have created a repo on Github https://github.com/harsh159357/customtextview

Activity Code From My Repo

CustomTextViewActivity.java

import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.view.View;
import android.widget.Button;
public class CustomTextViewActivity extends AppCompatActivity implements View.OnClickListener {
    public static final String MAKE_THIS_SPECIFIC_PART_COLORED = "MakeThisSpecificPartColored";
    public static final String MAKE_THIS_SPECIFIC_PART_BOLD = "MakeThisSpecificPartBold";
    public static final String MAKE_THIS_SPECIFIC_PART_BOLD_AND_COLORED = "MakeThisSpecificPartBoldAndColored";
    CustomTextView customTextView1,
            customTextView2,
            customTextView3;
    Button changeToRoboto,
            changeToCalculus,
            makeSpecificTextColored,
            makeSpecificTextBold,
            makeSpecificTextBoldAndColored;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_text_view);
        customTextView1 = (CustomTextView) findViewById(R.id.customTextView1);
        customTextView2 = (CustomTextView) findViewById(R.id.customTextView2);
        customTextView3 = (CustomTextView) findViewById(R.id.customTextView3);
        changeToRoboto = (Button) findViewById(R.id.change_to_roboto);
        changeToCalculus = (Button) findViewById(R.id.change_to_calculus);
        makeSpecificTextBold = (Button) findViewById(R.id.make_specific_text_bold);
        makeSpecificTextColored = (Button) findViewById(R.id.make_text_colored);
        makeSpecificTextBoldAndColored = (Button) findViewById(R.id.make_text_bold_and_colored);
        changeToRoboto.setOnClickListener(this);
        changeToCalculus.setOnClickListener(this);
        makeSpecificTextColored.setOnClickListener(this);
        makeSpecificTextBold.setOnClickListener(this);
        makeSpecificTextBoldAndColored.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.change_to_roboto:
                customTextView1.setFont(getString(R.string.font_roboto_regular));
                customTextView2.setFont(getString(R.string.font_roboto_regular));
                customTextView3.setFont(getString(R.string.font_roboto_regular));
                break;
            case R.id.change_to_calculus:
                customTextView1.setFont(getString(R.string.font_calculus_sans));
                customTextView2.setFont(getString(R.string.font_calculus_sans));
                customTextView3.setFont(getString(R.string.font_calculus_sans));
                break;
            case R.id.make_text_colored:
                makeTextColoured();
                break;
            case R.id.make_specific_text_bold:
                makeSpecificTextBold();
                break;
            case R.id.make_text_bold_and_colored:
                makeTextBoldAndColored();
                break;
        }
    }
    public static SpannableString giveMeColoredSpan(SpannableString spannableString, int color) {
        spannableString.setSpan(
                new ForegroundColorSpan(color), 0, spannableString.length(), 0);
        return spannableString;
    }
    private void makeTextColoured() {
        String textToBeSpanned = customTextView1.getText().toString();
        SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(textToBeSpanned);
        int positionOfSearchedText = textToBeSpanned.indexOf(MAKE_THIS_SPECIFIC_PART_COLORED);
        SpannableString coloredSpan = giveMeColoredSpan(
                new SpannableString(textToBeSpanned),
                ContextCompat.getColor(getApplicationContext(), android.R.color.holo_red_dark));
        customTextView1.setText(coloredSpan);
    }
    private void makeSpecificTextBold() {
        String textToBeSpanned = customTextView2.getText().toString();
        SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(textToBeSpanned);
        int positionOfSearchedText = textToBeSpanned.indexOf(MAKE_THIS_SPECIFIC_PART_BOLD);
        StyleSpan styleSpan = new StyleSpan(android.graphics.Typeface.BOLD);
        spannableStringBuilder.setSpan(styleSpan,
                positionOfSearchedText,
                positionOfSearchedText + MAKE_THIS_SPECIFIC_PART_BOLD.length(),
                Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        customTextView2.setText(spannableStringBuilder);
    }
    private void makeTextBoldAndColored() {
        String textToBeSpanned = customTextView3.getText().toString();
        SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(textToBeSpanned);
        int positionOfSearchedText = textToBeSpanned.indexOf(MAKE_THIS_SPECIFIC_PART_BOLD_AND_COLORED);
        StyleSpan styleSpan = new StyleSpan(android.graphics.Typeface.BOLD);
        spannableStringBuilder.setSpan(styleSpan,
                positionOfSearchedText,
                positionOfSearchedText + MAKE_THIS_SPECIFIC_PART_BOLD_AND_COLORED.length(),
                Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        SpannableString coloredBoldSpan = giveMeColoredSpan(
                new SpannableString(spannableStringBuilder),
                ContextCompat.getColor(getApplicationContext(), android.R.color.holo_red_dark));
        customTextView3.setText(coloredBoldSpan);
    }
}

actvity_text_view.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="vertical"
        tools:context="com.harsh.customtextview.CustomTextViewActivity">

        <com.harsh.customtextview.CustomTextView
            android:id="@+id/customTextView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:gravity="center"
            android:text="@string/roboto_regular"
            android:textColor="@color/colorPrimary"
            android:textSize="18sp"
            app:font="@string/font_roboto_regular" />

        <com.harsh.customtextview.CustomTextView
            android:id="@+id/customTextView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:gravity="center"
            android:text="@string/themed_text"
            android:textColor="@color/colorPrimary"
            android:textSize="18sp"
            app:theme="@style/roboto_theme" />

        <com.harsh.customtextview.CustomTextView
            android:id="@+id/customTextView3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:gravity="center"
            android:text="@string/calculus_sans"
            android:textColor="@color/colorPrimary"
            android:textSize="18sp"
            app:font="@string/font_calculus_sans" />


        <Button
            android:id="@+id/change_to_roboto"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Change to Roboto" />

        <Button
            android:id="@+id/change_to_calculus"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Change to Calculus" />

        <Button
            android:id="@+id/make_text_colored"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Make text coloured" />

        <Button
            android:id="@+id/make_specific_text_bold"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Make specific text bold" />

        <Button
            android:id="@+id/make_text_bold_and_colored"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="Make text bold and colored" />

    </LinearLayout>
</ScrollView>

Upvotes: 1

Natalie
Natalie

Reputation: 163

So I solved this issue. 2 parts that solved it: setting the textview to empty string before applying style changes (firstLineTextView.setText("");) and using firstLineTextView.append(wordToSpan); instead of firstLineTextView.setText(wordToSpan)

Here is the code:

String fullName = "some name";
String searchFreeText = "some";
int startPosition = fullName.toLowerCase().indexOf(searchFreeText.toLowerCase());
SpannableString wordToSpan = new SpannableString(fullName);
firstLineTextView.setText("");
                    wordToSpan.setSpan(new StyleSpan(Typeface.BOLD), startPosition, startPosition + searchFreeText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    firstLineTextView.append(wordToSpan);

Upvotes: 0

Related Questions