如何从 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
}
)
我计划开发一个非常简单的应用程序 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
}
)