如何在 TextView 中的每个单词上使用 onTouchListeners? [英] How can I use onTouchListeners on each word in a TextView?

查看:24
本文介绍了如何在 TextView 中的每个单词上使用 onTouchListeners?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将 onTouchListeners 分配给 TextView 中的每个单词.(不链接到互联网上的东西,而只是为了继续应用程序内的游戏逻辑).此时我的游戏的一般动作是查看一个 TextView,触摸一个单词,如果它是您赢得的目标单词,否则根据您触摸的单词加载另一个 TextView 并重复.我现在实现这一点的方法是为每个单词使用 ClickableSpans 和 onClicks.

I would like to assign onTouchListeners to each word in a TextView. (Not to link to something on the internet, but just to continue the game logic inside the app). The general action of my game at this point is to see a TextView, touch a word, if it's the target word you win, else load another TextView based on the word you touch and repeat. The way I accomplish this now is with ClickableSpans and onClicks for each word.

但我宁愿使用 onTouchListeners,这样我就可以在 touch_down 上更改单词背景的颜色,并在 touch_up 上执行游戏逻辑,使其看起来更具响应性.我怎样才能做到这一点?

But I would rather have onTouchListeners so I can change the color of the background of the word on touch_down and do the game logic on touch_up, to make it look more responsive. How can I accomplish this?

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

        }

推荐答案

于是我复制了 ClickableSpan.java 并制作了 TouchableSpan.java:

So I copied ClickableSpan.java and made 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 并添加了一个新行:

And I extended LinkMovementMethod.java to LinkTouchMovementMethod.java. The onTouchEvent method is the same the same except for a mention of onClick is changed to onTouch and a new line is added:

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:

And set the MovementMethod appropriately in your code:

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

这篇关于如何在 TextView 中的每个单词上使用 onTouchListeners?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