Android 英文文章选词
点击文章中的一个单词,获取它。
通过点击的坐标y来获取行数,通过x坐标获取字符偏移量,向前遍历匹配,向后遍历匹配,匹配不成功则跳出循环。截取开始位置和最后位置的字符串。
主要代码
public String getSelectText(int currOff) {
int leftOff = currOff, rigthOff = currOff;
int length = getText().toString().length();
while (true) { //左移currOff
if (leftOff <= 0) {
break;
}
if (leftOff != 0) {
leftOff = leftOff - 1;
if (leftOff < 0) {
leftOff = 0;
}
}
String selectText = getText().subSequence(leftOff, currOff).toString();
if (!selectText.matches("^[()._0-9a-zA-Z'-]*")) {
leftOff += 1;
break;
}
}
while (true) { //右移currOff
if (rigthOff >= length) {
break;
}
if (rigthOff != 0) {
rigthOff = rigthOff + 1;
if (rigthOff > length) {
rigthOff = length;
}
}
String selectText = getText().subSequence(currOff, rigthOff).toString();
if (!selectText.matches("^[()_0-9a-zA-Z'-]*")) {
rigthOff -= 1;
break;
}
}
String endString = "";
try {
endString = getText().subSequence(leftOff, rigthOff).toString();
if (!endString.trim().isEmpty()) {
Selection.setSelection((Spannable) getText(), leftOff, rigthOff);//选中
Log.d("WordTextView", "setSelection");
} else {
Log.d("WordTextView", endString);
}
} catch (Exception e) {
e.printStackTrace();
}
return endString.trim();
}
全部代码
主要控件
public class WordTextView extends androidx.appcompat.widget.AppCompatTextView {
private Callback callback;
public WordTextView(Context context) {
super(context);
}
public WordTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public WordTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public Callback getCallback() {
return callback;
}
public void setCallback(Callback callback) {
this.callback = callback;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
Layout layout = getLayout();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Selection.removeSelection(getEditableText());
break;
case MotionEvent.ACTION_HOVER_MOVE:
break;
case MotionEvent.ACTION_UP:
int line = layout.getLineForVertical((int) event.getY());
int off = layout.getOffsetForHorizontal(line, (int) event.getX());
String selectText = getSelectText(off);
if (selectText != null && callback != null) {
callback.getWord(selectText);
}
Log.d("WordTextView1", off + "," + selectText);
break;
}
return true;
}
public String getSelectText(int currOff) {
int leftOff = currOff, rigthOff = currOff;
int length = getText().toString().length();
while (true) { //左移currOff
if (leftOff <= 0) {
break;
}
if (leftOff != 0) {
leftOff = leftOff - 1;
if (leftOff < 0) {
leftOff = 0;
}
}
String selectText = getText().subSequence(leftOff, currOff).toString();
if (!selectText.matches("^[()._0-9a-zA-Z'-]*")) {
leftOff += 1;
break;
}
}
while (true) { //右移currOff
if (rigthOff >= length) {
break;
}
if (rigthOff != 0) {
rigthOff = rigthOff + 1;
if (rigthOff > length) {
rigthOff = length;
}
}
String selectText = getText().subSequence(currOff, rigthOff).toString();
if (!selectText.matches("^[()_0-9a-zA-Z'-]*")) {
rigthOff -= 1;
break;
}
}
String endString = "";
try {
endString = getText().subSequence(leftOff, rigthOff).toString();
if (!endString.trim().isEmpty()) {
Selection.setSelection((Spannable) getText(), leftOff, rigthOff);//选中
Log.d("WordTextView", "setSelection");
} else {
Log.d("WordTextView", endString);
}
} catch (Exception e) {
e.printStackTrace();
}
return endString.trim();
}
public interface Callback {
void getWord(String word);
}
}
使用
WordTextView main_wtv = findViewById(R.id.main_wtv);
main_wtv.setText(content);
TextView textView = findViewById(R.id.main_tv_word);
main_wtv.setCallback(new WordTextView.Callback() {
@Override
public void getWord(String word) {
textView.setText(String.format("单词:%s", word));
}
});
布局
不要设置inputType,否则点击选词失效
<com.jn.yyz.testone.WordTextView
android:id="@+id/main_wtv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingMultiplier="1.5"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:text="Hello World!"
android:textIsSelectable="true"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/main_tv_word" />