How can I use onTouchListeners on each word in a TextView?

前端 未结 1 869
野趣味
野趣味 2020-12-23 08:57

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 gener

相关标签:
1条回答
  • 2020-12-23 09:28

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

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

    And set the MovementMethod appropriately in your code:

    TextView tv = (TextView) findViewById(R.id.tv);
    tv.setMovementMethod(new LinkTouchMovementMethod());
    

    Now to show the text:

    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);
    
    0 讨论(0)
提交回复
热议问题