2016-11-20 2 views
5

나는 TextView이고 모든 단어의 길이는 ClickableSpan입니다. 클릭하면 단어 은 굵게이되고 단어 사전 정의는 TextView으로 표시됩니다. 응용 프로그램은 텍스트가 TextView으로 선택 될 때까지 제대로 작동합니다. 텍스트를 선택 가능하게 만들 때 클릭에 정의가 표시되지만 두 번 클릭하면 굵게는 굵게입니다. 더블 클릭이나 길게 누를 때 텍스트가 선택됩니다 (길게 누르면 굵게 표시되지 않습니다).선택 가능한 텍스트가있는 ClickableSpan에 대한 처리는 더블 클릭이 필요합니다.

내 생각 엔 동작 처리 프로세스에서 그리기 상태가 업데이트되었지만 수정 프로그램을 찾을 수 없을 때 문제가 발생했다고 생각합니다. TextViewfocusable="false" 설정을 시도했지만 아무 것도 변경되지 않았습니다. 관련 코드는 다음과 같습니다.

curSpan = new WordSpan(index) { 
    @Override 
    public void onClick(View view) { 
     handleWordClick(index,this); // handles code to display definition 
     setMarking(true); 
     view.invalidate(); 
     tvText.invalidate(); 
    } 
}; 

spannableStringBuilder.setSpan(curSpan, totalLength, totalLength + strWord, Spanned.SPAN_COMPOSING); 

그리고 WordSpan 정의 :

class WordSpan extends ClickableSpan 
    { 
     int id; 
     private boolean marking = false; 

     public WordSpan(int id) { 
      this.id = id; 
     } 

     @Override 
     public void updateDrawState(TextPaint ds) { 
      ds.setColor(Color.BLACK); 
      ds.setUnderlineText(false); 
      if (marking) { 
       ds.setTypeface(Typeface.create(myFont,Typeface.BOLD)); 
      } 
     } 

     @Override 
     public void onClick(View v) {} 

     public void setMarking(boolean m) { 
      marking = m; 
     } 
    } 

텍스트 뷰의 이동 방법을 설정 :

private MovementMethod createMovementMethod (Context context) { 
     final GestureDetector detector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { 
       @Override 
       public boolean onSingleTapUp (MotionEvent e) { 
        return true; 
       } 

       @Override 
       public boolean onSingleTapConfirmed (MotionEvent e) { 
        return true; 
       } 
      }); 

     return new ScrollingMovementMethod() { 

      @Override 
      public boolean canSelectArbitrarily() { 
       return true; 
      } 

      @Override 
      public void initialize(TextView widget, Spannable text) { 
       Selection.setSelection(text, text.length()); 
      } 

      @Override 
      public void onTakeFocus(TextView view, Spannable text, int dir) { 
       if ((dir & (View.FOCUS_FORWARD | View.FOCUS_DOWN)) != 0) { 
        if (view.getLayout() == null) { 
         // This shouldn't be null, but do something sensible if it is. 
         Selection.setSelection(text, text.length()); 
        } 
       } else { 
        Selection.setSelection(text, text.length()); 
       } 
      } 

      @Override 
      public boolean onTouchEvent (TextView widget, Spannable buffer, MotionEvent event) { 
       // check if event is a single tab 
       boolean isClickEvent = detector.onTouchEvent(event); 

       // detect span that was clicked 
       if (isClickEvent) { 
        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); 

        WordSpan[] link = buffer.getSpans(off, off, WordSpan.class); 

        if (link.length != 0) { 
         // execute click only for first clickable span 
         // can be a for each loop to execute every one 
         if (event.getAction() == MotionEvent.ACTION_UP) { 
          link[0].onClick(widget); 
         } else if (event.getAction() == MotionEvent.ACTION_DOWN) { 
          Selection.setSelection(buffer, 
                buffer.getSpanStart(link[0]), 
                buffer.getSpanEnd(link[0])); 
         } 
         return true; 
        } 
       } 

       // let scroll movement handle the touch 
       return super.onTouchEvent(widget, buffer, event); 
      } 
     }; 
    } 

편집 : 난 그냥 해결에 도움이 될 수 있습니다 새로운 특질을 발견했다. 더블 클릭하지만 클릭 사이의 단어를 변경하는 경우 (한 단어 &을 신속하게 누른 다음 다른 단어를 빨리 누릅니다), 첫 번째 탭에서 해당 단어에 대한 정의가 표시되고 두 번째 탭에서 첫 번째 단어는 굵게 표시되지만 두 번째 단어가 선택됩니다) 그리고 FIRST 단어에 대한 정의는 계속 표시됩니다.

