Repository: incubator-weex
Updated Branches:
  refs/heads/0.16-dev 8b9845ebe -> c95fc2325


* [android] Refactor the process of lines style in text.


Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/86c2a7d6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/86c2a7d6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/86c2a7d6

Branch: refs/heads/0.16-dev
Commit: 86c2a7d60e1e506b7c448fb5e83b6ecc00c5b697
Parents: 92a1616
Author: YorkShen <shenyua...@gmail.com>
Authored: Fri Jul 21 14:43:25 2017 +0800
Committer: YorkShen <shenyua...@gmail.com>
Committed: Fri Jul 21 14:43:25 2017 +0800

----------------------------------------------------------------------
 .../com/taobao/weex/dom/WXTextDomObject.java    | 91 +++++++++++++-------
 1 file changed, 60 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/86c2a7d6/android/sdk/src/main/java/com/taobao/weex/dom/WXTextDomObject.java
----------------------------------------------------------------------
diff --git a/android/sdk/src/main/java/com/taobao/weex/dom/WXTextDomObject.java 
b/android/sdk/src/main/java/com/taobao/weex/dom/WXTextDomObject.java
index fe06b06..06084a9 100644
--- a/android/sdk/src/main/java/com/taobao/weex/dom/WXTextDomObject.java
+++ b/android/sdk/src/main/java/com/taobao/weex/dom/WXTextDomObject.java
@@ -18,22 +18,26 @@
  */
 package com.taobao.weex.dom;
 
+import static com.taobao.weex.dom.WXStyle.UNSET;
+
 import android.graphics.Canvas;
 import android.graphics.Typeface;
 import android.os.Build;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.text.Editable;
 import android.text.Layout;
 import android.text.Spannable;
 import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
 import android.text.Spanned;
+import android.text.SpannedString;
 import android.text.StaticLayout;
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.text.style.AbsoluteSizeSpan;
 import android.text.style.AlignmentSpan;
 import android.text.style.ForegroundColorSpan;
-
 import com.taobao.weex.WXEnvironment;
 import com.taobao.weex.common.Constants;
 import com.taobao.weex.dom.flex.CSSConstants;
@@ -45,15 +49,12 @@ import com.taobao.weex.ui.component.WXTextDecoration;
 import com.taobao.weex.utils.WXDomUtils;
 import com.taobao.weex.utils.WXLogUtils;
 import com.taobao.weex.utils.WXResourceUtils;
