onClick을 호출하지 않는 Android ClickableSpan


150

ClickableSpan을 만들고 있는데 적절한 텍스트에 밑줄이 그어져 있습니다. 그러나 클릭이 등록되지 않습니다. 내가 뭘 잘못하고 있는지 알아?

고마워, 빅터

다음은 코드 스 니펫입니다.

view.setText("This is a test");
ClickableSpan span = new ClickableSpan() {
    @Override
    public void onClick(View widget) {
        log("Clicked");
    }
};
view.getText().setSpan(span, 0, view.getText().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

답변:


430

범위가 포함 된 TextView에서 MovementMethod를 설정해 보셨습니까? 클릭이 작동하도록하려면이 작업을 수행해야합니다 ...

tv.setMovementMethod(LinkMovementMethod.getInstance());

tvEditText 유형 인 경우 제대로 작동하지 않습니다 . 범위를 클릭 할 수는 있지만 정상적으로 편집 할 수는 없습니다.
FIG-GHD742

많은 감사합니다! 나에게도 효과가 있습니다! 이 설정에 대해 설명해 주시겠습니까?
alfo888_ibg

63
과정 나는 클릭 핸들러가 작동하도록 문서가 "화살표 키 핸들러"라고 부르는 것을 설정해야한다. 너무 명백하다! (╯ ° □ °) ╯︵ ┻━┻
adamdport

작동하지만 이것이 기본 동작이 아닌 이유를 실제로 알 수는 없습니다.
EpicPandaForce

그리고 Google은 setMovementMethod를 호출하면 "타원"이 작동하지 않는다고 언급하는 것을 잊었습니다. 따라서 올바른 접근 방식은 TouchListener를 수동으로 구현하고 거기에서 가져 오는 것입니다.
slott

4

시행 착오 후에는 설정 순서 tv.setMovementMethod(LinkMovementMethod.getInstance());가 중요합니다.

여기 내 전체 코드가 있습니다

String stringTerms = getString(R.string.sign_up_terms);
Spannable spannable = new SpannableString(stringTerms);
int indexTermsStart = stringTerms.indexOf("Terms");
int indexTermsEnd = indexTermsStart + 18;
spannable.setSpan(new UnderlineSpan(), indexTermsStart, indexTermsEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new ForegroundColorSpan(getColor(R.color.theme)), indexTermsStart, indexTermsEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new ClickableSpan() {
    @Override
    public void onClick(View widget) {
        Log.d(TAG, "TODO onClick.. Terms and Condition");
    }
}, indexTermsStart, indexTermsEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

int indexPolicyStart = stringTerms.indexOf("Privacy");
int indexPolicyEnd = indexPolicyStart + 14;
spannable.setSpan(new UnderlineSpan(), indexPolicyStart, indexPolicyEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new ForegroundColorSpan(getColor(R.color.theme)), indexPolicyStart, indexPolicyEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new ClickableSpan() {
    @Override
    public void onClick(View widget) {
        Log.d(TAG, "TODO onClick.. Privacy Policy");
    }
}, indexPolicyStart, indexPolicyEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

TextView textViewTerms = (TextView) findViewById(R.id.sign_up_terms_text);
textViewTerms.setText(spannable);
textViewTerms.setClickable(true);
textViewTerms.setMovementMethod(LinkMovementMethod.getInstance());

4

코 틀린 유틸리티 기능 :

fun setClickable(textView: TextView, subString: String, handler: () -> Unit, drawUnderline: Boolean = false) {
    val text = textView.text
    val start = text.indexOf(subString)
    val end = start + subString.length

    val span = SpannableString(text)
    span.setSpan(ClickHandler(handler, drawUnderline), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)

    textView.linksClickable = true
    textView.isClickable = true
    textView.movementMethod = LinkMovementMethod.getInstance()

    textView.text = span
}

class ClickHandler(
        private val handler: () -> Unit,
        private val drawUnderline: Boolean
) : ClickableSpan() {
    override fun onClick(widget: View?) {
        handler()
    }

    override fun updateDrawState(ds: TextPaint?) {
        if (drawUnderline) {
            super.updateDrawState(ds)
        } else {
            ds?.isUnderlineText = false
        }
    }
}

용법:

Utils.setClickable(textView, subString, {handleClick()})

1

코 틀린에서의 직접 접근

  val  textHeadingSpannable = SpannableString(resources.getString(R.string.travel_agent))


           val clickSpan = object : ClickableSpan(){
               override fun onClick(widget: View) {

                // Handel your click
               }
           }
            textHeadingSpannable.setSpan(clickSpan,104,136,Spannable.SPAN_INCLUSIVE_EXCLUSIVE)

            tv_contact_us_inquire_travel_agent.movementMethod = LinkMovementMethod.getInstance()
            tv_contact_us_inquire_travel_agent.text = textHeadingSpannable
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.