은 "그래서 예를 들어 나는"첫 번째 "탭을 두 배로하면 다음"초 "때"첫 번째는 "표시됩니다에 대한 "최초의 "정의를 클릭하고 난 "두 번째 "라는 단어를 터치하면 첫 번째 "는 굵게 표시되고"second "라는 단어는 으로 강조 표시되지만 정의는 변경되지 않습니다 (여전히 에 대한 정의가 첫 번째로 표시됨).

+0

안녕하세요! 나는 정확한 질문을 이해하고있다. 클릭 가능한 텍스트가 다른 Spannable String이있는 TextView를 두 번 클릭하는 방법은 무엇입니까? – GensaGames

+0

두 번 클릭하는 대신 한 번 클릭해야합니다. 사용자가 단어를 클릭하면 단어를 굵게 표시하고 정의를 표시해야합니다. 더블 클릭으로 아무것도하지 말아야합니다. –

답변

0

createMovementMethod을 다음으로 바꿉니다. 만약 당신이 오류 얼굴 오류 plz 그것을 수정 하고이 답변을 편집 할 수 있습니다.

private MovementMethod createMovementMethod (final Context context) { 

     return new ScrollingMovementMethod() { 
      public MotionEvent event; 
      public Spannable buffer; 
      public TextView widget; 
      final GestureDetector detector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { 
       @Override 
       public boolean onSingleTapUp (MotionEvent e) { 

        return true; 
       } 

       @Override 
       public boolean onSingleTapConfirmed (MotionEvent e) { 
        triggerClick(); 
        return true; 
       } 

       @Override 
       public boolean onDoubleTap(MotionEvent e) { 
        triggerClick(); 
        return true; 
       } 

       private boolean triggerClick() { 
        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); 

        WordSpan[] link = buffer.getSpans(off, off, WordSpan.class); 

        if (link.length != 0) { 
         // execute click only for first clickable span 
         // can be a for each loop to execute every one 
         if (event.getAction() == MotionEvent.ACTION_UP) { 
          link[0].onClick(widget); 
         } else if (event.getAction() == MotionEvent.ACTION_DOWN) { 
          Selection.setSelection(buffer, 
            buffer.getSpanStart(link[0]), 
            buffer.getSpanEnd(link[0])); 
         } 
         return true; 
        } 

        return true; 
       } 
      }); 
      @Override 
      public boolean canSelectArbitrarily() { 
       return true; 
      } 

      @Override 
      public void initialize(TextView widget, Spannable text) { 
       Selection.setSelection(text, text.length()); 
      } 

      @Override 
      public void onTakeFocus(TextView view, Spannable text, int dir) { 
       if ((dir & (View.FOCUS_FORWARD | View.FOCUS_DOWN)) != 0) { 
        if (view.getLayout() == null) { 
         // This shouldn't be null, but do something sensible if it is. 
         Selection.setSelection(text, text.length()); 
        } 
       } else { 
        Selection.setSelection(text, text.length()); 
       } 
      } 

      @Override 
      public boolean onTouchEvent (TextView widget, Spannable buffer, MotionEvent event) { 
       // check if event is a single tab 
       boolean isClickEvent = detector.onTouchEvent(event); 

       //record this for GestureDetector 
       this.widget = widget; 
       this.buffer = buffer; 
       this.event = event; 

       // detect span that was clicked 
       if (isClickEvent) { 
        //ignore click here 
        return true; 
       } 

       // let scroll movement handle the touch 
       return super.onTouchEvent(widget, buffer, event); 
      } 
     }; 
    } 
+0

답장을 보내 주셔서 감사합니다. 그러나 문제는 해결되지 않으며 터치 할 때 잘못된 단어가 선택되었다는 추가 문제가 추가됩니다. –

+0

또한 onDoubleTap()은 두 번 탭에 의해 트리거되지 않습니다. 그것은 두 번 탭할 때만 작동하지만이 방법은 트리거되지 않으므로이 응답 시도처럼 리디렉션 할 수 없습니다. –

+0

예, 비슷한 것이 필요합니다. 그것은 당신이 그것을 고치고 대답 자체를 편집 할 필요가 테스트되지 않았습니다. 감사 – Qamar

관련 문제