如何从 TextView 显示每个点击的单词

How to display each clicked words from TextView

我计划开发一个非常简单的应用程序 concept.The 要求是我想从 phone(Dynamic 添加一个文本文件,所以设置 span 与 clickabble 位置不是在意图选择器的帮助下,可跨越字符串 ) 是可能的。并且需要在 textView 中显示选定的文件内容(如果你建议的话,任何视图)。 单击 textview 内容中的任何单词后,我需要在 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]

我终于得到了我的问题的准确答案

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

为了防止先前答案出现异常,您需要在 findWordForRightHanded 中将第一个偏移量--更改为 offset=str.lenght()-1 我让自己的偏移量比 str.lenght()

高得多

这是此功能的另一种实现方式

使用新的 class 实现触摸侦听器,例如 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
    }
}

以下扩展函数:

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

所以,现在您只需在 TextView 上调用 setWordsClickListener:

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