我有一个带有TextViewClickableSpan,因为layout_height和layout_width都是wrap_content。

TextView中的文本不太长时,它可以正常工作。
当文本足够长以至于需要2行时,它也可以正常工作,但是会有一些奇怪的行为。

那就是当我单击第二行的空白区域(还没有填充文本,但是是TextView的一部分)时,调用ClickableSpan onClick()回调。

我不希望这样做,因为我只单击了空白区域,但没有单击跨区域的文本。
尽管影响不大,但我想知道背后的原因。

我将ClickableSpan设置为以下代码:

TextView tv = (TextView) findViewById(R.id.text);
tv.setText("TEXT TEXT TEXT TEXT");
SpannableStringBuilder ssb = new SpannableStringBuilder();
ssb.append(tv.getText());
ssb.setSpan(new TestClickableSpan(), ssb.length()-5, ssb.length(), 0);
tv.setText(ssb);
tv.setMovementMethod(LinkMovementMethod.getInstance());
tv.setOnTouchListener(new TextViewOnTouchListener());

TextViewOnTouchListener:
class TextViewOnTouchListener implements OnTouchListener{

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            Log.d("TextView", "onTouch");
            return false;
        }
}

TestClickableSpan:
class TestClickableSpan extends ClickableSpan{

        @Override
        public void onClick(View arg0) {
            Log.d("ClickableSpan", "Confirm OnClick: "+arg0.toString());
        }
    }

最佳答案

我设法通过扩展LinkMovementMethod来解决它,并检查触摸事件是否
offset等于或大于文字长度:

public class MovementMethod 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);

            if (off >= widget.getText().length()) {
               // Return true so click won't be triggered in the leftover empty space
                return true;
            }
        }

        return super.onTouchEvent(widget, buffer, event);
    }
}

10-07 22:02