ClickableSpan странное поведение: onClick () вызывается при нажатии на пустое место - PullRequest
10 голосов
/ 14 февраля 2012

У меня есть TextView с ClickableSpan, в котором layout_height и layout_width имеют значение wrap_content.

Когда текст в TextView не слишком длинный, он работает нормально.Когда текст настолько длинный, что занимает 2 строки, он также работает нормально, но имеет странное поведение.

Именно тогда я щелкнул по пустому пространству второй строки (пока не заполняется текстом, но является частью *).1008 *), вызывается обратный вызов 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());
        }       
    }

Ответы [ 3 ]

13 голосов
/ 28 июля 2014

Мне удалось решить ее, расширив LinkMovementMethod и проверив, равно ли смещение события касания или больше, чем длина текста:

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);
    }
}
1 голос
/ 23 мая 2019

Ответ dor506 отлично сработал для меня для EditTexts с одной строкой Однако, когда пользователь набрал несколько строк, решение будет применяться только к последней строке. То есть ClickableSpans в нижней строке будет вести себя правильно, но во всех остальных строках будет активен щелчок через пробел.

Я решил это, изменив:

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

до:

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

(Извините за публикацию в качестве отдельного ответа - у меня недостаточно репутации, чтобы добавить комментарий, но я подумал, что это может стоить документировать!)

0 голосов
/ 17 июля 2019

Ответ dor506 у меня не сработал, поэтому я искал другие решения и нашел этот репозиторий: https://github.com/saket/Better-Link-Movement-Method

После добавления его в свой проект используйте его так:

textView.setMovementMethod(BetterLinkMovementMethod.newInstance());

Это должно решить проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...