How to Convert Text to Clickable Words in Android

How to Convert Text to Clickable Words in Android

Hello everyone, in this article we are going to talk about Clickable Span in android with Java. We will talk about how can we make an entire text to the clickable words. When we click words we will fire another method.

Let's get started.

I will use a Textview to show the text and I will use the clickableSpan class to seperate the text word by word. I also use Link MovementMethod to prevent frezeng on scrolling. Below you will see the all libraries to import. First import them to the java page.


import android.widget.TextView;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.method.LinkMovementMethod;
import android.text.method.ScrollingMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;

And then I will initialize my activity body and my text view.


public class ReadActivity extends AppCompatActivity  {

    TextView lblContent ;
    String content = "";

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

        //Initialize the textview
        lblContent = (TextView)findViewById(R.id.lblContent);

        //Load the text which be spanned and being clickable.
        content = "This text will be clackable span text.";
        lblContent.setText(content); 
    }

}

Now I need a method to make this textview and its content as clickable.

What will we do with below function : First we trim the text and remove the spaces at start and end. And then set the textview movement method to prevent frezing And we set the text as SPANNABLE text. After we get the spans of the text with iterator and we initialized the iterator ant we get all possible words by iterators.


    private void initSelectebleWord(String entireContent) {
        //First we trim the text and remove the spaces at start and end.
        String definition = entireContent.trim();
        //And then  set the textview movement method to prevent frezing
        //And we set the text as SPANNABLE text.
        TextView definitionView = (TextView) findViewById(R.id.lblContent);
        definitionView.setMovementMethod(LinkMovementMethod.getInstance());
        definitionView.setText(definition, TextView.BufferType.SPANNABLE);
        //After we get the spans of the text with iterator and we initialized the iterator
        Spannable spans = (Spannable) definitionView.getText();
        BreakIterator iterator = BreakIterator.getWordInstance(Locale.US);
        iterator.setText(definition);
        int start = iterator.first();

        //Here we get all possible words by iterators
        for (int end = iterator.next(); end != BreakIterator.DONE; start = end, end = iterator.next()) {
            String possibleWord = definition.substring(start, end);
            if (Character.isLetterOrDigit(possibleWord.charAt(0))) {
                ClickableSpan clickSpan = getClickableSpan(possibleWord);
                spans.setSpan(clickSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
    }

Here I need to explain two things. First what is LinkMovementMethodOverride class and then getClickableSpan methods. Below Code block I will explain them one by one. Let's start with LinkMovementMethodOverride.

What will we do with the below code block.

First we get the initizlized text view and its content And the control it if a Spanned. If it is a spanned text we get the text and motion event. This will decide the movement direction: UP or DOWN. After We set the new position to show. We moved the lines. And we initiazlized the clickable spans again for all spanned words and assign onclick method of the ClickableSpan class for each word.


    public class LinkMovementMethodOverride implements View.OnTouchListener{

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            //First we get the initizlized text view and its content
            TextView widget = (TextView) v;
            Object text = widget.getText();
            //And the control it if a Spanned.
            if (text instanceof Spanned) {
                //If it is a spanned text we get the text and motion event. This will decide the movement direction: UP or DOWN.
                Spanned buffer = (Spanned) text;
                int action = event.getAction();
                if (action == MotionEvent.ACTION_UP
                        || action == MotionEvent.ACTION_DOWN) {
                    //We set the new position to show. We moved the lines.
                    int x = (int) event.getX();
                    int y = (int) event.getY();

                    x -= widget.getTotalPaddingLeft();
                    y -= widget.getTotalPaddingTop();

                    x += widget.getScrollX();
                    y += widget.getScrollY();

                    Layout layout = widget.getLayout();
                    int line = layout.getLineForVertical(y);
                    int off = layout.getOffsetForHorizontal(line, x);
                    //And we initiazlized the clickable spans again for all spanned words
                    ClickableSpan[] link = buffer.getSpans(off, off,
                            ClickableSpan.class);
                    // and assign onclick method of the ClickableSpan class for each word.
                    if (link.length != 0) {
                        if (action == MotionEvent.ACTION_UP) {
                            link[0].onClick(widget);
                        } else if (action == MotionEvent.ACTION_DOWN) {
                            
                        }
                        return true;
                    }
                }
            }
            return false;
        }
    }
And below my clickable span class is:

    private ClickableSpan getClickableSpan(final String word) {
        return new ClickableSpan() {
            final String mWord;
            {
                mWord = word;
            }

            @Override
            public void onClick(View widget) {
                Log.d("Clicked word is : ", mWord); 
                //Here you can do whatever you want with this word.
               //I have made a translation with this and show my users.
        };
    }

And last we will set the textviews on movement as LinkMovementMethodOverride onCreate().


public class ReadActivity extends AppCompatActivity  {

    TextView lblContent ;
    String content = "";

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

        //Initialize the textview
        lblContent = (TextView)findViewById(R.id.lblContent);

        //Load the text which be spanned and being clickable.
        content = "This text will be clackable span text.";
        lblContent.setText(content); 
        initSelectebleWord(content);
        lblContent.setOnTouchListener(new LinkMovementMethodOverride());

    }
}

You can reach the example file via https://github.com/thecodeprogram/TheSingleFiles/blob/master/Clicakblespan_Example.java

And you can reach the Android application which I use this method from here : https://play.google.com/store/apps/details?id=com.thecodeprogram.readalot

That is all in this article.

Have great clicking on spans.

I wish you all healthy days.

Burak Hamdi TUFAN.


Tags


Share this Post

Send with Whatsapp

Post a Comment

Success! Your comment sent to post. It will be showed after confirmation.
Error! There was an error sending your comment.

Comments

    There is no comment. Be the owner of first comment...