Android - 点击可点击Span和TextView的问题

6
我正在尝试实现可点击的话题标签在我的TextView中,如下所示:
mTextView.setMovementMethod(LinkMovementMethod.getInstance());

Spannable s = (Spannable) mTextView.getText();
CharacterStyle clickableSpan = new MyClickableSpan();
s.setSpan(clickableSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

这段代码处理了我想要的hashtag onClick事件,但似乎其他文本部分也会监听onClick事件,却没有做任何操作。

我的问题是如何使不可跨度的文本部分将onClick事件委托给父视图,如下图所示。

enter image description here

3个回答

1
我用这种方法解决了我的问题,但如果有更好的解决方案,请告诉我。
我为我的TextView设置了OnClickListener,在onClick事件中获取我的TextView的父级并检查父级是否可点击,然后执行父级onClick事件,如果不可点击,则递归获取父级的父级,直到达到可点击的父级。通过这种方式,哈希标签仍然可以通过自己的操作进行点击,并且当单击文本的其他部分时,将执行父级的onClick事件。
以下是我如何递归查找可点击父级的代码:
private View getParentClickable(View view) {
    try {
        if (((View) view.getParent()).isClickable()) {
            return (View) view.getParent();
        } else {
            return getParentClickable(((View) view.getParent()));
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

然后为我的视图设置setOnClickListener:
mTextView.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
       View parent = getParentClickable(mTextView);
       if (parent != null) parent.performClick();
   }
});

1
当您单击可点击的span本身时,它也会调用TextView的onClickListener。如果这不是您想要的,您需要检查最近是否已经调用了span监听器,然后再将点击委托给父级。 - kecal909

0
你可以使用类似这样的代码:
`SpannableString string = new SpannableString(getString(R.string.some_string));
 ClickableSpan clickableSpan = new ClickableSpan() {
            @Override
            public void onClick(View textView) {
                //do something
            }`

            @Override
            public void updateDrawState(TextPaint ds) {
                super.updateDrawState(ds);
                ds.setUnderlineText(false);
            }
        };

`string.setSpan(clickableSpan, string.length() - 20, string.length(),
                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        textView.setText(string);
        textView.setMovementMethod(LinkMovementMethod.getInstance());`

非常抱歉,我觉得我没有很好地解释我的问题。请重新查看问题并给出另一个提示。谢谢! - SamiAzar

0
我在 Kotlin 中使用下一个扩展。
fun SpannableString.withClickableSpan(
    context: Context,
    clickablePart: String,
    onClickListener: () -> Unit
): SpannableString {
    val clickableSpan = object : ClickableSpan() {
        override fun onClick(widget: View?) {
            onClickListener.invoke()
        }
    }
    val clickablePartStart = indexOf(clickablePart)

    this.setSpan(
        clickableSpan,
        clickablePartStart, clickablePartStart + clickablePart.length,
        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
    )
    this.setSpan(
        ForegroundColorSpan(ContextCompat.getColor(context, R.color.cyan)),
        clickablePartStart, clickablePartStart + clickablePart.length,
        Spanned.SPAN_INCLUSIVE_EXCLUSIVE
    )

    return this
}

并且像这样调用它:

val span = SpannableString(text).withClickableSpan(requireContext(), text) {
   onRevisionDateClicked(view)
}
view.movementMethod = LinkMovementMethod.getInstance()
view.setText(span, TextView.BufferType.SPANNABLE)
view.isClickable = true

您可以在Java中使用类似以下的东西:
SpannableString ss = new SpannableString("Hello World");
ClickableSpan spanText = new ClickableSpan() {
   @Override
   public void onClick(View textView) {
      // do some thing
   }
};

ss.setSpan(spanText, 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

textView.setText(ss);
textView.setMovementMethod(LinkMovementMethod.getInstance());

如果这个回答有帮助,请为@M.SamiAzar评分。 - Andrii Zhumela
2
我觉得你没有理解我的问题。我已经完成了可点击的span,但是我希望文本中除了hashtag之外的另一部分不可点击,并且当我点击该区域时执行父级onClick事件。 - SamiAzar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接