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

text spans: what, why and how?

text spans: what, why and how?

Matheus Cassiano Candido

September 05, 2017
Tweet

More Decks by Matheus Cassiano Candido

Other Decks in Programming

Transcript

  1. TextView Layout TextLine basic and global attrs: padding, margin, background,

    etc. also text selection and highlight. paragraph styling: bullet points, line breaking, line backgrounds. character level styling.
  2. bullet span val spacing = 20 // px! val items

    = arrayOf("Item 1", "Item 2", "Item 3") val builder = SpannableStringBuilder() items.forEach { val line = SpannableString(it) line.setSpan(BulletSpan(spacing), 0, it.length, SPAN_EXCLUSIVE_EXCLUSIVE) builder.appendln(line) } textView.text = builder
  3. quote span val quote = "I'm selfish,…” val author =

    "Marilyn Monroe" val quoteSpan = SpannableString(quote) quoteSpan.setSpan(QuoteSpan(), 0, quote.length, SPAN_EXCLUSIVE_EXCLUSIVE) val finalText = SpannableStringBuilder() finalText.appendln(quoteSpan) finalText.append(author) textView.text = finalText
  4. class CustomQuoteSpan : LeadingMarginSpan { val gap = 200 val

    quoteSize = 300 val leftQuote = "\u201C" val paint = TextPaint() init { paint.textSize = 240f } override fun drawLeadingMargin(canvas: Canvas, paint: Paint, x: Int, dir: Int, top: Int, baseline: Int, bottom: Int, text: CharSequence, start: Int, end: Int, first: Boolean, layout: Layout) { if ((text as Spanned).getSpanStart(this) == start) { canvas.drawText(leftQuote, x, top + quoteSize, this.paint) } } override fun getLeadingMargin(p0: Boolean): Int = gap } custom quote span
  5. custom quote span val quote = "I'm selfish,…” val author

    = "Marilyn Monroe" val quoteSpan = SpannableString(quote) quoteSpan.setSpan(CustomQuoteSpan(), 0, quote.length, SPAN_EXCLUSIVE_EXCLUSIVE) val finalText = SpannableStringBuilder() finalText.appendln(quoteSpan) finalText.append(author) textView.text = finalText
  6. alignment span //... val authorSpan = SpannableString(author) authorSpan.setSpan(AlignmentSpan.Standard(ALIGN_OPPOSITE), 0, author.length,

    SPAN_EXCLUSIVE_EXCLUSIVE) val finalText = SpannableStringBuilder() finalText .appendln(quoteSpan) .appendln() .append(authorSpan) textView.text = finalText
  7. foreground color span //... val selfish = "selfish" val impatient

    = "impatient" val insecure = "insecure" //... quoteSpan.setSpan(ForegroundColorSpan(myPinkColorInt), quote.indexOf(selfish), quote.indexOf(selfish) + selfish.length, SPAN_EXCLUSIVE_EXCLUSIVE) //... textView.text = builder
  8. relative size span //... val sureAsHell = "sure as hell"

    //... quoteSpan.setSpan(RelativeSizeSpan(1.5f), quote.indexOf(sureAsHell), quote.indexOf(sureAsHell) + sureAsHell.length, SPAN_EXCLUSIVE_EXCLUSIVE) //... textView.text = builder
  9. background color span //... quoteSpan.setSpan(BackgroundColorSpan(myPinkColor), quote.indexOf(sureAsHell), quote.indexOf(sureAsHell) + sureAsHell.length, SPAN_EXCLUSIVE_EXCLUSIVE)

    quoteSpan.setSpan(ForegroundColorSpan(myWhiteColor), quote.indexOf(sureAsHell), quote.indexOf(sureAsHell) + sureAsHell.length, SPAN_EXCLUSIVE_EXCLUSIVE) //... textView.text = builder
  10. custom typeface span class CustomTypefaceSpan(val typeface: Typeface) : MetricAffectingSpan() {

    override fun updateMeasureState(paint: TextPaint) { paint.typeface = typeface } override fun updateDrawState(paint: TextPaint) { paint.typeface = typeface } }
  11. custom typeface span //... val italicTypeface = ResourcesCompat .getFont(this, R.font.alegreya_italic)!!

    val boldTypeface = ResourcesCompat .getFont(this, R.font.alegreya_bold)!! quoteSpan.setSpan(CustomTypefaceSpan(italicTypeface), 0, quote.length, SPAN_EXCLUSIVE_EXCLUSIVE) authorSpan.setSpan(CustomTypefaceSpan(boldTypeface), 0, author.length, SPAN_EXCLUSIVE_EXCLUSIVE) textView.text = builder
  12. custom letter spacing span class LetterSpacingSpan(val spacing: Float) : CharacterStyle()

    { override fun updateDrawState(paint: TextPaint) { if (SDK_INT >= LOLLIPOP) paint.letterSpacing = spacing } } authorSpan.setSpan(LetterSpacingSpan(0.15f), 0, author.length, SPAN_EXCLUSIVE_EXCLUSIVE)
  13. clickable span class CustomClickSpan : ClickableSpan() { override fun onClick(view:

    View) { // action view.showToast("Clicked!", LENGTH_SHORT) } override fun updateDrawState(textPaint: TextPaint) { // do whatever with the textPaint textPaint.isUnderlineText = true } }
  14. image span val imageHolder = SpannableString(" ") val image =

    getDrawable(this, R.drawable.monroe) image.setBounds(0, 0, 100, 100) val imageSpan = ImageSpan(image, ImageSpan.ALIGN_BOTTOM) imageHolder.setSpan(imageSpan, 0, 1, SPAN_EXCLUSIVE_EXCLUSIVE) finalText .appendln(quoteSpan) .appendln() .append(authorSpan) .append(" ") .append(imageHolder) textView.text = finalText
  15. accessibility •the TtsSpan supplies extra information (meta-data) used for when

    text-to-speech is scanning •there are numerous types of TtsSpan •TYPE_DIGITS •TYPE_TELEPHONE •TYPE_TIME •TYPE_MONEY •and others
  16. span flags Flags control the span behavior of text inserted

    later (using the insert method for example).