Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The magic of SpannableString by Samuel Dionne

GDG Montreal
November 27, 2019

The magic of SpannableString by Samuel Dionne

SpannableString is a powerful concept that goes beyond clickable links in a TextView. We’ll look at different standard use cases and other more daring. We’ll check the different already available Span types and look at how we can create our very own.

https://gdgmontreal.com/2019/11/15/november-meetup/
https://youtu.be/U3cBsubemPc

GDG Montreal

November 27, 2019
Tweet

More Decks by GDG Montreal

Other Decks in Technology

Transcript

  1. Spannable
    Magic
    What are spans and what can we do with them

    View full-size slide

  2. Outline What is are Span and Spannable strings
    What can we do with them
    How do they work
    How to create a custom span
    Questions

    View full-size slide

  3. What are Spans and Spannable strings

    View full-size slide

  4. Differents ways
    to style text
    Changing all the text at once
    Here is my example text
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="#ff0000"
    android:textSize="22sp"
    android:textStyle="bold" />

    View full-size slide

  5. Differents ways
    to style text
    Changing only part of the text
    Here is my example text
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:magic="???" />

    View full-size slide

  6. Here come the Span
    Spans are a way to apply style to different part of a strings

    View full-size slide

  7. Here come the Span
    Spans are a way to apply style to different part of a strings
    Here is my example text

    View full-size slide

  8. Here come the Span
    Spans are a way to apply style to different part of a strings
    Here is my example text
    SpannableString str = new SpannableString(“Here is my example”);
    str.setSpan(new UnderlineSpan(), 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    str.setSpan(new ForegroundColorSpan(0xffff0000), 8, 10, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    str.setSpan(new StyleSpan(BOLC), 19, 23, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

    View full-size slide

  9. Here come the Span
    str.setSpan(new UnderlineSpan(), 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    Span: what style we want
    Span Start index End index Flags

    View full-size slide

  10. Here come the Span
    str.setSpan(new UnderlineSpan(), 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    Span: what style we want
    Start index: where to start from
    Span Start index End index Flags

    View full-size slide

  11. Here come the Span
    str.setSpan(new UnderlineSpan(), 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    Span: what style we want
    Start index: where to start from
    End index: where to end
    Span Start index End index Flags

    View full-size slide

  12. Here come the Span
    str.setSpan(new UnderlineSpan(), 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    Span: what style we want
    Start index: where to start from
    End index: where to end
    Flags: what should happen when the text change
    Span Start index End index Flags

    View full-size slide

  13. Text change behaviours
    Here is my text
    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
    Spannable.SPAN_INCLUSIVE_EXCLUSIVE
    Spannable.SPAN_EXCLUSIVE_INCLUSIVE
    Spannable.SPAN_INCLUSIVE_INCLUSIVE
    Here is my super-text-er
    Here is my super-text-er
    Here is my super-text-er
    Here is my super-text-er
    Here is my super-text-er

    View full-size slide

  14. How to apply
    span?
    It depends of what part can change

    View full-size slide

  15. How to apply
    span?
    It depends of what part can change
    SpannedString
    Text is immutable
    Spans are immutables

    View full-size slide

  16. How to apply
    span?
    It depends of what part can change
    SpannedString
    Text is immutable
    Spans are immutables
    SpannableString
    Text is immutable
    Spans are mutables

    View full-size slide

  17. How to apply
    span?
    It depends of what part can change
    SpannedString
    Text is immutable
    Spans are immutables
    SpannableString
    Text is immutable
    Spans are mutables
    SpannableStringBuilder
    Text is mutable
    Spans are mutables

    View full-size slide

  18. What can we do with them

    View full-size slide

  19. Provided spans
    AbsoluteSizeSpan
    AlignmentSpan.Standard
    BackgroundColorSpan
    BulletSpan
    CharacterStyle
    ClickableSpan
    DrawableMarginSpan
    DynamicDrawableSpan
    EasyEditSpan
    ForegroundColorSpan
    IconMarginSpan
    ImageSpan
    LeadingMarginSpan.Standard
    MaskFilterSpan
    MetricAffectingSpan
    QuoteSpan
    RelativeSizeSpan
    ReplacementSpan
    ScaleXSpan
    StrikethroughSpan
    StyleSpan
    SubscriptSpan
    SuggestionSpan
    SuperscriptSpan
    TabStopSpan.Standard
    TextAppearanceSpan

    View full-size slide

  20. Provided spans
    AbsoluteSizeSpan
    AlignmentSpan.Standard
    BackgroundColorSpan
    BulletSpan
    CharacterStyle
    ClickableSpan
    DrawableMarginSpan
    DynamicDrawableSpan
    EasyEditSpan
    ForegroundColorSpan
    IconMarginSpan
    ImageSpan
    MaskFilterSpan
    MetricAffectingSpan
    QuoteSpan
    RelativeSizeSpan
    ReplacementSpan
    ScaleXSpan
    StrikethroughSpan
    StyleSpan
    SubscriptSpan
    SuggestionSpan
    SuperscriptSpan
    TabStopSpan.Standard
    TextAppearanceSpan

    View full-size slide

  21. Provided spans
    AbsoluteSizeSpan
    AlignmentSpan.Standard
    BackgroundColorSpan
    BulletSpan
    CharacterStyle
    ClickableSpan
    DrawableMarginSpan
    DynamicDrawableSpan
    EasyEditSpan
    ForegroundColorSpan
    IconMarginSpan
    ImageSpan
    LeadingMarginSpan.Standard
    MaskFilterSpan
    MetricAffectingSpan
    QuoteSpan
    RelativeSizeSpan
    ReplacementSpan
    ScaleXSpan
    StrikethroughSpan
    StyleSpan
    SubscriptSpan
    SuggestionSpan
    SuperscriptSpan
    TabStopSpan.Standard
    TextAppearanceSpan

    View full-size slide

  22. Provided spans
    AbsoluteSizeSpan
    AlignmentSpan.Standard
    BackgroundColorSpan
    • BulletSpan
    CharacterStyle
    ClickableSpan
    DrawableMarginSpan
    DynamicDrawableSpan
    EasyEditSpan
    ForegroundColorSpan
    IconMarginSpan
    ImageSpan
    LeadingMarginSpan.Standard
    MaskFilterSpan
    MetricAffectingSpan
    QuoteSpan
    RelativeSizeSpan
    ReplacementSpan
    ScaleXSpan
    StrikethroughSpan
    StyleSpan
    SubscriptSpan
    SuggestionSpan
    SuperscriptSpan
    TabStopSpan.Standard
    TextAppearanceSpan

    View full-size slide

  23. Provided spans
    AbsoluteSizeSpan
    AlignmentSpan.Standard
    BackgroundColorSpan
    BulletSpan
    CharacterStyle
    ClickableSpan
    DrawableMarginSpan
    DynamicDrawableSpan
    EasyEditSpan
    ForegroundColorSpan
    IconMarginSpan
    ImageSpan
    LeadingMarginSpan.Standard
    MaskFilterSpan
    MetricAffectingSpan
    QuoteSpan
    RelativeSizeSpan
    ReplacementSpan
    ScaleXSpan
    StrikethroughSpan
    StyleSpan
    SubscriptSpan
    SuggestionSpan
    SuperscriptSpan
    TabStopSpan.Standard
    TextAppearanceSpan

    View full-size slide

  24. Provided spans
    AbsoluteSizeSpan
    AlignmentSpan.Standard
    BackgroundColorSpan
    BulletSpan
    CharacterStyle
    ClickableSpan
    DrawableMarginSpan
    DynamicDrawableSpan
    EasyEditSpan
    ForegroundColorSpan
    IconMarginSpan
    ImageSpan
    LeadingMarginSpan.Standard
    MaskFilterSpan
    MetricAffectingSpan
    QuoteSpan
    RelativeSizeSpan
    ReplacementSpan
    ScaleXSpan
    StrikethroughSpan
    StyleSpan
    SubscriptSpan
    SuggestionSpan
    SuperscriptSpan
    TabStopSpan.Standard
    TextAppearanceSpan

    View full-size slide

  25. Provided spans
    AbsoluteSizeSpan
    AlignmentSpan.Standard
    BackgroundColorSpan
    BulletSpan
    CharacterStyle
    ClickableSpan
    DrawableMarginSpan
    DynamicDrawableSpan
    EasyEditSpan
    ForegroundColorSpan
    IconMarginSpan
    ImageSpan
    LeadingMarginSpan.Standard
    MaskFilterSpan
    MetricAffectingSpan
    QuoteSpan
    RelativeSizeSpan
    ReplacementSpan
    ScaleXSpan
    StrikethroughSpan
    StyleSpan
    S
    ubscriptSpan
    SuggestionSpan
    SuperscriptSpan
    TabStopSpan.Standard
    TextAppearanceSpan

    View full-size slide

  26. Provided spans
    AbsoluteSizeSpan
    AlignmentSpan.Standard
    BackgroundColorSpan
    BulletSpan
    CharacterStyle
    ClickableSpan
    DrawableMarginSpan
    DynamicDrawableSpan
    EasyEditSpan
    ForegroundColorSpan
    IconMarginSpan
    ImageSpan
    LeadingMarginSpan.Standard
    MaskFilterSpan
    MetricAffectingSpan
    QuoteSpan
    RelativeSizeSpan
    ReplacementSpan
    ScaleXSpan
    StrikethroughSpan
    StyleSpan
    SubscriptSpan
    SuggestionSpan
    SuperscriptSpan
    TabStopSpan.Standard
    TextAppearanceSpan

    View full-size slide

  27. How do they work

    View full-size slide

  28. 3 types of Spans

    View full-size slide

  29. 3 types of Spans Character Affecting Spans
    Appearance Affecting Spans
    Only affect the style
    No effect on the layout
    Example: ForegroundColorSpan

    View full-size slide

  30. 3 types of Spans Character Affecting Spans
    Appearance Affecting Spans
    Only affect the style
    No effect on the layout
    Metric Affecting Spans
    Affect the dimensions of the text
    Example: AbsoluteSizeSpan

    View full-size slide

  31. 3 types of Spans Character Affecting Spans
    Appearance Affecting Spans
    Only affect the style
    No effect on the layout
    Metric Affecting Spans
    Affect the dimensions of the text
    Paragraph Affecting Spans
    A paragraph is delimited by \n
    Example: QuoteSpan

    View full-size slide

  32. How to create a custom span

    View full-size slide

  33. Mise en scène
    01
    Julia
    UI Designer

    View full-size slide

  34. 1
    Mise en scène
    02
    2 min
    10 min
    1 h 25 min

    View full-size slide

  35. 1
    Mise en scène
    03
    2 min

    View full-size slide

  36. 1
    Mise en scène
    03
    2 min
    AbsoluteSizeSpan

    View full-size slide

  37. 1
    Mise en scène
    03
    2 min
    AbsoluteSizeSpan
    StyleSpan

    View full-size slide

  38. 1
    Mise en scène
    03
    2 min
    AbsoluteSizeSpan
    StyleSpan
    ImageSpan

    View full-size slide

  39. 1
    Mise en scène
    04
    2 min
    AbsoluteSizeSpan
    StyleSpan
    ImageSpan

    View full-size slide

  40. 1
    Mise en scène
    04
    2 min
    AbsoluteSizeSpan
    StyleSpan
    ImageSpan

    View full-size slide

  41. 1
    Solution 2 min
    AbsoluteSizeSpan
    StyleSpan
    SuperscriptImageSpan

    View full-size slide

  42. SuperscriptImageSpan.java
    public int getSize(Paint paint,
    CharSequence text,
    int start, int end,
    Paint.FontMetricsInt fm);
    public void draw(Canvas canvas,
    CharSequence text,
    int start, int end, float x, int top, int y, int bottom,
    Paint paint);

    View full-size slide

  43. SuperscriptImageSpan.java
    public int getSize(Paint paint,
    CharSequence text,
    int start, int end,
    Paint.FontMetricsInt fm);
    public void draw(Canvas canvas,
    CharSequence text,
    int start, int end, float x, int top, int y, int bottom,
    Paint paint);

    View full-size slide

  44. SuperscriptImageSpan.java
    public int getSize(Paint paint,
    CharSequence text,
    int start, int end,
    Paint.FontMetricsInt fm);
    public void draw(Canvas canvas,
    CharSequence text,
    int start, int end, float x, int top, int y, int bottom,
    Paint paint);

    View full-size slide

  45. Paint.FontMetricsInt

    View full-size slide

  46. SuperscriptImageSpan.java
    public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
    Rect rect = drawable.getBounds();
    if (fm != null) {
    fm.top = fm.ascent - rect.bottom / 2;
    }
    return rect.right;
    }

    View full-size slide

  47. SuperscriptImageSpan.java
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y,
    int bottom, Paint paint) {
    canvas.save();
    canvas.translate(x, drawable.getBounds().bottom / 2);
    drawable.draw(canvas);
    canvas.restore();
    }

    View full-size slide

  48. 1
    Finally 2 min
    AbsoluteSizeSpan
    StyleSpan
    SuperscriptImageSpan

    View full-size slide

  49. References
    Spantastic text styling with Spans
    String Manipulation Using SpannableString
    Android Developer Doc

    View full-size slide