TextView 에 ClickableSpan 과 LinkMovement Method 의 관 계 를 추가 합 니 다.

4857 단어 Android
Android 에서 일부 텍스트 를 클릭 하고 변색 할 수 있 습 니 다.일반적으로 ClickableSpan 을 사용 할 생각 을 하기 때문에 아래 코드 가 있 습 니 다.
TextView tv = (TextView) findViewById(R.id.textview);
SpannableString ss = new SpannableString("Java            Android");
ss.setSpan(new MyClickSpan("java"),0,4,0);
tv.setText(ss);

4.567913.다시 실행 하면 클릭 할 수 있 습 니 다.여기 서 기본적으로 만족 하 는 대부분의 개발 업 무 를 발견 할 수 있 습 니 다.그러나 어 려 운 개발 자로 서 제품 매니저 를 만족 시 켜 야 합 니 다.
먼저 클릭 한 문 제 를 말 하고,뒤에 다시 그림 과 글 을 혼합 하여 배열 하 다.위의 코드 는 현재 로 서 는 문제 가 없 는 것 같 지만 필 자 는 현재 두 가지 문 제 를 발견 했다.
1.textview 가 일부 파일 의 클릭 이벤트 에 응답 하 는 것 을 제외 하고 나머지 부분 이 다른 작업 에 응답 하면 문제 가 발생 합 니 다.(동료 가 span 의 onclick 과 textview 의 click 을 되 돌려 줍 니 다)
2.textview 가 설정 한 max Line 과 텍스트 높이 가 max line 의 값 을 초과 하면 텍스트 가 굴 러 갈 수 있 습 니 다.ellipsize 의 값 을 설정 하 더 라 도 LinkMovement Method 가 설정 되 어 있 기 때 문 입 니 다.
이 두 버그 의 존 재 는 반드시 테스트 를 통과 할 수 없 기 때문에 각종 도 모 와 구 글 은 만 족 스 러 운 답 을 찾 지 못 해 스스로 TextView 소스 코드 를 뜯 어 먹 을 수 밖 에 없 었 다.
클릭 이 onClick 이나 onTouch 이벤트 와 관련 되 기 때문에 먼저 onClick 을 찾 았 으 나 TextView 에서 onClick 관련 코드 를 찾 지 못 했 습 니 다.그리고 온 터치 이벤트 방법 을 보면,
그래서 아래 코드 를 찾 았 습 니 다.
 
   
  

tv.setMovementMethod(LinkMovementMethod.getInstance());

코드 중
if ((mMovement != null || onCheckIsTextEditor()) && isEnabled()
                && mText instanceof Spannable && mLayout != null) {
            boolean handled = false;

            if (mMovement != null) {
                handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
            }
            final boolean textIsSelectable = isTextSelectable();
            if (touchIsFinished && mLinksClickable && mAutoLinkMask != 0 && textIsSelectable) {
                // The LinkMovementMethod which should handle taps on links has not been installed
                // on non editable text that support text selection.
                // We reproduce its behavior here to open links for these.
                ClickableSpan[] links = ((Spannable) mText).getSpans(getSelectionStart(),
                        getSelectionEnd(), ClickableSpan.class);

                if (links.length > 0) {
                    links[0].onClick(this);
                    handled = true;
                }
            }

부분 은 set Movement Method 방법 으로 설 정 된 대상 입 니 다.LinkMovement Method 의 인 스 턴 스 를 설정 하기 때문에 LinkMovement Method 소스 코드 를 계속 열 어 onTouchEvent 의 코드 를 봅 니 다.
Clickable Span 의 실현 원 리 를 한눈 에 알 수 있다.
tv.setMovement Method(LinkMovement Method.getInstance())때문에;코드 상기 빨간색 두 가지 문 제 를 보고 소스 코드 를 보면 우리 의 해결 방법 은 TextView 에 onTouch Event 를 직접 설정 하 는 것 입 니 다.
다음은 스스로 Clickable Span 클릭 을 실현 하 는 코드 입 니 다.
        if (mMovement != null) {
                handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
        }

디 버 깅 을 실행 하 였 는데,더 이상 상술 한 두 가지 문제 가 없 음 을 발견 하여 큰 성 과 를 거 두 었 다.
최종 코드 는 아주 적은 것 이지 만 처음에 문 제 를 만 나 어떻게 해결 해 야 할 지 모 를 때 소스 코드 를 읽 는 것 이 힘 들 기 때문에 평소에 문 제 를 해결 할 때 소스 코드 를 많이 보 는 것 이 큰 도움 이 된다.구 글 이 안 드 로 이 드 를 오픈 해 주 셔 서 감사합니다.
사용자 정의 클릭 가능 한 텍스트 색상 을 포함 하여 MyClickSpan 코드 를 추가 합 니 다.
    @Override
    public boolean onTouchEvent(TextView widget, Spannable buffer,
                                MotionEvent event) {
        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;
            } else {
                Selection.removeSelection(buffer);
            }
        }

        return super.onTouchEvent(widget, buffer, event);
    }

작가 가 문 제 를 해결 한 후에 stackoverflow 에서 발견 한 똑 같은 문제 에 링크 를 첨부 하여 참고 하 시기 바 랍 니 다.
https://stackoverflow.com/questions/5183645/android-clickablespan-in-clickable-textview/40214599#40214599

좋은 웹페이지 즐겨찾기