Как я могу использовать onTouchListeners для каждого слова в TextView?
Я хотел бы назначить onTouchListeners для каждого слова в TextView. (Не для того, чтобы ссылаться на что-то в Интернете, а просто для продолжения игровой логики внутри приложения). Основное действие моей игры на этом этапе - увидеть TextView, коснуться слова, если это целевое слово, которое ты выиграл, иначе загрузить другой TextView, основанный на слове, которого ты коснулся, и повторить. Теперь я выполняю это с помощью ClickableSpans и onClicks для каждого слова.
Но я бы предпочел иметь onTouchListeners, чтобы я мог изменить цвет фона слова на touch_down и выполнить игровую логику на touch_up, чтобы он выглядел более отзывчивым. Как я могу сделать это?
final TextView defTV = (TextView) findViewById(R.id.defTV);
text = new SpannableString(rv); // rv is the future clickable TextView text
ClickableSpan clickableSpan = null;
String regex = "\\w+";
Pattern p = Pattern.compile(regex);
Matcher matcher = p.matcher(text);
while (matcher.find()) {
final int begin = matcher.start();
final int end = matcher.end();
clickableSpan = new ClickableSpan() {
public void onClick(View arg0) {
String lword = (String) text.subSequence(begin, end).toString();
if (lword.equalsIgnoreCase(targetword)) {
// WIN
} else {
// Build new TextView based on lword, start over
}
}
};
text.setSpan(clickableSpan, begin, end, 0);
}
1 ответ
Поэтому я скопировал ClickableSpan.java и сделал TouchableSpan.java:
import android.text.TextPaint;
import android.text.style.CharacterStyle;
import android.text.style.UpdateAppearance;
import android.view.MotionEvent;
import android.view.View;
/**
* If an object of this type is attached to the text of a TextView
* with a movement method of LinkTouchMovementMethod, the affected spans of
* text can be selected. If touched, the {@link #onTouch} method will
* be called.
*/
public abstract class TouchableSpan extends CharacterStyle implements UpdateAppearance {
/**
* Performs the touch action associated with this span.
* @return
*/
public abstract boolean onTouch(View widget, MotionEvent m);
/**
* Could make the text underlined or change link color.
*/
@Override
public abstract void updateDrawState(TextPaint ds);
}
И я продлил LinkMovementMethod.java
в LinkTouchMovementMethod.java
, Метод onTouchEvent остается тем же, за исключением того, что упоминание onClick изменено на onTouch и добавлена новая строка:
import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.LinkMovementMethod;
import android.view.MotionEvent;
import android.widget.TextView;
public class LinkTouchMovementMethod extends LinkMovementMethod
{
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer,
MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN) {
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);
TouchableSpan[] link = buffer.getSpans(off, off, TouchableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onTouch(widget,event); //////// CHANGED HERE
} else if (action == MotionEvent.ACTION_DOWN) {
link[0].onTouch(widget,event); //////// ADDED THIS
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
}
return true;
} else {
Selection.removeSelection(buffer);
}
}
return super.onTouchEvent(widget, buffer, event);
}
}
И установите MovementMethod соответствующим образом в вашем коде:
TextView tv = (TextView) findViewById(R.id.tv);
tv.setMovementMethod(new LinkTouchMovementMethod());
Теперь, чтобы показать текст:
touchableSpan = new TouchableSpan() {
public boolean onTouch(View widget, MotionEvent m) {
...
}
public void updateDrawState(TextPaint ds) {
ds.setUnderlineText(false);
ds.setAntiAlias(true);
}
};
String rv = "Text to span";
text = new SpannableString(rv);
text.setSpan(touchableSpan, begin, end, 0);
tv.setText(text, BufferType.SPANNABLE);