-
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 
-import static com.taobao.weex.dom.WXStyle.UNSET;
-
 /**
  * Class for calculating a given text's height and width. The calculating of 
width and height of
  * text is done by {@link Layout}.
@@ -299,7 +300,7 @@ public class WXTextDomObject extends WXDomObject {
     Layout layout;
     if (!FloatUtil.floatsEqual(previousWidth, textWidth) || previousLayout == 
null) {
       layout = new StaticLayout(spanned, mTextPaint, (int) 
Math.ceil(textWidth),
-                                Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
+          Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
     } else {
       layout = previousLayout;
     }
@@ -308,37 +309,65 @@ public class WXTextDomObject extends WXDomObject {
       lastLineStart = layout.getLineStart(mNumberOfLines - 1);
       lastLineEnd = layout.getLineEnd(mNumberOfLines - 1);
       if (lastLineStart < lastLineEnd) {
-        String text = mText.subSequence(0, lastLineStart).toString() +
-                               truncate(mText.substring(lastLineStart, 
lastLineEnd),
-                                        mTextPaint, layout.getWidth(), 
textOverflow);
-        spanned = createSpanned(text);
+        SpannableStringBuilder builder = new 
SpannableStringBuilder(spanned.subSequence(0, lastLineStart));
+        Editable lastLine = new 
SpannableStringBuilder(spanned.subSequence(lastLineStart, lastLineEnd));
+        builder.append(truncate(lastLine, mTextPaint, layout.getWidth(), 
textOverflow));
+        adjustSpansRange(spanned, builder);
+        spanned = builder;
         return new StaticLayout(spanned, mTextPaint, (int) 
Math.ceil(textWidth),
-                                Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
+            Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
       }
     }
     return layout;
   }
 
-  public @NonNull String truncate(@Nullable String source, @NonNull TextPaint 
paint,
-                                  int desired, @Nullable TextUtils.TruncateAt 
truncateAt){
-    if(!TextUtils.isEmpty(source)){
-      StringBuilder builder;
-      Spanned spanned;
+  /**
+   * Truncate the source span to the specified lines.
+   * Caller of this method must ensure that the lines of text is 
<strong>greater than desired lines and need truncate</strong>.
+   * Otherwise, unexpected behavior may happen.
+   * @param source The source span.
+   * @param paint the textPaint
+   * @param desired specified lines.
+   * @param truncateAt truncate method, null value means clipping overflow 
text directly, non-null value means using ellipsis strategy to clip
+   * @return The spans after clipped.
+   */
+  private
+  @NonNull
+  Spanned truncate(@Nullable Editable source, @NonNull TextPaint paint,
+      int desired, @Nullable TextUtils.TruncateAt truncateAt) {
+    Spanned ret = new SpannedString("");
+    if (!TextUtils.isEmpty(source) && source.length() > 0) {
       StaticLayout layout;
-      for(int i=source.length();i>0;i--){
-        builder=new StringBuilder(i+1);
-        builder.append(source, 0, i);
-        if(truncateAt!=null){
-          builder.append(ELLIPSIS);
-        }
-        spanned = createSpanned(builder.toString());
-        layout = new StaticLayout(spanned, paint, desired, 
Layout.Alignment.ALIGN_NORMAL, 1, 0, true);
-        if(layout.getLineCount()<=1){
-          return spanned.toString();
+      if (truncateAt != null) {
+        source.append(ELLIPSIS);
+      }
+      while (source.length() > 1) {
+        source.delete(source.length() - 2, source.length() - 1);
+        layout = new StaticLayout(source, paint, desired, 
Layout.Alignment.ALIGN_NORMAL, 1, 0, true);
+        if (layout.getLineCount() <= 1) {
+          ret = source;
+          break;
         }
       }
     }
-    return "";
+    return ret;
+  }
+
+  /**
+   * Adjust span range after truncate due to the wrong span range during span 
copy and slicing.
+   * @param beforeTruncate The span before truncate
+   * @param afterTruncate The span after truncate
+   */
+  private void adjustSpansRange(@NonNull Spanned beforeTruncate, @NonNull 
Spannable afterTruncate){
+    Object[] spans = beforeTruncate.getSpans(0, beforeTruncate.length(), 
Object.class);
+    for(Object span:spans){
+      int start = beforeTruncate.getSpanStart(span);
+      int end = beforeTruncate.getSpanEnd(span);
+      if(start == 0 && end == beforeTruncate.length()){
+        afterTruncate.removeSpan(span);
+        afterTruncate.setSpan(span, 0, afterTruncate.length(), 
beforeTruncate.getSpanFlags(span));
+      }
+    }
   }
 
   /**
@@ -350,7 +379,7 @@ public class WXTextDomObject extends WXDomObject {
    * @return if forceToDesired is false, it will be the minimum value of the 
width of text and
    * outerWidth in case of outerWidth is defined, in other case, it will be 
outer width.
    */
-  /** package **/ float getTextWidth(TextPaint textPaint,float outerWidth, 
boolean forceToDesired) {
+   float getTextWidth(TextPaint textPaint,float outerWidth, boolean 
forceToDesired) {
     float textWidth;
     if (forceToDesired) {
       textWidth = outerWidth;
@@ -385,7 +414,7 @@ public class WXTextDomObject extends WXDomObject {
     List<SetSpanOperation> ops = createSetSpanOperation(spannable.length(), 
spanFlag);
     if (mFontSize == UNSET) {
       ops.add(new SetSpanOperation(0, spannable.length(),
-                                   new AbsoluteSizeSpan(WXText.sDEFAULT_SIZE), 
spanFlag));
+          new AbsoluteSizeSpan(WXText.sDEFAULT_SIZE), spanFlag));
     }
     Collections.reverse(ops);
     for (SetSpanOperation op : ops) {
@@ -408,7 +437,7 @@ public class WXTextDomObject extends WXDomObject {
       }
       if (mIsColorSet) {
         ops.add(new SetSpanOperation(start, end,
-                                     new ForegroundColorSpan(mColor), 
spanFlag));
+            new ForegroundColorSpan(mColor), spanFlag));
       }
       if (mFontSize != UNSET) {
         ops.add(new SetSpanOperation(start, end, new 
AbsoluteSizeSpan(mFontSize), spanFlag));
@@ -417,8 +446,8 @@ public class WXTextDomObject extends WXDomObject {
           || mFontWeight != UNSET
           || mFontFamily != null) {
         ops.add(new SetSpanOperation(start, end,
-                                     new WXCustomStyleSpan(mFontStyle, 
mFontWeight, mFontFamily),
-                                     spanFlag));
+            new WXCustomStyleSpan(mFontStyle, mFontWeight, mFontFamily),
+            spanFlag));
       }
       ops.add(new SetSpanOperation(start, end, new 
AlignmentSpan.Standard(mAlignment), spanFlag));
       if (mLineHeight != UNSET) {

Reply via email to