Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android TextView Linkify intercepts with parent View gestures

The problem is that if i Linkify the textView the underliyng ScrollView don't listen the sweep Gestures I've setted.Is there a way to have Linkify without messing with the underliyng view's gestures? I tried to override ontouchEvent and return false to ACTION_MOVE but the scrollview's gesture needs the ACTION_DOWN and ACTION_UP event to function. Is there a way to achieve that?

like image 725
weakwire Avatar asked Aug 29 '11 22:08

weakwire


2 Answers

Linkify applies to a movementMethod to the textView LinkMovementMethod. That movement method thought it implements a scrolling vertically method it overrides any other scrolling method the parent has. Although touchEvent can be dispached to the parent, the specific parent ScrollView needed the whole sequence ACTION_DOWN , ACTION_MOVE, ACTION_UP to perform (sweep detection).

So the solution to my problem is after Linkify to remove the textView's scrolling method and handle the LinkMovementMethod link detection action in onTouchEvent of the textView.

@override
public boolean onTouchEvent(MotionEvent event) {
        TextView widget = (TextView) this;
        Object text = widget.getText();
        if (text instanceof Spanned) {
            Spannable buffer = (Spannable) text;

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

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

                if (link.length != 0) {
                    if (action == MotionEvent.ACTION_UP) {
                        link[0].onClick(widget);
                    } else if (action == MotionEvent.ACTION_DOWN) {
                         Selection.setSelection(buffer,
                                 buffer.getSpanStart(link[0]),
                                 buffer.getSpanEnd(link[0]));
                    }
                    return true;
                }
            }

        }

        return false;
    }

This way i have the Link_Click detection (performed only with the user touches the link and not the whole textview) and i don't have the whole LinkMovementMethod.

like image 90
weakwire Avatar answered Oct 31 '22 13:10

weakwire


@weakwire and @Ridicully answers are correct. I just created a small gist that you can re-use in your project.

This is the link: https://gist.github.com/amilcar-andrade/e4b76840da1dc92febfc

like image 21
Amilcar Andrade Avatar answered Oct 31 '22 13:10

Amilcar Andrade