title: Handling click for a ClickableSpan with selectable text requires double click
body: <p>I have a <code>TextView</code> in which every word is a <code>ClickableSpan</code>. When clicked, the word become <strong>bold</strong> and the dictionary definition of the word is shown in another <em>TextView</em>. The app works correctly until I make the text in the <em>TextView</em> selectable. When the text is made selectable, the definition is shown on click, but the word is only <em>bold</em> on a double click. Text is selected on double click or long press (but long press does not make the word bold).</p>
  
  <p>My guess is that the problem has something to do with when in the action handling process the draw state is updated, but I am not been able to find a fix. I tried setting the <code>TextView</code> <code>focusable="false"</code> but nothing changed. Relevant code is below.</p>
  
  <pre><code>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);
  </code></pre>
  
  <p>And the WordSpan definition:</p>
  
  <pre><code>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;
          }
      }
  </code></pre>
  
  <p>Setting the movement method for the TextView:</p>
  
  <pre><code>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 &amp; (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);
              }
          };
      }
  </code></pre>
  
  <p>Edit:
  I just discovered a new quirk that may help in solving. If I double click but change words between clicks (tap one word &amp; then a different word quickly), on the first tap the definition for that word is shown and on the second tap the FIRST word is bold but the SECOND word is selected (highlighted) and the definition for the FIRST word is still shown.</p>
  
  <blockquote>
    <p>So for example if I double tap "first" and then "second", when I click
    "first" the definition for "first" will be shown, and when I touch
    "second" the word "first" is bold and the word "second" is highlighted
    but the definition does not change (still showing definition for
    "first").</p>
  </blockquote>