'How to display each clicked words from TextView

I am planned to develop an App with very simple concept.The requirement is I want to add a text file from phone(Dynamic, so set span with clickabble position not possible for spannable string) with help of intent chooser. And need to display the selected file content in textView (any view if u suggested). Once I clicked any of the word from textview content i need display that word in Toast.

    button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showFileChooser();
            }
        });



 private void showFileChooser() {

        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        //intent.setType("*/*");      //all files
        intent.setType("text/xml");   //XML file only
        intent.addCategory(Intent.CATEGORY_OPENABLE);

        try {
            startActivityForResult(Intent.createChooser(intent, "Select a File to Upload"), 1);
        } catch (android.content.ActivityNotFoundException ex) {
            // Potentially direct the user to the Market with a Dialog
            Toast.makeText(this, "Please install a File Manager.", Toast.LENGTH_SHORT).show();
        }
    }


 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == 1) {
            if (resultCode == RESULT_OK) {
                // User pick the file
                Uri uri = data.getData();
                ExternalFileHandling fileObj=new ExternalFileHandling(getApplicationContext());
                String fileContent = fileObj.readTextFile(uri);
                aboutTextView.setText(fileContent);
                Toast.makeText(this, fileContent, Toast.LENGTH_LONG).show();
            } else {
                Log.i("data", data.toString());
            }
        }``


public String readTextFile(Uri uri){
        BufferedReader reader = null;
        StringBuilder builder = new StringBuilder();
        try {
            reader = new BufferedReader(new InputStreamReader(Currentcontext.getContentResolver().openInputStream(uri)));
            String line = "";

            while ((line = reader.readLine()) != null) {
                builder.append(line);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return builder.toString();
    }

[![intent chooser for dynamic file content][1]][1]

clicked word marked in RED



Solution 1:[1]

Finally I got the Exact answer for my question

aboutTextView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                mOffset = aboutTextView.getOffsetForPosition(motionEvent.getX(), motionEvent.getY());
              //  mTxtOffset.setText("" + mOffset);
                Toast.makeText(HomeScreen.this, findWordForRightHanded(aboutTextView.getText().toString(), mOffset), Toast.LENGTH_SHORT).show();

            }
            return false;
        }
    });



private String findWordForRightHanded(String str, int offset) { // when you touch ' ', this method returns left word.
    if (str.length() == offset) {
        offset--; // without this code, you will get exception when touching end of the text
    }

    if (str.charAt(offset) == ' ') {
        offset--;
    }
    int startIndex = offset;
    int endIndex = offset;

    try {
        while (str.charAt(startIndex) != ' ' && str.charAt(startIndex) != '\n') {
            startIndex--;
        }
    } catch (StringIndexOutOfBoundsException e) {
        startIndex = 0;
    }

    try {
        while (str.charAt(endIndex) != ' ' && str.charAt(endIndex) != '\n') {
            endIndex++;
        }
    } catch (StringIndexOutOfBoundsException e) {
        endIndex = str.length();
    }

    // without this code, you will get 'here!' instead of 'here'
    // if you use only english, just check whether this is alphabet,
    // but 'I' use korean, so i use below algorithm to get clean word.
    char last = str.charAt(endIndex - 1);
    if (last == ',' || last == '.' ||
            last == '!' || last == '?' ||
            last == ':' || last == ';') {
        endIndex--;
    }

    return str.substring(startIndex, endIndex);
}

Solution 2:[2]

Here is one more implementation of this functionality

Implement a touch listener with a new class like WordsTouchListener

class WordsTouchListener(
    private val text: CharSequence,
    private val words: List<CharSequence>,
    private val onTargetClicked: (CharSequence) -> Unit,
    private val onTextClicked: () -> Unit
) : View.OnTouchListener {
    override fun onTouch(view: View, event: MotionEvent): Boolean {
        if (event.action == MotionEvent.ACTION_UP) {
            val offset = (view as? TextView)?.getOffsetForPosition(event.x, event.y) ?: 0
            // You could also add custom delimeters
            val target = text.extractWord(offset, ' ', '\n', '\t')
            if (target.containsOneOf(*words.toTypedArray())) {
                onTargetClicked(target)
            } else {
                onTextClicked()
            }
        }
        return true
    }
}

Extension functions below:

fun Char?.isOneOf(vararg symbols: Char) = symbols.any { this == it }

fun CharSequence.containsOneOf(vararg targets: CharSequence) = targets.any { contains(it) }

fun CharSequence.extractWord(index: Int, vararg delimiters: Char): String {
    var startIndex = index
    var endIndex = index
    while (!getOrNull(startIndex).isOneOf(*delimiters) && startIndex > 0) startIndex--
    while (!getOrNull(endIndex).isOneOf(*delimiters) && endIndex < length) endIndex++
    return substring(startIndex, endIndex).trim()
}

fun TextView.setWordsClickListener(
    words: List<CharSequence>,
    onTargetClicked: (CharSequence) -> Unit,
    onTextClicked: () -> Unit
) = setOnTouchListener(WordsTouchListener(text, words, onTargetClicked, onTextClicked))

So, now you can just call setWordsClickListener on TextView:

textView.setWordsClickListener(
    words = listOf("hello", "world"),
    onTargetClicked = {
        // Handle specific word clicks
    },
    onTextClicked = {
        // Handle text view clicks
    }
)

Solution 3:[3]

to prevent exception with previous answer you need to change 1st offset-- to offset=str.lenght()-1 in findWordForRightHanded I got myself offset much higher then str.lenght()

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ASKAR ALI
Solution 2 lincollincol
Solution 3 George