javaandroidtextviewunderlineandroid-spannable

how can i underline a text word by word?


how can i underline word by word in a sentence in android studio? so my program would be like this if i click a button the underline will start at first and when i click again the button it will move again to the next word.

for Example:

_The_ *** *** ***** **** *** **** ***.

so if i want to click the button the underline will move next to it word or 3 asterisk.

The _***_ *** ***** **** *** **** ***.

and click again to the next asterisk.

this is my code using for this:

public class MainActivity extends AppCompatActivity {

Button btn;
TextView txt;
int counter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    btn = findViewById(R.id.button);
    txt = findViewById(R.id.display);

    txt.setText("the red fox jumps over the lazy dog.");
    final String [] compare1 = txt.getText().toString().split("\\s");
    final String arr[] = txt.getText().toString().split(" ",2);
    final String fword = arr[0];
    String rword = arr[1];
    final String reprword = rword.replaceAll("[a-z]", "*");
    txt.setText(fword + " " + reprword);
    final String [] display = txt.getText().toString().split("\\s");
    /*final ArrayList<String> getters = new ArrayList<String>(Arrays.asList(display));*/

    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            if(counter <= display.length) {
                if(compare1[counter].length() == display[counter].length())
                {
                    txt.setText(formatText(fword + " " + reprword,display[counter]));
                }

                counter++;
            }
            else
            {


            }
        }
    });
}
public CharSequence formatText(String base, String highlight) {
    int start = base.indexOf(highlight);
    if (start >= 0) {
        SpannableString span = new SpannableString(base);
        span.setSpan(new UnderlineSpan(), start, start + highlight.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        return span;
    }
    return base;
}
}

I change the other half the sentence to test it for this.


Solution

  • base.indexOf(highlight) ==> indexOf() returns the first occurrence of highlight in base , thats why the underline span jumps to first "the" instead of the next occurrence. You can use indexOf(String str, int fromIndex). The following code tracks the "fromIndex" in this variable "nextStartIndex", and also underlining resets to first word after completing the sentence.

    public class UnderlineWordsActivity extends AppCompatActivity {
    
        private Button btn;
        private TextView txt;
        private int counter=0;
        private int nextStartIndex=0;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            btn = findViewById(R.id.button);
            txt = findViewById(R.id.display);
            txt.setText("the red fox jumps over the lazy dog.");
    
            final String[] arr = txt.getText().toString().split(" ", 2);
            final String firstWord = arr[0];
            String remainingWords = arr[1];
            final String reprword = remainingWords.replaceAll("[a-z]", "*");
            String text = firstWord+" "+reprword;
            txt.setText(text);
    
            final String[] display = txt.getText().toString().split("\\s");
    
    
           btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (counter >= display.length) {
                        counter = 0;
                        nextStartIndex = 0;
                    }
                    txt.setText(formatText(text, display[counter]));
                    counter++;
                }
            });
        }
    
        public CharSequence formatText(String base, String highlight) {
            int start = base.indexOf(highlight,nextStartIndex);
            nextStartIndex = start+highlight.length();
            if (start >= 0) {
                SpannableString span = new SpannableString(base);
                span.setSpan(new UnderlineSpan(), start, nextStartIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                return span;
            }
            return base;
        }
    }