@Override
 public void clearSpans() {
   /* XXX this clears the selection spans too,
   but there is no way to clear the corresponding selection in Gecko */
   Log.w(LOGTAG, "selection cleared with clearSpans()");
   mText.clearSpans();
 }
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    tv = new TextView(this);
    ctx = this;

    String htmlLinkText = "我是超链接" + "<a href='lianjie'><font color='red'>超链接点击事件</font></a>";
    // 文字的样式(style)被覆盖,不能改变……

    tv.setText(Html.fromHtml(htmlLinkText));
    tv.setMovementMethod(LinkMovementMethod.getInstance());
    CharSequence text = tv.getText();
    if (text instanceof Spannable) {
      int end = text.length();
      Spannable sp = (Spannable) tv.getText();
      URLSpan[] urls = sp.getSpans(0, end, URLSpan.class);
      SpannableStringBuilder style = new SpannableStringBuilder(text);
      style.clearSpans(); // should clear old spans

      // 循环把链接发过去
      for (URLSpan url : urls) {
        MyURLSpan myURLSpan = new MyURLSpan(url.getURL());
        style.setSpan(
            myURLSpan,
            sp.getSpanStart(url),
            sp.getSpanEnd(url),
            Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
      }
      tv.setText(style);
    }
    setContentView(tv);
  }
 /**
  * @desc
  *     <pre>表情解析,转成unicode字符</pre>
  *
  * @author Weiliang Hu
  * @date 2013-12-17
  * @param cs
  * @param mContext
  * @return
  */
 public static String convertToMsg(CharSequence cs, Context mContext) {
   SpannableStringBuilder ssb = new SpannableStringBuilder(cs);
   ImageSpan[] spans = ssb.getSpans(0, cs.length(), ImageSpan.class);
   for (int i = 0; i < spans.length; i++) {
     ImageSpan span = spans[i];
     String c = span.getSource();
     int a = ssb.getSpanStart(span);
     int b = ssb.getSpanEnd(span);
     if (c.contains("[")) {
       ssb.replace(a, b, convertUnicode(c));
     }
   }
   ssb.clearSpans();
   return ssb.toString();
 }
Exemple #4
0
 private void updateErrorText() {
   mErrorText.clear();
   mErrorText.clearSpans();
   final int length = mTextInputLayout.getEditText().length();
   if (length > 0) {
     mErrorText.append(String.valueOf(length));
     mErrorText.append(" / ");
     mErrorText.append(String.valueOf(mMaxLen));
     mErrorText.setSpan(
         mAlignmentSpan, 0, mErrorText.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
     if (hasValidLength()) {
       mErrorText.setSpan(
           mNormalTextAppearance, 0, mErrorText.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
     }
   }
   mTextInputLayout.setError(mErrorText);
 }
  @WrapForJNI
  @Override
  public void onTextChange(
      final CharSequence text,
      final int start,
      final int unboundedOldEnd,
      final int unboundedNewEnd) {
    if (DEBUG) {
      // GeckoEditableListener methods should all be called from the Gecko thread
      ThreadUtils.assertOnGeckoThread();
      StringBuilder sb = new StringBuilder("onTextChange(");
      debugAppend(sb, text);
      sb.append(", ")
          .append(start)
          .append(", ")
          .append(unboundedOldEnd)
          .append(", ")
          .append(unboundedNewEnd)
          .append(")");
      Log.d(LOGTAG, sb.toString());
    }
    if (start < 0 || start > unboundedOldEnd) {
      Log.e(LOGTAG, "invalid text notification range: " + start + " to " + unboundedOldEnd);
      throw new IllegalArgumentException("invalid text notification range");
    }
    /* For the "end" parameters, Gecko can pass in a large
    number to denote "end of the text". Fix that here */
    final int oldEnd = unboundedOldEnd > mText.length() ? mText.length() : unboundedOldEnd;
    // new end should always match text
    if (start != 0 && unboundedNewEnd != (start + text.length())) {
      Log.e(
          LOGTAG,
          "newEnd does not match text: " + unboundedNewEnd + " vs " + (start + text.length()));
      throw new IllegalArgumentException("newEnd does not match text");
    }
    final int newEnd = start + text.length();
    final Action action = mActionQueue.peek();

    /* Text changes affect the selection as well, and we may not receive another selection
    update as a result of selection notification masking on the Gecko side; therefore,
    in order to prevent previous stale selection notifications from occurring, we need
    to increment the seqno here as well */
    ++mGeckoUpdateSeqno;

    if (action != null && action.mType == Action.TYPE_ACKNOWLEDGE_FOCUS) {
      // Simply replace the text for newly-focused editors.
      mText.replace(0, mText.length(), text);

    } else {
      mChangedText.clearSpans();
      mChangedText.replace(0, mChangedText.length(), text);
      // Preserve as many spans as possible
      TextUtils.copySpansFrom(
          mText, start, Math.min(oldEnd, newEnd), Object.class, mChangedText, 0);

      if (action != null
          && (action.mType == Action.TYPE_REPLACE_TEXT || action.mType == Action.TYPE_COMPOSE_TEXT)
          && start <= action.mStart
          && action.mStart + action.mSequence.length() <= newEnd) {

        // actionNewEnd is the new end of the original replacement action
        final int actionNewEnd = action.mStart + action.mSequence.length();
        int selStart = Selection.getSelectionStart(mText);
        int selEnd = Selection.getSelectionEnd(mText);

        // Replace old spans with new spans
        mChangedText.replace(action.mStart - start, actionNewEnd - start, action.mSequence);
        geckoReplaceText(start, oldEnd, mChangedText);

        // delete/insert above might have moved our selection to somewhere else
        // this happens when the Gecko text change covers a larger range than
        // the original replacement action. Fix selection here
        if (selStart >= start && selStart <= oldEnd) {
          selStart =
              selStart < action.mStart
                  ? selStart
                  : selStart < action.mEnd ? actionNewEnd : selStart + actionNewEnd - action.mEnd;
          mText.setSpan(Selection.SELECTION_START, selStart, selStart, Spanned.SPAN_POINT_POINT);
        }
        if (selEnd >= start && selEnd <= oldEnd) {
          selEnd =
              selEnd < action.mStart
                  ? selEnd
                  : selEnd < action.mEnd ? actionNewEnd : selEnd + actionNewEnd - action.mEnd;
          mText.setSpan(Selection.SELECTION_END, selEnd, selEnd, Spanned.SPAN_POINT_POINT);
        }

      } else {
        // Gecko side initiated the text change.
        if (isSameText(start, oldEnd, mChangedText)) {
          // Nothing to do because the text is the same.
          // This could happen when the composition is updated for example.
          return;
        }
        geckoReplaceText(start, oldEnd, mChangedText);
      }
    }

    geckoPostToIc(
        new Runnable() {
          @Override
          public void run() {
            mListener.onTextChange(text, start, oldEnd, newEnd);
          }
        });
  }