Android TextView Linkify 拦截父View手势

发布于 2024-12-02 03:55:36 字数 178 浏览 0 评论 0原文

问题是,如果我 Linkify textView,底层 ScrollView 不会听我设置的扫描手势。有没有办法让 Linkify 不干扰底层视图的手势? 我尝试覆盖 ontouchEvent 并向 ACTION_MOVE 返回 false,但滚动视图的手势需要 ACTION_DOWN 和 ACTION_UP 事件才能起作用。有办法实现吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

吻风 2024-12-09 03:55:36

Linkify 适用于 textView LinkMovementMethod 的 moveMethod。该移动方法认为它实现了垂直滚动方法,它覆盖了父级具有的任何其他滚动方法。虽然 touchEvent 可以分派给父级,但特定的父级 ScrollView 需要整个序列 ACTION_DOWNACTION_MOVE、< code>ACTION_UP 执行(扫描检测)。

所以我的问题的解决方案是在Linkify之后删除textView的滚动方法并在textView的onTouchEvent中处理LinkMovementMethod链接检测操作。

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

这样我就有了 Link_Click 检测(仅在用户触摸链接而不是整个文本视图时执行),并且我没有整个 LinkMovementMethod。

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.

沙与沫 2024-12-09 03:55:36

@weakwire 和 @Ridicully 的答案是正确的。我刚刚创建了一个小要点,您可以在项目中重复使用它。

这是链接:https://gist.github.com/amilcar-andrade/e4b76840da1dc92febfc

@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

顾忌 2024-12-09 03:55:36

有一个小坏事就是
TextView::setText(...) 方法利用了 autoLink 标志,

if (mAutoLinkMask != 0) {
        Spannable s2;

        if (type == BufferType.EDITABLE || text instanceof Spannable) {
            s2 = (Spannable) text;
        } else {
            s2 = mSpannableFactory.newSpannable(text);
        }

        if (Linkify.addLinks(s2, mAutoLinkMask)) {
            text = s2;
            type = (type == BufferType.EDITABLE) ? BufferType.EDITABLE : BufferType.SPANNABLE;

            /*
             * We must go ahead and set the text before changing the
             * movement method, because setMovementMethod() may call
             * setText() again to try to upgrade the buffer type.
             */
            mText = text;

            // Do not change the movement method for text that support text selection as it
            // would prevent an arbitrary cursor displacement.
            if (mLinksClickable && !textCanBeSelected()) {
                setMovementMethod(LinkMovementMethod.getInstance());
            }
        }
    }

所以我花了一些时间来理解,
为什么我禁用 ListView 项目中的链接,
但有时会获得链接!

您需要将该标志设置为所需的值
然后调用 setText(...)

There is a small bad thing that
TextView::setText(...) method utilizing autoLink flag,

if (mAutoLinkMask != 0) {
        Spannable s2;

        if (type == BufferType.EDITABLE || text instanceof Spannable) {
            s2 = (Spannable) text;
        } else {
            s2 = mSpannableFactory.newSpannable(text);
        }

        if (Linkify.addLinks(s2, mAutoLinkMask)) {
            text = s2;
            type = (type == BufferType.EDITABLE) ? BufferType.EDITABLE : BufferType.SPANNABLE;

            /*
             * We must go ahead and set the text before changing the
             * movement method, because setMovementMethod() may call
             * setText() again to try to upgrade the buffer type.
             */
            mText = text;

            // Do not change the movement method for text that support text selection as it
            // would prevent an arbitrary cursor displacement.
            if (mLinksClickable && !textCanBeSelected()) {
                setMovementMethod(LinkMovementMethod.getInstance());
            }
        }
    }

So I spent a time to understand,
why i'm disabling links in ListView item,
but it obtains a link sometimes!

You need to set that flag in needed value
and then call a setText(...)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文