简体   繁体   中英

Android - Issue with clickableSpan and TextView

I'm trying to implement clickable hashtags in my TextView as below:

mTextView.setMovementMethod(LinkMovementMethod.getInstance());

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

this handles onClick for my hashtags as I wanted, but it seems that the other part of the text also listens for onClick events and does nothing.

My question is how to make the non-spannable text parts, delegate the onClick event to the parent view as see in below image.

在此处输入图片说明

You can use something like this :

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

I use the next extension in 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
}

And call it like:

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

OR you can use something like that in 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());

I figured out my question with this solution but if anyone had a better solution please let me know.

I set OnClickListener for my TextView and in the onClick event I get the parent of my TextView and check if the parent is clickable then perform parent onClick event and if not I recursively get the parent of the parent until I achieve to clickable parent. In this way, hashtags still are clickable with own actions and when clicking another part of the text the onClick event of the parent is performed.

here is the code of how I recursively find clickable parent:

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

and then setOnClickListener for my view:

mTextView.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
       View parent = getParentClickable(mTextView);
       if (parent != null) parent.performClick();
   }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM