LinkMovementMethod does not scroll if you start dragging from the link region

255 Views Asked by At

LinkMovementMethod class, which helps to find, highlight and handle clicks on links inside the TextView, has the issue with processing onTouch() method - if you start dragging from the detected link, you will see that no scrolling will occur.

1

There are 1 best solutions below

2
On

ScrollSensitiveLinkMovementMethod has better processing touches and allows you to scroll in this case.

I want to share my simple solution, might it will be helpful. https://gist.github.com/mpetlyuk/ec2d64659fbedfd47f7e0e650c9608dd If you enjoy it, you could please me with the star :)

package your_package_name;

import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.LinkMovementMethod;
import android.text.method.Touch;
import android.text.style.ClickableSpan;
import android.view.MotionEvent;
import android.widget.TextView;

public class ScrollSensitiveLinkMovementMethod extends LinkMovementMethod {

    private int CLICK_ACTION_THRESHOLD = 100;
    private float startX;
    private float startY;

    private boolean isAClick(float startX, float endX, float startY, float endY) {
        float differenceX = Math.abs(startX - endX);
        float differenceY = Math.abs(startY - endY);
        return !(differenceX > CLICK_ACTION_THRESHOLD || differenceY > CLICK_ACTION_THRESHOLD);
    }

    @Override
    public boolean onTouchEvent(TextView widget, Spannable buffer,
                                MotionEvent event) {

        int action = event.getAction();

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                startX = event.getX();
                startY = event.getY();

            case MotionEvent.ACTION_UP:
                float endX = event.getX();
                float endY = event.getY();

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

                ClickableSpan[] links = buffer.getSpans(off, off, ClickableSpan.class);

                if (links.length != 0) {
                    if (action == MotionEvent.ACTION_UP && isAClick(startX, endX, startY, endY)) {
                        links[0].onClick(widget);
                        return true;
                    } else {
                        Selection.setSelection(buffer,
                                buffer.getSpanStart(links[0]),
                                buffer.getSpanEnd(links[0]));
                    }
                } else {
                    Selection.removeSelection(buffer);
                }
                break;
        }

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