diff options
19 files changed, 501 insertions, 146 deletions
diff --git a/core/java/android/text/style/DrawableMarginSpan.java b/core/java/android/text/style/DrawableMarginSpan.java index 35241796c3c3..cd199b3547c9 100644 --- a/core/java/android/text/style/DrawableMarginSpan.java +++ b/core/java/android/text/style/DrawableMarginSpan.java @@ -16,60 +16,100 @@ package android.text.style; +import android.annotation.NonNull; +import android.annotation.Px; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.text.Layout; import android.text.Spanned; -public class DrawableMarginSpan -implements LeadingMarginSpan, LineHeightSpan -{ - public DrawableMarginSpan(Drawable b) { - mDrawable = b; +/** + * A span which adds a drawable and a padding to the paragraph it's attached to. + * <p> + * If the height of the drawable is bigger than the height of the line it's attached to then the + * line height is increased to fit the drawable. <code>DrawableMarginSpan</code> allows setting a + * padding between the drawable and the text. The default value is 0. The span must be set from the + * beginning of the text, otherwise either the span won't be rendered or it will be rendered + * incorrectly. + * <p> + * For example, a drawable and a padding of 20px can be added like this: + * <pre>{@code SpannableString string = new SpannableString("Text with a drawable."); + * string.setSpan(new DrawableMarginSpan(drawable, 20), 0, string.length(), + * Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);}</pre> + * <img src="{@docRoot}reference/android/images/text/style/drawablemarginspan.png" /> + * <figcaption>Text with a drawable and a padding.</figcaption> + * <p> + * + * @see IconMarginSpan for working with a {@link android.graphics.Bitmap} instead of + * a {@link Drawable}. + */ +public class DrawableMarginSpan implements LeadingMarginSpan, LineHeightSpan { + private static final int STANDARD_PAD_WIDTH = 0; + + @NonNull + private final Drawable mDrawable; + @Px + private final int mPad; + + /** + * Creates a {@link DrawableMarginSpan} from a {@link Drawable}. The pad width will be 0. + * + * @param drawable the drawable to be added + */ + public DrawableMarginSpan(@NonNull Drawable drawable) { + this(drawable, STANDARD_PAD_WIDTH); } - public DrawableMarginSpan(Drawable b, int pad) { - mDrawable = b; + /** + * Creates a {@link DrawableMarginSpan} from a {@link Drawable} and a padding, in pixels. + * + * @param drawable the drawable to be added + * @param pad the distance between the drawable and the text + */ + public DrawableMarginSpan(@NonNull Drawable drawable, int pad) { + mDrawable = drawable; mPad = pad; } + @Override public int getLeadingMargin(boolean first) { return mDrawable.getIntrinsicWidth() + mPad; } - 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 layout) { + @Override + public void drawLeadingMargin(@NonNull Canvas c, @NonNull Paint p, int x, int dir, + int top, int baseline, int bottom, + @NonNull CharSequence text, int start, int end, + boolean first, @NonNull Layout layout) { int st = ((Spanned) text).getSpanStart(this); - int ix = (int)x; - int itop = (int)layout.getLineTop(layout.getLineForOffset(st)); + int ix = (int) x; + int itop = (int) layout.getLineTop(layout.getLineForOffset(st)); int dw = mDrawable.getIntrinsicWidth(); int dh = mDrawable.getIntrinsicHeight(); // XXX What to do about Paint? - mDrawable.setBounds(ix, itop, ix+dw, itop+dh); + mDrawable.setBounds(ix, itop, ix + dw, itop + dh); mDrawable.draw(c); } - public void chooseHeight(CharSequence text, int start, int end, - int istartv, int v, - Paint.FontMetricsInt fm) { + @Override + public void chooseHeight(@NonNull CharSequence text, int start, int end, + int istartv, int v, + @NonNull Paint.FontMetricsInt fm) { if (end == ((Spanned) text).getSpanEnd(this)) { int ht = mDrawable.getIntrinsicHeight(); int need = ht - (v + fm.descent - fm.ascent - istartv); - if (need > 0) + if (need > 0) { fm.descent += need; + } need = ht - (v + fm.bottom - fm.top - istartv); - if (need > 0) + if (need > 0) { fm.bottom += need; + } } } - - private Drawable mDrawable; - private int mPad; } diff --git a/core/java/android/text/style/DynamicDrawableSpan.java b/core/java/android/text/style/DynamicDrawableSpan.java index 5b8a6dd3bf6f..1b16f3345bfa 100644 --- a/core/java/android/text/style/DynamicDrawableSpan.java +++ b/core/java/android/text/style/DynamicDrawableSpan.java @@ -16,6 +16,9 @@ package android.text.style; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; @@ -24,32 +27,71 @@ import android.graphics.drawable.Drawable; import java.lang.ref.WeakReference; /** + * Span that replaces the text it's attached to with a {@link Drawable} that can be aligned with + * the bottom or with the baseline of the surrounding text. + * <p> + * For an implementation that constructs the drawable from various sources (<code>Bitmap</code>, + * <code>Drawable</code>, resource id or <code>Uri</code>) use {@link ImageSpan}. + * <p> + * A simple implementation of <code>DynamicDrawableSpan</code> that uses drawables from resources + * looks like this: + * <pre> + * class MyDynamicDrawableSpan extends DynamicDrawableSpan { * + * private final Context mContext; + * private final int mResourceId; + * + * public MyDynamicDrawableSpan(Context context, @DrawableRes int resourceId) { + * mContext = context; + * mResourceId = resourceId; + * } + * + * {@literal @}Override + * public Drawable getDrawable() { + * Drawable drawable = mContext.getDrawable(mResourceId); + * drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); + * return drawable; + * } + * }</pre> + * The class can be used like this: + * <pre> + * SpannableString string = new SpannableString("Text with a drawable span"); + * string.setSpan(new MyDynamicDrawableSpan(context, R.mipmap.ic_launcher), 12, 20, Spanned + * .SPAN_EXCLUSIVE_EXCLUSIVE);</pre> + * <img src="{@docRoot}reference/android/images/text/style/dynamicdrawablespan.png" /> + * <figcaption>Replacing text with a drawable.</figcaption> */ public abstract class DynamicDrawableSpan extends ReplacementSpan { - private static final String TAG = "DynamicDrawableSpan"; - + /** * A constant indicating that the bottom of this span should be aligned * with the bottom of the surrounding text, i.e., at the same level as the * lowest descender in the text. */ public static final int ALIGN_BOTTOM = 0; - + /** * A constant indicating that the bottom of this span should be aligned * with the baseline of the surrounding text. */ public static final int ALIGN_BASELINE = 1; - + protected final int mVerticalAlignment; - + + private WeakReference<Drawable> mDrawableRef; + + /** + * Creates a {@link DynamicDrawableSpan}. The default vertical alignment is + * {@link #ALIGN_BOTTOM} + */ public DynamicDrawableSpan() { mVerticalAlignment = ALIGN_BOTTOM; } /** - * @param verticalAlignment one of {@link #ALIGN_BOTTOM} or {@link #ALIGN_BASELINE}. + * Creates a {@link DynamicDrawableSpan} based on a vertical alignment.\ + * + * @param verticalAlignment one of {@link #ALIGN_BOTTOM} or {@link #ALIGN_BASELINE} */ protected DynamicDrawableSpan(int verticalAlignment) { mVerticalAlignment = verticalAlignment; @@ -64,22 +106,22 @@ public abstract class DynamicDrawableSpan extends ReplacementSpan { } /** - * Your subclass must implement this method to provide the bitmap + * Your subclass must implement this method to provide the bitmap * to be drawn. The dimensions of the bitmap must be the same * from each call to the next. */ public abstract Drawable getDrawable(); @Override - public int getSize(Paint paint, CharSequence text, - int start, int end, - Paint.FontMetricsInt fm) { + public int getSize(@NonNull Paint paint, CharSequence text, + @IntRange(from = 0) int start, @IntRange(from = 0) int end, + @Nullable Paint.FontMetricsInt fm) { Drawable d = getCachedDrawable(); Rect rect = d.getBounds(); if (fm != null) { - fm.ascent = -rect.bottom; - fm.descent = 0; + fm.ascent = -rect.bottom; + fm.descent = 0; fm.top = fm.ascent; fm.bottom = 0; @@ -89,12 +131,12 @@ public abstract class DynamicDrawableSpan extends ReplacementSpan { } @Override - public void draw(Canvas canvas, CharSequence text, - int start, int end, float x, - int top, int y, int bottom, Paint paint) { + public void draw(@NonNull Canvas canvas, CharSequence text, + @IntRange(from = 0) int start, @IntRange(from = 0) int end, float x, + int top, int y, int bottom, @NonNull Paint paint) { Drawable b = getCachedDrawable(); canvas.save(); - + int transY = bottom - b.getBounds().bottom; if (mVerticalAlignment == ALIGN_BASELINE) { transY -= paint.getFontMetricsInt().descent; @@ -109,8 +151,9 @@ public abstract class DynamicDrawableSpan extends ReplacementSpan { WeakReference<Drawable> wr = mDrawableRef; Drawable d = null; - if (wr != null) + if (wr != null) { d = wr.get(); + } if (d == null) { d = getDrawable(); @@ -119,7 +162,5 @@ public abstract class DynamicDrawableSpan extends ReplacementSpan { return d; } - - private WeakReference<Drawable> mDrawableRef; } diff --git a/core/java/android/text/style/IconMarginSpan.java b/core/java/android/text/style/IconMarginSpan.java index 304c83f19f02..ad78bd574696 100644 --- a/core/java/android/text/style/IconMarginSpan.java +++ b/core/java/android/text/style/IconMarginSpan.java @@ -16,57 +16,98 @@ package android.text.style; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Px; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.text.Layout; import android.text.Spanned; -public class IconMarginSpan -implements LeadingMarginSpan, LineHeightSpan -{ - public IconMarginSpan(Bitmap b) { - mBitmap = b; +/** + * Paragraph affecting span, that draws a bitmap at the beginning of a text. The span also allows + * setting a padding between the bitmap and the text. The default value of the padding is 0px. The + * span should be attached from the first character of the text. + * <p> + * For example, an <code>IconMarginSpan</code> with a bitmap and a padding of 30px can be set + * like this: + * <pre> + * SpannableString string = new SpannableString("Text with icon and padding"); + * string.setSpan(new IconMarginSpan(bitmap, 30), 0, string.length(), + * Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + * </pre> + * <img src="{@docRoot}reference/android/images/text/style/iconmarginspan.png" /> + * <figcaption>Text with <code>IconMarginSpan</code></figcaption> + * <p> + * + * @see DrawableMarginSpan for working with a {@link android.graphics.drawable.Drawable} instead of + * a {@link Bitmap}. + */ +public class IconMarginSpan implements LeadingMarginSpan, LineHeightSpan { + + @NonNull + private final Bitmap mBitmap; + @Px + private final int mPad; + + /** + * Creates an {@link IconMarginSpan} from a {@link Bitmap}. + * + * @param bitmap bitmap to be rendered at the beginning of the text + */ + public IconMarginSpan(@NonNull Bitmap bitmap) { + this(bitmap, 0); } - public IconMarginSpan(Bitmap b, int pad) { - mBitmap = b; + /** + * Creates an {@link IconMarginSpan} from a {@link Bitmap}. + * + * @param bitmap bitmap to be rendered at the beginning of the text + * @param pad padding width, in pixels, between the bitmap and the text + */ + public IconMarginSpan(@NonNull Bitmap bitmap, @IntRange(from = 0) int pad) { + mBitmap = bitmap; mPad = pad; } + @Override public int getLeadingMargin(boolean first) { return mBitmap.getWidth() + mPad; } + @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 layout) { + int top, int baseline, int bottom, + CharSequence text, int start, int end, + boolean first, Layout layout) { int st = ((Spanned) text).getSpanStart(this); int itop = layout.getLineTop(layout.getLineForOffset(st)); - if (dir < 0) + if (dir < 0) { x -= mBitmap.getWidth(); + } c.drawBitmap(mBitmap, x, itop, p); } + @Override public void chooseHeight(CharSequence text, int start, int end, - int istartv, int v, - Paint.FontMetricsInt fm) { + int istartv, int v, + Paint.FontMetricsInt fm) { if (end == ((Spanned) text).getSpanEnd(this)) { int ht = mBitmap.getHeight(); int need = ht - (v + fm.descent - fm.ascent - istartv); - if (need > 0) + if (need > 0) { fm.descent += need; + } need = ht - (v + fm.bottom - fm.top - istartv); - if (need > 0) + if (need > 0) { fm.bottom += need; + } } } - private Bitmap mBitmap; - private int mPad; } diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java index b0bff680f390..95f0b43341a2 100644 --- a/core/java/android/text/style/ImageSpan.java +++ b/core/java/android/text/style/ImageSpan.java @@ -17,6 +17,8 @@ package android.text.style; import android.annotation.DrawableRes; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -27,18 +29,49 @@ import android.util.Log; import java.io.InputStream; +/** + * Span that replaces the text it's attached to with a {@link Drawable} that can be aligned with + * the bottom or with the baseline of the surrounding text. The drawable can be constructed from + * varied sources: + * <ul> + * <li>{@link Bitmap} - see {@link #ImageSpan(Context, Bitmap)} and + * {@link #ImageSpan(Context, Bitmap, int)} + * </li> + * <li>{@link Drawable} - see {@link #ImageSpan(Drawable, int)}</li> + * <li>resource id - see {@link #ImageSpan(Context, int, int)}</li> + * <li>{@link Uri} - see {@link #ImageSpan(Context, Uri, int)}</li> + * </ul> + * The default value for the vertical alignment is {@link DynamicDrawableSpan#ALIGN_BOTTOM} + * <p> + * For example, an <code>ImagedSpan</code> can be used like this: + * <pre> + * SpannableString string = SpannableString("Bottom: span.\nBaseline: span."); + * // using the default alignment: ALIGN_BOTTOM + * string.setSpan(ImageSpan(this, R.mipmap.ic_launcher), 7, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + * string.setSpan(ImageSpan(this, R.mipmap.ic_launcher, DynamicDrawableSpan.ALIGN_BASELINE), + * 22, 23, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + * </pre> + * <img src="{@docRoot}reference/android/images/text/style/imagespan.png" /> + * <figcaption>Text with <code>ImageSpan</code>s aligned bottom and baseline.</figcaption> + */ public class ImageSpan extends DynamicDrawableSpan { + + @Nullable private Drawable mDrawable; + @Nullable private Uri mContentUri; + @DrawableRes private int mResourceId; + @Nullable private Context mContext; + @Nullable private String mSource; /** * @deprecated Use {@link #ImageSpan(Context, Bitmap)} instead. */ @Deprecated - public ImageSpan(Bitmap b) { + public ImageSpan(@NonNull Bitmap b) { this(null, b, ALIGN_BOTTOM); } @@ -46,80 +79,143 @@ public class ImageSpan extends DynamicDrawableSpan { * @deprecated Use {@link #ImageSpan(Context, Bitmap, int)} instead. */ @Deprecated - public ImageSpan(Bitmap b, int verticalAlignment) { + public ImageSpan(@NonNull Bitmap b, int verticalAlignment) { this(null, b, verticalAlignment); } - public ImageSpan(Context context, Bitmap b) { - this(context, b, ALIGN_BOTTOM); + /** + * Constructs an {@link ImageSpan} from a {@link Context} and a {@link Bitmap} with the default + * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM} + * + * @param context context used to create a drawable from {@param bitmap} based on the display + * metrics of the resources + * @param bitmap bitmap to be rendered + */ + public ImageSpan(@NonNull Context context, @NonNull Bitmap bitmap) { + this(context, bitmap, ALIGN_BOTTOM); } /** + * Constructs an {@link ImageSpan} from a {@link Context}, a {@link Bitmap} and a vertical + * alignment. + * + * @param context context used to create a drawable from {@param bitmap} based on + * the display metrics of the resources + * @param bitmap bitmap to be rendered * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or - * {@link DynamicDrawableSpan#ALIGN_BASELINE}. + * {@link DynamicDrawableSpan#ALIGN_BASELINE} */ - public ImageSpan(Context context, Bitmap b, int verticalAlignment) { + public ImageSpan(@NonNull Context context, @NonNull Bitmap bitmap, int verticalAlignment) { super(verticalAlignment); mContext = context; mDrawable = context != null - ? new BitmapDrawable(context.getResources(), b) - : new BitmapDrawable(b); + ? new BitmapDrawable(context.getResources(), bitmap) + : new BitmapDrawable(bitmap); int width = mDrawable.getIntrinsicWidth(); int height = mDrawable.getIntrinsicHeight(); - mDrawable.setBounds(0, 0, width > 0 ? width : 0, height > 0 ? height : 0); + mDrawable.setBounds(0, 0, width > 0 ? width : 0, height > 0 ? height : 0); } - public ImageSpan(Drawable d) { - this(d, ALIGN_BOTTOM); + /** + * Constructs an {@link ImageSpan} from a drawable with the default + * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM}. + * + * @param drawable drawable to be rendered + */ + public ImageSpan(@NonNull Drawable drawable) { + this(drawable, ALIGN_BOTTOM); } /** + * Constructs an {@link ImageSpan} from a drawable and a vertical alignment. + * + * @param drawable drawable to be rendered * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or - * {@link DynamicDrawableSpan#ALIGN_BASELINE}. + * {@link DynamicDrawableSpan#ALIGN_BASELINE} */ - public ImageSpan(Drawable d, int verticalAlignment) { + public ImageSpan(@NonNull Drawable drawable, int verticalAlignment) { super(verticalAlignment); - mDrawable = d; + mDrawable = drawable; } - public ImageSpan(Drawable d, String source) { - this(d, source, ALIGN_BOTTOM); + /** + * Constructs an {@link ImageSpan} from a drawable and a source with the default + * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM} + * + * @param drawable drawable to be rendered + * @param source drawable's Uri source + */ + public ImageSpan(@NonNull Drawable drawable, @NonNull String source) { + this(drawable, source, ALIGN_BOTTOM); } /** + * Constructs an {@link ImageSpan} from a drawable, a source and a vertical alignment. + * + * @param drawable drawable to be rendered + * @param source drawable's uri source * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or - * {@link DynamicDrawableSpan#ALIGN_BASELINE}. + * {@link DynamicDrawableSpan#ALIGN_BASELINE} */ - public ImageSpan(Drawable d, String source, int verticalAlignment) { + public ImageSpan(@NonNull Drawable drawable, @NonNull String source, int verticalAlignment) { super(verticalAlignment); - mDrawable = d; + mDrawable = drawable; mSource = source; } - public ImageSpan(Context context, Uri uri) { + /** + * Constructs an {@link ImageSpan} from a {@link Context} and a {@link Uri} with the default + * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM}. The Uri source can be retrieved via + * {@link #getSource()} + * + * @param context context used to create a drawable from {@param bitmap} based on the display + * metrics of the resources + * @param uri {@link Uri} used to construct the drawable that will be rendered + */ + public ImageSpan(@NonNull Context context, @NonNull Uri uri) { this(context, uri, ALIGN_BOTTOM); } /** + * Constructs an {@link ImageSpan} from a {@link Context}, a {@link Uri} and a vertical + * alignment. The Uri source can be retrieved via {@link #getSource()} + * + * @param context context used to create a drawable from {@param bitmap} based on + * the display + * metrics of the resources + * @param uri {@link Uri} used to construct the drawable that will be rendered. * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or - * {@link DynamicDrawableSpan#ALIGN_BASELINE}. + * {@link DynamicDrawableSpan#ALIGN_BASELINE} */ - public ImageSpan(Context context, Uri uri, int verticalAlignment) { + public ImageSpan(@NonNull Context context, @NonNull Uri uri, int verticalAlignment) { super(verticalAlignment); mContext = context; mContentUri = uri; mSource = uri.toString(); } - public ImageSpan(Context context, @DrawableRes int resourceId) { + /** + * Constructs an {@link ImageSpan} from a {@link Context} and a resource id with the default + * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM} + * + * @param context context used to retrieve the drawable from resources + * @param resourceId drawable resource id based on which the drawable is retrieved + */ + public ImageSpan(@NonNull Context context, @DrawableRes int resourceId) { this(context, resourceId, ALIGN_BOTTOM); } /** + * Constructs an {@link ImageSpan} from a {@link Context}, a resource id and a vertical + * alignment. + * + * @param context context used to retrieve the drawable from resources + * @param resourceId drawable resource id based on which the drawable is retrieved. * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or - * {@link DynamicDrawableSpan#ALIGN_BASELINE}. + * {@link DynamicDrawableSpan#ALIGN_BASELINE} */ - public ImageSpan(Context context, @DrawableRes int resourceId, int verticalAlignment) { + public ImageSpan(@NonNull Context context, @DrawableRes int resourceId, + int verticalAlignment) { super(verticalAlignment); mContext = context; mResourceId = resourceId; @@ -128,10 +224,10 @@ public class ImageSpan extends DynamicDrawableSpan { @Override public Drawable getDrawable() { Drawable drawable = null; - + if (mDrawable != null) { drawable = mDrawable; - } else if (mContentUri != null) { + } else if (mContentUri != null) { Bitmap bitmap = null; try { InputStream is = mContext.getContentResolver().openInputStream( @@ -142,7 +238,7 @@ public class ImageSpan extends DynamicDrawableSpan { drawable.getIntrinsicHeight()); is.close(); } catch (Exception e) { - Log.e("sms", "Failed to loaded content " + mContentUri, e); + Log.e("ImageSpan", "Failed to loaded content " + mContentUri, e); } } else { try { @@ -150,8 +246,8 @@ public class ImageSpan extends DynamicDrawableSpan { drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); } catch (Exception e) { - Log.e("sms", "Unable to find resource: " + mResourceId); - } + Log.e("ImageSpan", "Unable to find resource: " + mResourceId); + } } return drawable; @@ -159,9 +255,12 @@ public class ImageSpan extends DynamicDrawableSpan { /** * Returns the source string that was saved during construction. + * + * @return the source string that was saved during construction + * @see #ImageSpan(Drawable, String) and this{@link #ImageSpan(Context, Uri)} */ + @Nullable public String getSource() { return mSource; } - } diff --git a/core/java/android/text/style/LineHeightSpan.java b/core/java/android/text/style/LineHeightSpan.java index 1ebee82c18a8..50ee5f387595 100644 --- a/core/java/android/text/style/LineHeightSpan.java +++ b/core/java/android/text/style/LineHeightSpan.java @@ -19,16 +19,42 @@ package android.text.style; import android.graphics.Paint; import android.text.TextPaint; -public interface LineHeightSpan -extends ParagraphStyle, WrapTogetherSpan -{ +/** + * The classes that affect the height of the line should implement this interface. + */ +public interface LineHeightSpan extends ParagraphStyle, WrapTogetherSpan { + /** + * Classes that implement this should define how the height is being calculated. + * + * @param text the text + * @param start the start of the line + * @param end the end of the line + * @param spanstartv the start of the span + * @param lineHeight the line height + * @param fm font metrics of the paint, in integers + */ public void chooseHeight(CharSequence text, int start, int end, - int spanstartv, int v, - Paint.FontMetricsInt fm); + int spanstartv, int lineHeight, + Paint.FontMetricsInt fm); + /** + * The classes that affect the height of the line with respect to density, should implement this + * interface. + */ public interface WithDensity extends LineHeightSpan { + + /** + * Classes that implement this should define how the height is being calculated. + * + * @param text the text + * @param start the start of the line + * @param end the end of the line + * @param spanstartv the start of the span + * @param lineHeight the line height + * @param paint the paint + */ public void chooseHeight(CharSequence text, int start, int end, - int spanstartv, int v, - Paint.FontMetricsInt fm, TextPaint paint); + int spanstartv, int lineHeight, + Paint.FontMetricsInt fm, TextPaint paint); } } diff --git a/core/java/android/text/style/MaskFilterSpan.java b/core/java/android/text/style/MaskFilterSpan.java index 2ff52a8f70e8..d76ef941d42e 100644 --- a/core/java/android/text/style/MaskFilterSpan.java +++ b/core/java/android/text/style/MaskFilterSpan.java @@ -18,15 +18,36 @@ package android.text.style; import android.graphics.MaskFilter; import android.text.TextPaint; - +/** + * Span that allows setting a {@link MaskFilter} to the text it's attached to. + * <p> + * For example, to blur a text, a {@link android.graphics.BlurMaskFilter} can be used: + * <pre> + * MaskFilter blurMask = new BlurMaskFilter(5f, BlurMaskFilter.Blur.NORMAL); + * SpannableString string = new SpannableString("Text with blur mask"); + * string.setSpan(new MaskFilterSpan(blurMask), 10, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + * </pre> + * <img src="{@docRoot}reference/android/images/text/style/maskfilterspan.png" /> + * <figcaption>Text blurred with the <code>MaskFilterSpan</code>.</figcaption> + */ public class MaskFilterSpan extends CharacterStyle implements UpdateAppearance { private MaskFilter mFilter; + /** + * Creates a {@link MaskFilterSpan} from a {@link MaskFilter}. + * + * @param filter the filter to be applied to the <code>TextPaint</code> + */ public MaskFilterSpan(MaskFilter filter) { mFilter = filter; } + /** + * Return the mask filter for this span. + * + * @return the mask filter for this span + */ public MaskFilter getMaskFilter() { return mFilter; } diff --git a/core/java/android/text/style/StyleSpan.java b/core/java/android/text/style/StyleSpan.java index f900db502d0d..bdfa700215f8 100644 --- a/core/java/android/text/style/StyleSpan.java +++ b/core/java/android/text/style/StyleSpan.java @@ -16,6 +16,7 @@ package android.text.style; +import android.annotation.NonNull; import android.graphics.Paint; import android.graphics.Typeface; import android.os.Parcel; @@ -24,55 +25,76 @@ import android.text.TextPaint; import android.text.TextUtils; /** - * - * Describes a style in a span. + * Span that allows setting the style of the text it's attached to. + * Possible styles are: {@link Typeface#NORMAL}, {@link Typeface#BOLD}, {@link Typeface#ITALIC} and + * {@link Typeface#BOLD_ITALIC}. + * <p> * Note that styles are cumulative -- if both bold and italic are set in * separate spans, or if the base style is bold and a span calls for italic, * you get bold italic. You can't turn off a style from the base style. - * + * <p> + * For example, the <code>StyleSpan</code> can be used like this: + * <pre> + * SpannableString string = new SpannableString("Bold and italic text"); + * string.setSpan(new StyleSpan(Typeface.BOLD), 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + * string.setSpan(new StyleSpan(Typeface.ITALIC), 9, 15, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + * </pre> + * <img src="{@docRoot}reference/android/images/text/style/stylespan.png" /> + * <figcaption>Text styled bold and italic with the <code>StyleSpan</code>.</figcaption> */ public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan { private final int mStyle; /** - * + * Creates a {@link StyleSpan} from a style. + * * @param style An integer constant describing the style for this span. Examples - * include bold, italic, and normal. Values are constants defined - * in {@link android.graphics.Typeface}. + * include bold, italic, and normal. Values are constants defined + * in {@link Typeface}. */ public StyleSpan(int style) { mStyle = style; } - public StyleSpan(Parcel src) { + /** + * Creates a {@link StyleSpan} from a parcel. + * + * @param src the parcel + */ + public StyleSpan(@NonNull Parcel src) { mStyle = src.readInt(); } - + + @Override public int getSpanTypeId() { return getSpanTypeIdInternal(); } /** @hide */ + @Override public int getSpanTypeIdInternal() { return TextUtils.STYLE_SPAN; } - + + @Override public int describeContents() { return 0; } + @Override public void writeToParcel(Parcel dest, int flags) { writeToParcelInternal(dest, flags); } /** @hide */ - public void writeToParcelInternal(Parcel dest, int flags) { + @Override + public void writeToParcelInternal(@NonNull Parcel dest, int flags) { dest.writeInt(mStyle); } /** - * Returns the style constant defined in {@link android.graphics.Typeface}. + * Returns the style constant defined in {@link Typeface}. */ public int getStyle() { return mStyle; diff --git a/core/java/android/text/style/TabStopSpan.java b/core/java/android/text/style/TabStopSpan.java index 056642841815..2cceb2c8ced9 100644 --- a/core/java/android/text/style/TabStopSpan.java +++ b/core/java/android/text/style/TabStopSpan.java @@ -16,39 +16,54 @@ package android.text.style; +import android.annotation.IntRange; +import android.annotation.Px; + /** - * Represents a single tab stop on a line. + * Paragraph affecting span that changes the position of the tab with respect to + * the leading margin of the line. <code>TabStopSpan</code> will only affect the first tab + * encountered on the first line of the text. */ -public interface TabStopSpan -extends ParagraphStyle -{ +public interface TabStopSpan extends ParagraphStyle { + /** - * Returns the offset of the tab stop from the leading margin of the - * line. - * @return the offset + * Returns the offset of the tab stop from the leading margin of the line, in pixels. + * + * @return the offset, in pixels */ - public int getTabStop(); + int getTabStop(); /** - * The default implementation of TabStopSpan. + * The default implementation of TabStopSpan that allows setting the offset of the tab stop + * from the leading margin of the first line of text. + * <p> + * Let's consider that we have the following text: <i>"\tParagraph text beginning with tab."</i> + * and we want to move the tab stop with 100px. This can be achieved like this: + * <pre> + * SpannableString string = new SpannableString("\tParagraph text beginning with tab."); + * string.setSpan(new TabStopSpan.Standard(100), 0, string.length(), + * Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);</pre> + * <img src="{@docRoot}reference/android/images/text/style/tabstopspan.png" /> + * <figcaption>Text with a tab stop and a <code>TabStopSpan</code></figcaption> */ - public static class Standard - implements TabStopSpan - { + class Standard implements TabStopSpan { + + @Px + private int mTabOffset; + /** - * Constructor. + * Constructs a {@link TabStopSpan.Standard} based on an offset. * - * @param where the offset of the tab stop from the leading margin of - * the line + * @param offset the offset of the tab stop from the leading margin of + * the line, in pixels */ - public Standard(int where) { - mTab = where; + public Standard(@IntRange(from = 0) int offset) { + mTabOffset = offset; } + @Override public int getTabStop() { - return mTab; + return mTabOffset; } - - private int mTab; } } diff --git a/core/java/android/text/style/TypefaceSpan.java b/core/java/android/text/style/TypefaceSpan.java index aa622d87c74e..162281250208 100644 --- a/core/java/android/text/style/TypefaceSpan.java +++ b/core/java/android/text/style/TypefaceSpan.java @@ -16,6 +16,7 @@ package android.text.style; +import android.annotation.NonNull; import android.graphics.Paint; import android.graphics.Typeface; import android.os.Parcel; @@ -24,42 +25,59 @@ import android.text.TextPaint; import android.text.TextUtils; /** - * Changes the typeface family of the text to which the span is attached. + * Changes the typeface family of the text to which the span is attached. Examples of typeface + * family include "monospace", "serif", and "sans-serif". + * <p> + * For example, change the typeface of a text to "monospace" like this: + * <pre> + * SpannableString string = new SpannableString("Text with typeface span"); + * string.setSpan(new TypefaceSpan("monospace"), 10, 18, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + * </pre> + * <img src="{@docRoot}reference/android/images/text/style/typefacespan.png" /> + * <figcaption>Text with "monospace" typeface family.</figcaption> */ public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan { + private final String mFamily; /** - * @param family The font family for this typeface. Examples include - * "monospace", "serif", and "sans-serif". + * Constructs a {@link TypefaceSpan} based on a font family. + * + * @param family The font family for this typeface. Examples include + * "monospace", "serif", and "sans-serif". */ public TypefaceSpan(String family) { mFamily = family; } - public TypefaceSpan(Parcel src) { + public TypefaceSpan(@NonNull Parcel src) { mFamily = src.readString(); } - + + @Override public int getSpanTypeId() { return getSpanTypeIdInternal(); } /** @hide */ + @Override public int getSpanTypeIdInternal() { return TextUtils.TYPEFACE_SPAN; } - + + @Override public int describeContents() { return 0; } - public void writeToParcel(Parcel dest, int flags) { + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { writeToParcelInternal(dest, flags); } /** @hide */ - public void writeToParcelInternal(Parcel dest, int flags) { + @Override + public void writeToParcelInternal(@NonNull Parcel dest, int flags) { dest.writeString(mFamily); } @@ -71,16 +89,16 @@ public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan } @Override - public void updateDrawState(TextPaint ds) { - apply(ds, mFamily); + public void updateDrawState(@NonNull TextPaint textPaint) { + apply(textPaint, mFamily); } @Override - public void updateMeasureState(TextPaint paint) { - apply(paint, mFamily); + public void updateMeasureState(@NonNull TextPaint textPaint) { + apply(textPaint, mFamily); } - private static void apply(Paint paint, String family) { + private static void apply(@NonNull Paint paint, String family) { int oldStyle; Typeface old = paint.getTypeface(); diff --git a/core/java/android/text/style/URLSpan.java b/core/java/android/text/style/URLSpan.java index 58239efe5c5f..eab1ef4f6afd 100644 --- a/core/java/android/text/style/URLSpan.java +++ b/core/java/android/text/style/URLSpan.java @@ -16,6 +16,7 @@ package android.text.style; +import android.annotation.NonNull; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; @@ -27,40 +28,71 @@ import android.text.TextUtils; import android.util.Log; import android.view.View; +/** + * Implementation of the {@link ClickableSpan} that allows setting a url string. When + * selecting and clicking on the text to which the span is attached, the <code>URLSpan</code> + * will try to open the url, by launching an an Activity with an {@link Intent#ACTION_VIEW} intent. + * <p> + * For example, a <code>URLSpan</code> can be used like this: + * <pre> + * SpannableString string = new SpannableString("Text with a url span"); + * string.setSpan(new URLSpan("http://www.developer.android.com"), 12, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + * </pre> + * <img src="{@docRoot}reference/android/images/text/style/urlspan.png" /> + * <figcaption>Text with <code>URLSpan</code>.</figcaption> + */ public class URLSpan extends ClickableSpan implements ParcelableSpan { private final String mURL; + /** + * Constructs a {@link URLSpan} from a url string. + * + * @param url the url string + */ public URLSpan(String url) { mURL = url; } - public URLSpan(Parcel src) { + /** + * Constructs a {@link URLSpan} from a parcel. + */ + public URLSpan(@NonNull Parcel src) { mURL = src.readString(); } - + + @Override public int getSpanTypeId() { return getSpanTypeIdInternal(); } /** @hide */ + @Override public int getSpanTypeIdInternal() { return TextUtils.URL_SPAN; } - + + @Override public int describeContents() { return 0; } - public void writeToParcel(Parcel dest, int flags) { + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { writeToParcelInternal(dest, flags); } /** @hide */ - public void writeToParcelInternal(Parcel dest, int flags) { + @Override + public void writeToParcelInternal(@NonNull Parcel dest, int flags) { dest.writeString(mURL); } + /** + * Get the url string for this span. + * + * @return the url string. + */ public String getURL() { return mURL; } diff --git a/docs/html/reference/images/text/style/drawablemarginspan.png b/docs/html/reference/images/text/style/drawablemarginspan.png Binary files differnew file mode 100644 index 000000000000..edf926d80130 --- /dev/null +++ b/docs/html/reference/images/text/style/drawablemarginspan.png diff --git a/docs/html/reference/images/text/style/dynamicdrawablespan.png b/docs/html/reference/images/text/style/dynamicdrawablespan.png Binary files differnew file mode 100644 index 000000000000..8776b0387278 --- /dev/null +++ b/docs/html/reference/images/text/style/dynamicdrawablespan.png diff --git a/docs/html/reference/images/text/style/iconmarginspan.png b/docs/html/reference/images/text/style/iconmarginspan.png Binary files differnew file mode 100644 index 000000000000..8ec39be039f6 --- /dev/null +++ b/docs/html/reference/images/text/style/iconmarginspan.png diff --git a/docs/html/reference/images/text/style/imagespan.png b/docs/html/reference/images/text/style/imagespan.png Binary files differnew file mode 100644 index 000000000000..c03e6bb68bd5 --- /dev/null +++ b/docs/html/reference/images/text/style/imagespan.png diff --git a/docs/html/reference/images/text/style/maskfilterspan.png b/docs/html/reference/images/text/style/maskfilterspan.png Binary files differnew file mode 100644 index 000000000000..6e55dbc1509c --- /dev/null +++ b/docs/html/reference/images/text/style/maskfilterspan.png diff --git a/docs/html/reference/images/text/style/stylespan.png b/docs/html/reference/images/text/style/stylespan.png Binary files differnew file mode 100644 index 000000000000..9ffa05b5ac43 --- /dev/null +++ b/docs/html/reference/images/text/style/stylespan.png diff --git a/docs/html/reference/images/text/style/tabstopspan.png b/docs/html/reference/images/text/style/tabstopspan.png Binary files differnew file mode 100644 index 000000000000..89a1121d0745 --- /dev/null +++ b/docs/html/reference/images/text/style/tabstopspan.png diff --git a/docs/html/reference/images/text/style/typefacespan.png b/docs/html/reference/images/text/style/typefacespan.png Binary files differnew file mode 100644 index 000000000000..67e2cf9b0468 --- /dev/null +++ b/docs/html/reference/images/text/style/typefacespan.png diff --git a/docs/html/reference/images/text/style/urlspan.png b/docs/html/reference/images/text/style/urlspan.png Binary files differnew file mode 100644 index 000000000000..11345206e594 --- /dev/null +++ b/docs/html/reference/images/text/style/urlspan.png |