OSDN Git Service

Add left and right indent arrays to TextView
authorRaph Levien <raph@google.com>
Wed, 15 Apr 2015 06:51:07 +0000 (23:51 -0700)
committerRaph Levien <raph@google.com>
Thu, 16 Apr 2015 01:57:53 +0000 (18:57 -0700)
In support of layout of paragraphs to non-rectangular regions, add
arrays for left and right indents to TextView, along with supporting
StaticLayout builder setters.

Bug: 20182243
Change-Id: I015bcef8f258c89001fcf8a54c179d2dfc0d7943

api/current.txt
api/system-current.txt
core/java/android/text/StaticLayout.java
core/java/android/widget/TextView.java
core/jni/android_text_StaticLayout.cpp
core/res/res/values/attrs.xml
core/res/res/values/public.xml

index 3a23b0f..e8d49c3 100644 (file)
@@ -793,6 +793,7 @@ package android {
     field public static final int layout_x = 16843135; // 0x101017f
     field public static final int layout_y = 16843136; // 0x1010180
     field public static final int left = 16843181; // 0x10101ad
+    field public static final int leftIndents = 16844016; // 0x10104f0
     field public static final int letterSpacing = 16843958; // 0x10104b6
     field public static final int lineSpacingExtra = 16843287; // 0x1010217
     field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
@@ -1021,6 +1022,7 @@ package android {
     field public static final int reversible = 16843851; // 0x101044b
     field public static final int revisionCode = 16843989; // 0x10104d5
     field public static final int right = 16843183; // 0x10101af
+    field public static final int rightIndents = 16844017; // 0x10104f1
     field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
     field public static final int ringtoneType = 16843257; // 0x10101f9
     field public static final int rotation = 16843558; // 0x1010326
@@ -41225,6 +41227,7 @@ package android.widget {
     method public int getInputType();
     method public final android.text.method.KeyListener getKeyListener();
     method public final android.text.Layout getLayout();
+    method public int[] getLeftIndents();
     method public float getLetterSpacing();
     method public int getLineBounds(int, android.graphics.Rect);
     method public int getLineCount();
@@ -41247,6 +41250,7 @@ package android.widget {
     method public android.text.TextPaint getPaint();
     method public int getPaintFlags();
     method public java.lang.String getPrivateImeOptions();
+    method public int[] getRightIndents();
     method public int getSelectionEnd();
     method public int getSelectionStart();
     method public int getShadowColor();
@@ -41324,6 +41328,7 @@ package android.widget {
     method public void setImeActionLabel(java.lang.CharSequence, int);
     method public void setImeOptions(int);
     method public void setIncludeFontPadding(boolean);
+    method public void setIndents(int[], int[]);
     method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public void setInputType(int);
     method public void setKeyListener(android.text.method.KeyListener);
index ef3d3df..0bc83c3 100644 (file)
@@ -866,6 +866,7 @@ package android {
     field public static final int layout_x = 16843135; // 0x101017f
     field public static final int layout_y = 16843136; // 0x1010180
     field public static final int left = 16843181; // 0x10101ad
+    field public static final int leftIndents = 16844016; // 0x10104f0
     field public static final int letterSpacing = 16843958; // 0x10104b6
     field public static final int lineSpacingExtra = 16843287; // 0x1010217
     field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
@@ -1094,6 +1095,7 @@ package android {
     field public static final int reversible = 16843851; // 0x101044b
     field public static final int revisionCode = 16843989; // 0x10104d5
     field public static final int right = 16843183; // 0x10101af
+    field public static final int rightIndents = 16844017; // 0x10104f1
     field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
     field public static final int ringtoneType = 16843257; // 0x10101f9
     field public static final int rotation = 16843558; // 0x1010326
@@ -43692,6 +43694,7 @@ package android.widget {
     method public int getInputType();
     method public final android.text.method.KeyListener getKeyListener();
     method public final android.text.Layout getLayout();
+    method public int[] getLeftIndents();
     method public float getLetterSpacing();
     method public int getLineBounds(int, android.graphics.Rect);
     method public int getLineCount();
@@ -43714,6 +43717,7 @@ package android.widget {
     method public android.text.TextPaint getPaint();
     method public int getPaintFlags();
     method public java.lang.String getPrivateImeOptions();
+    method public int[] getRightIndents();
     method public int getSelectionEnd();
     method public int getSelectionStart();
     method public int getShadowColor();
@@ -43791,6 +43795,7 @@ package android.widget {
     method public void setImeActionLabel(java.lang.CharSequence, int);
     method public void setImeOptions(int);
     method public void setIncludeFontPadding(boolean);
+    method public void setIndents(int[], int[]);
     method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public void setInputType(int);
     method public void setKeyListener(android.text.method.KeyListener);
index 7828851..67794b1 100644 (file)
@@ -165,6 +165,19 @@ public class StaticLayout extends Layout {
             return this;
         }
 
+        public Builder setIndents(int[] leftIndents, int[] rightIndents) {
+            int leftLen = leftIndents == null ? 0 : leftIndents.length;
+            int rightLen = rightIndents == null ? 0 : rightIndents.length;
+            int[] indents = new int[Math.max(leftLen, rightLen)];
+            for (int i = 0; i < indents.length; i++) {
+                int leftMargin = i < leftLen ? leftIndents[i] : 0;
+                int rightMargin = i < rightLen ? rightIndents[i] : 0;
+                indents[i] = leftMargin + rightMargin;
+            }
+            nSetIndents(mNativePtr, indents);
+            return this;
+        }
+
         /**
          * Measurement and break iteration is done in native code. The protocol for using
          * the native code is as follows.
@@ -1009,6 +1022,8 @@ public class StaticLayout extends Layout {
 
     private static native void nSetLocale(long nativePtr, String locale, long nativeHyphenator);
 
+    private static native void nSetIndents(long nativePtr, int[] indents);
+
     // Set up paragraph text and settings; done as one big method to minimize jni crossings
     private static native void nSetupParagraph(long nativePtr, char[] text, int length,
             float firstWidth, int firstWidthLineCount, float restWidth,
index b44a886..0854eef 100644 (file)
@@ -236,6 +236,9 @@ import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
  * @attr ref android.R.styleable#TextView_elegantTextHeight
  * @attr ref android.R.styleable#TextView_letterSpacing
  * @attr ref android.R.styleable#TextView_fontFeatureSettings
+ * @attr ref android.R.styleable#TextView_breakStrategy
+ * @attr ref android.R.styleable#TextView_leftIndents
+ * @attr ref android.R.styleable#TextView_rightIndents
  */
 @RemoteView
 public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
@@ -551,6 +554,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     private float mSpacingAdd = 0.0f;
 
     private int mBreakStrategy;
+    private int[] mLeftIndents;
+    private int[] mRightIndents;
 
     private int mMaximum = Integer.MAX_VALUE;
     private int mMaxMode = LINES;
@@ -1146,6 +1151,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
 
             case com.android.internal.R.styleable.TextView_breakStrategy:
                 mBreakStrategy = a.getInt(attr, Layout.BREAK_STRATEGY_SIMPLE);
+                break;
+
+            case com.android.internal.R.styleable.TextView_leftIndents:
+                TypedArray margins = res.obtainTypedArray(a.getResourceId(attr, View.NO_ID));
+                mLeftIndents = parseDimensionArray(margins);
+                break;
+
+            case com.android.internal.R.styleable.TextView_rightIndents:
+                margins = res.obtainTypedArray(a.getResourceId(attr, View.NO_ID));
+                mRightIndents = parseDimensionArray(margins);
+                break;
             }
         }
         a.recycle();
@@ -1421,6 +1437,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
         }
     }
 
+    private int[] parseDimensionArray(TypedArray dimens) {
+        if (dimens == null) {
+            return null;
+        }
+        int[] result = new int[dimens.length()];
+        for (int i = 0; i < result.length; i++) {
+            result[i] = dimens.getDimensionPixelSize(i, 0);
+        }
+        return result;
+    }
+
     /**
      * @hide
      */
@@ -3019,6 +3046,51 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     }
 
     /**
+     * Set indents. Arguments are arrays holding an indent amount, one per line, measured in
+     * pixels. For lines past the last element in the array, the last element repeats.
+     *
+     * @param leftIndents array of indent values for left margin, in pixels
+     * @param rightIndents array of indent values for right margin, in pixels
+     *
+     * @see #getLeftIndents()
+     * @see #getRightIndents()
+     *
+     * @attr ref android.R.styleable#TextView_leftIndents
+     * @attr ref android.R.styleable#TextView_rightIndents
+     */
+    public void setIndents(@Nullable int[] leftIndents, @Nullable int[] rightIndents) {
+        mLeftIndents = leftIndents;
+        mRightIndents = rightIndents;
+        if (mLayout != null) {
+            nullLayouts();
+            requestLayout();
+            invalidate();
+        }
+    }
+
+    /**
+     * Get left indents. See {#link setMargins} for more details.
+     *
+     * @return left indents
+     * @see #setIndents(int[], int[])
+     * @attr ref android.R.styleable#TextView_leftIndents
+     */
+    public int[] getLeftIndents() {
+        return mLeftIndents;
+    }
+
+    /**
+     * Get right indents. See {#link setMargins} for more details.
+     *
+     * @return right indents
+     * @see #setIndents(int[], int[])
+     * @attr ref android.R.styleable#TextView_rightIndents
+     */
+    public int[] getRightIndents() {
+        return mRightIndents;
+    }
+
+    /**
      * Sets font feature settings.  The format is the same as the CSS
      * font-feature-settings attribute:
      * http://dev.w3.org/csswg/css-fonts/#propdef-font-feature-settings
@@ -6564,6 +6636,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                         .setSpacingAdd(mSpacingAdd)
                         .setIncludePad(mIncludePad)
                         .setBreakStrategy(mBreakStrategy);
+                if (mLeftIndents != null || mRightIndents != null) {
+                    builder.setIndents(mLeftIndents, mRightIndents);
+                }
                 if (shouldEllipsize) {
                     builder.setEllipsize(mEllipsize)
                             .setEllipsizedWidth(ellipsisWidth)
@@ -6652,6 +6727,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                     .setSpacingAdd(mSpacingAdd)
                     .setIncludePad(mIncludePad)
                     .setBreakStrategy(mBreakStrategy);
+            if (mLeftIndents != null || mRightIndents != null) {
+                builder.setIndents(mLeftIndents, mRightIndents);
+            }
             if (shouldEllipsize) {
                 builder.setEllipsize(effectiveEllipsize)
                         .setEllipsizedWidth(ellipsisWidth)
index 87c58d6..5e73ef2 100644 (file)
@@ -132,6 +132,13 @@ static void nSetLocale(JNIEnv* env, jclass, jlong nativePtr, jstring javaLocaleN
     }
 }
 
+static void nSetIndents(JNIEnv* env, jclass, jlong nativePtr, jintArray indents) {
+    ScopedIntArrayRO indentArr(env, indents);
+    std::vector<float> indentVec(indentArr.get(), indentArr.get() + indentArr.size());
+    LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr);
+    b->setIndents(indentVec);
+}
+
 // Basically similar to Paint.getTextRunAdvances but with C++ interface
 static jfloat nAddStyleRun(JNIEnv* env, jclass, jlong nativePtr,
         jlong nativePaint, jlong nativeTypeface, jint start, jint end, jboolean isRtl) {
@@ -171,6 +178,7 @@ static JNINativeMethod gMethods[] = {
     {"nLoadHyphenator", "(Ljava/lang/String;)J", (void*) nLoadHyphenator},
     {"nSetLocale", "(JLjava/lang/String;J)V", (void*) nSetLocale},
     {"nSetupParagraph", "(J[CIFIF[III)V", (void*) nSetupParagraph},
+    {"nSetIndents", "(J[I)V", (void*) nSetIndents},
     {"nAddStyleRun", "(JJJIIZ)F", (void*) nAddStyleRun},
     {"nAddMeasuredRun", "(JII[F)V", (void*) nAddMeasuredRun},
     {"nAddReplacementRun", "(JIIF)V", (void*) nAddReplacementRun},
index a623d0c..674c695 100644 (file)
             <!-- Line breaking stratgegy balances line lengths. -->
             <enum name="balanced" value="2" />
         </attr>
+        <!-- Array of indents, one dimension value per line, left side. -->
+        <attr name="leftIndents" format="reference" />
+        <!-- Array of indents, one dimension value per line, right side. -->
+        <attr name="rightIndents" format="reference" />
     </declare-styleable>
     <declare-styleable name="TextViewAppearance">
         <!-- Base text color, typeface, size, and style. -->
index 8806869..282c80b 100644 (file)
   <public type="attr" name="durationScaleHint" />
 
   <public type="attr" name="lockTaskMode" />
+
+  <public type="attr" name="leftIndents" />
+  <public type="attr" name="rightIndents" />
 </resources>