2

I had a need to have a CheckBox that contained an integrated clickable area to bring up another screen in the app. This solution works wonderfully:

CheckBox checkBox = (CheckBox) findViewById(R.id.my_check_box);

ClickableSpan clickableSpan = new ClickableSpan() {
    @Override
    public void onClick(View widget) {
        // Prevent CheckBox state from being toggled when link is clicked
        widget.cancelPendingInputEvents();
        // Do action for link text...
    }
    @Override
    public void updateDrawState(TextPaint ds) {
        super.updateDrawState(ds);
        // Show links with underlines (optional)
        ds.setUnderlineText(true);
    }
};

SpannableString linkText = new SpannableString("Link text");
linkText.setSpan(clickableSpan, 0, linkText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
CharSequence cs = TextUtils.expandTemplate(
    "CheckBox text with link: ^1 , and after link", linkText);

checkBox.setText(cs);
// Finally, make links clickable
checkBox.setMovementMethod(LinkMovementMethod.getInstance());

...except that I am running into the same problem as mentioned in this comment. When the user clicks the ClickableSpan, while the click gets registered and handled by the span, the CheckBox also briefly goes into the pressed state. The box of the CheckBox behaves as though the user clicked it, though it does not toggle the actual checked state.

You can see the effect in this GIF — watch the actual box of the CheckBox on the left:

CheckBox Animation

I still want that pressed state when the user clicks on the rest of the CheckBox, so I do not want to try changing a background or something to eliminate the pressed state. Is there a way from the ClickableSpan to say "please do not transition to the checked state"?

aminography
  • 21,986
  • 13
  • 70
  • 74
CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I doubt you can do this. A CheckBox is basically just a TextView with a compound drawable and a boolean, so when you press anything drawn in it, you're pressing the whole View. Does it actually check it though, or just make it look like it's going to? – TheWanderer Oct 11 '18 at 20:50
  • @TheWanderer: Just as you see in the GIF, you get the brief pressed state flash, but that's it. There is no actual transition to the checked state. Frankly, I would have expected `cancelPendingInputEvents()` to cover this, which is why I was wondering if there was something else that could be called from inside of `onClick()` that would address the pressed state. – CommonsWare Oct 11 '18 at 20:59
  • You might be able to do `setClickable(false)` and then set it back to true. – TheWanderer Oct 11 '18 at 21:13
  • No luck, but that was a good thing to try -- thanks! – CommonsWare Oct 11 '18 at 21:21

0 Answers0