From 987189b93639f009cdbba09a4f7c83c536cb52d3 Mon Sep 17 00:00:00 2001 From: Florina Muntenescu Date: Fri, 19 Jan 2018 17:14:39 +0000 Subject: [PATCH] Make BulletSpan more flexible and update JavaDoc. Test: BulletSpanTest Bug: 72217003 Change-Id: I0ba4d93bd5a7bac02410e0edbd4b20f254959d4e --- api/current.txt | 4 + core/java/android/text/style/BulletSpan.java | 186 ++++++++++++++---- .../images/text/style/custombulletspan.png | Bin 0 -> 11949 bytes .../images/text/style/defaultbulletspan.png | Bin 0 -> 6376 bytes 4 files changed, 149 insertions(+), 41 deletions(-) create mode 100644 docs/html/reference/images/text/style/custombulletspan.png create mode 100644 docs/html/reference/images/text/style/defaultbulletspan.png diff --git a/api/current.txt b/api/current.txt index 3d8c5a64f913c..b74252ce3f6c8 100644 --- a/api/current.txt +++ b/api/current.txt @@ -43091,9 +43091,13 @@ package android.text.style { ctor public BulletSpan(); ctor public BulletSpan(int); ctor public BulletSpan(int, int); + ctor public BulletSpan(int, int, int); ctor public BulletSpan(android.os.Parcel); method public int describeContents(); method public void drawLeadingMargin(android.graphics.Canvas, android.graphics.Paint, int, int, int, int, int, java.lang.CharSequence, int, int, boolean, android.text.Layout); + method public int getBulletRadius(); + method public int getColor(); + method public int getGapWidth(); method public int getLeadingMargin(boolean); method public int getSpanTypeId(); method public void writeToParcel(android.os.Parcel, int); diff --git a/core/java/android/text/style/BulletSpan.java b/core/java/android/text/style/BulletSpan.java index 43dd0ff52e49e..70175c8611e49 100644 --- a/core/java/android/text/style/BulletSpan.java +++ b/core/java/android/text/style/BulletSpan.java @@ -16,6 +16,11 @@ package android.text.style; +import android.annotation.ColorInt; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.Px; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; @@ -26,38 +31,108 @@ import android.text.ParcelableSpan; import android.text.Spanned; import android.text.TextUtils; +/** + * A span which styles paragraphs as bullet points (respecting layout direction). + *

+ * BulletSpans must be attached from the first character to the last character of a single + * paragraph, otherwise the bullet point will not be displayed but the first paragraph encountered + * will have a leading margin. + *

+ * BulletSpans allow configuring the following elements: + *

+ * For example, a BulletSpan using the default values can be constructed like this: + *
{@code
+ *  SpannableString string = new SpannableString("Text with\nBullet point");
+ *string.setSpan(new BulletSpan(), 10, 22, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);}
+ * + *
BulletSpan constructed with default values.
+ *

+ *

+ * To construct a BulletSpan with a gap width of 40px, green bullet point and bullet radius of + * 20px: + *

{@code
+ *  SpannableString string = new SpannableString("Text with\nBullet point");
+ *string.setSpan(new BulletSpan(40, color, 20), 10, 22, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);}
+ * + *
Customized BulletSpan.
+ */ public class BulletSpan implements LeadingMarginSpan, ParcelableSpan { - private final int mGapWidth; - private final boolean mWantColor; - private final int mColor; - // Bullet is slightly bigger to avoid aliasing artifacts on mdpi devices. - private static final float BULLET_RADIUS = 3 * 1.2f; - private static Path sBulletPath = null; + private static final int STANDARD_BULLET_RADIUS = 4; public static final int STANDARD_GAP_WIDTH = 2; + private static final int STANDARD_COLOR = 0; + @Px + private final int mGapWidth; + @Px + private final int mBulletRadius; + private Path mBulletPath = null; + @ColorInt + private final int mColor; + private final boolean mWantColor; + + /** + * Creates a {@link BulletSpan} with the default values. + */ public BulletSpan() { - mGapWidth = STANDARD_GAP_WIDTH; - mWantColor = false; - mColor = 0; + this(STANDARD_GAP_WIDTH, STANDARD_COLOR, false, STANDARD_BULLET_RADIUS); } + /** + * Creates a {@link BulletSpan} based on a gap width + * + * @param gapWidth the distance, in pixels, between the bullet point and the paragraph. + */ public BulletSpan(int gapWidth) { - mGapWidth = gapWidth; - mWantColor = false; - mColor = 0; + this(gapWidth, STANDARD_COLOR, false, STANDARD_BULLET_RADIUS); } - public BulletSpan(int gapWidth, int color) { + /** + * Creates a {@link BulletSpan} based on a gap width and a color integer. + * + * @param gapWidth the distance, in pixels, between the bullet point and the paragraph. + * @param color the bullet point color, as a color integer + * @see android.content.res.Resources#getColor(int, Resources.Theme) + */ + public BulletSpan(int gapWidth, @ColorInt int color) { + this(gapWidth, color, true, STANDARD_BULLET_RADIUS); + } + + /** + * Creates a {@link BulletSpan} based on a gap width and a color integer. + * + * @param gapWidth the distance, in pixels, between the bullet point and the paragraph. + * @param color the bullet point color, as a color integer. + * @param bulletRadius the radius of the bullet point, in pixels. + * @see android.content.res.Resources#getColor(int, Resources.Theme) + */ + public BulletSpan(int gapWidth, @ColorInt int color, @IntRange(from = 0) int bulletRadius) { + this(gapWidth, color, true, bulletRadius); + } + + private BulletSpan(int gapWidth, @ColorInt int color, boolean wantColor, + @IntRange(from = 0) int bulletRadius) { mGapWidth = gapWidth; - mWantColor = true; + mBulletRadius = bulletRadius; mColor = color; + mWantColor = wantColor; } - public BulletSpan(Parcel src) { + /** + * Creates a {@link BulletSpan} from a parcel. + */ + public BulletSpan(@NonNull Parcel src) { mGapWidth = src.readInt(); mWantColor = src.readInt() != 0; mColor = src.readInt(); + mBulletRadius = src.readInt(); } @Override @@ -77,68 +152,97 @@ public class BulletSpan implements LeadingMarginSpan, ParcelableSpan { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { writeToParcelInternal(dest, flags); } /** @hide */ @Override - public void writeToParcelInternal(Parcel dest, int flags) { + public void writeToParcelInternal(@NonNull Parcel dest, int flags) { dest.writeInt(mGapWidth); dest.writeInt(mWantColor ? 1 : 0); dest.writeInt(mColor); + dest.writeInt(mBulletRadius); } @Override public int getLeadingMargin(boolean first) { - return (int) (2 * BULLET_RADIUS + mGapWidth); + return 2 * mBulletRadius + mGapWidth; + } + + /** + * Get the distance, in pixels, between the bullet point and the paragraph. + * + * @return the distance, in pixels, between the bullet point and the paragraph. + */ + public int getGapWidth() { + return mGapWidth; + } + + /** + * Get the radius, in pixels, of the bullet point. + * + * @return the radius, in pixels, of the bullet point. + */ + public int getBulletRadius() { + return mBulletRadius; + } + + /** + * Get the bullet point color. + * + * @return the bullet point color + */ + public int getColor() { + return mColor; } @Override - public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, - int top, int baseline, int bottom, - CharSequence text, int start, int end, - boolean first, Layout l) { + public void drawLeadingMargin(@NonNull Canvas canvas, @NonNull Paint paint, int x, int dir, + int top, int baseline, int bottom, + @NonNull CharSequence text, int start, int end, + boolean first, @Nullable Layout layout) { if (((Spanned) text).getSpanStart(this) == start) { - Paint.Style style = p.getStyle(); + Paint.Style style = paint.getStyle(); int oldcolor = 0; if (mWantColor) { - oldcolor = p.getColor(); - p.setColor(mColor); + oldcolor = paint.getColor(); + paint.setColor(mColor); } - p.setStyle(Paint.Style.FILL); + paint.setStyle(Paint.Style.FILL); - if (l != null) { + if (layout != null) { // "bottom" position might include extra space as a result of line spacing // configuration. Subtract extra space in order to show bullet in the vertical // center of characters. - final int line = l.getLineForOffset(start); - bottom = bottom - l.getLineExtra(line); + final int line = layout.getLineForOffset(start); + bottom = bottom - layout.getLineExtra(line); } - final float y = (top + bottom) / 2f; + final float yPosition = (top + bottom) / 2f; + final float xPosition = x + dir * mBulletRadius; - if (c.isHardwareAccelerated()) { - if (sBulletPath == null) { - sBulletPath = new Path(); - sBulletPath.addCircle(0.0f, 0.0f, BULLET_RADIUS, Direction.CW); + if (canvas.isHardwareAccelerated()) { + if (mBulletPath == null) { + mBulletPath = new Path(); + mBulletPath.addCircle(0.0f, 0.0f, mBulletRadius, Direction.CW); } - c.save(); - c.translate(x + dir * BULLET_RADIUS, y); - c.drawPath(sBulletPath, p); - c.restore(); + canvas.save(); + canvas.translate(xPosition, yPosition); + canvas.drawPath(mBulletPath, paint); + canvas.restore(); } else { - c.drawCircle(x + dir * BULLET_RADIUS, y, BULLET_RADIUS, p); + canvas.drawCircle(xPosition, yPosition, mBulletRadius, paint); } if (mWantColor) { - p.setColor(oldcolor); + paint.setColor(oldcolor); } - p.setStyle(style); + paint.setStyle(style); } } } diff --git a/docs/html/reference/images/text/style/custombulletspan.png b/docs/html/reference/images/text/style/custombulletspan.png new file mode 100644 index 0000000000000000000000000000000000000000..251f8a13c0771c87174767c4dd1f295232557cd7 GIT binary patch literal 11949 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 G4ftOvu7gDY literal 0 HcmV?d00001 diff --git a/docs/html/reference/images/text/style/defaultbulletspan.png b/docs/html/reference/images/text/style/defaultbulletspan.png new file mode 100644 index 0000000000000000000000000000000000000000..854143f8e7dccd32991f21610c4e3a996c798eff GIT binary patch literal 6376 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 literal 0 HcmV?d00001