SpannableString: wat is het, stijlklassen en hoe het werkt

Auteur: IT Sectr Gepubliceerd: 2026-07-23 Leestijd: 10 min

SpannableString is een klasse uit de Android SDK in het android.text-pakket waarmee meerdere stijlen kunnen worden toegepast op verschillende delen van een tekststring in TextView. In tegenstelling tot HTML-opmaak werkt SpannableString op het niveau van Span-objecten en beheert het de visuele weergave van tekst: kleur, grootte, lettertype, onderstreping en interactieve elementen. Volgens Google Developers wordt SpannableString gebruikt in systeemcomponenten van Android voor het formatteren van links. Het is de primaire manier om tekst te stylen zonder externe bibliotheken aan te sluiten.

Belangrijkste

  • SpannableString — Android-klasse voor tekststyling via Span-objecten, onveranderlijk na creatie
  • Spans worden onderverdeeld in CharacterStyle (individuele tekens) en ParagraphStyle (hele alinea’s)
  • ForegroundColorSpan verandert de tekstkleur, StyleSpan is verantwoordelijk voor vet en cursief
  • SpannableStringBuilder — veranderlijke versie voor dynamische tekstconstructie met ondersteuning voor Editable
  • Span flags bepalen het gedrag van de span bij het invoegen en verwijderen van tekst op de grenzen van het bereik

Wat is SpannableString?

SpannableString is een Android-klasse die de Spannable-interface implementeert en tekst opslaat samen met een set Span-objecten die de visuele weergave beheren. In tegenstelling tot een gewone String maakt SpannableString het mogelijk om stijlkenmerken te koppelen aan specifieke tekenbereiken: een deel van de tekst rood maken, het lettertype in de kop vergroten of een klikbare link binnen een alinea toevoegen.

De klasse bevindt zich in het pakket android.text en is beschikbaar vanaf API Level 1. SpannableString is onveranderlijk — na creatie wordt de structuur vastgelegd en het vervangen van tekst vereist het maken van een nieuw object. Voor dynamische bewerking wordt SpannableStringBuilder gebruikt, die het invoegen en verwijderen van tekens ondersteunt zonder verlies van stijlen.

Verschil met CharSequence

CharSequence is de basisinterface voor tekstgegevens, geïmplementeerd door String, StringBuilder en SpannableString. Het belangrijkste verschil tussen SpannableString en String is de ondersteuning voor het koppelen van willekeurige objecten aan substrings. TextView herkent de Spannable-interface en past bij het renderen de span-objecten toe op de corresponderende delen van de tekst. Als een gewone String aan TextView wordt doorgegeven, worden geen stijlen toegepast.

Interne structuur

SpannableString slaat tekst op als een array char[] en een aparte array van span-objecten met metadata over de begin- en eindpositie. Bij het aanroepen van setSpan(what, start, end, flags) wordt het object what opgeslagen in de lijst samen met informatie over het bereik. Bij het renderen past TextView achtereenvolgens alle spans toe die binnen het weergegeven bereik vallen, door de methoden updateDrawState en updateMeasureState aan te roepen.

Soorten spans: CharacterStyle en ParagraphStyle

CharacterStyle is de basisklasse voor spans die individuele tekens beïnvloeden, ongeacht hun positie in regels. Dit omvat ForegroundColorSpan (tekstkleur), RelativeSizeSpan (relatieve grootte), StyleSpan (vet en cursief), UnderlineSpan (onderstreping) en andere. Character-spans worden afzonderlijk toegepast op elk teken in het opgegeven bereik.

ParagraphStyle is de interface voor spans die hele alinea’s beïnvloeden. De bekendste vertegenwoordiger is AlignmentSpan, die de hele alinea links, gecentreerd of rechts uitlijnt. Paragraph-spans moeten de hele alinea bestrijken, anders negeert Android hun toepassing. Deze beperking komt doordat uitlijning of inspringing alleen zinvol is voor een volledig tekstblok.

Span flags

Span flags zijn vier constanten die het gedrag van de span bepalen bij het invoegen of verwijderen van tekst op de grenzen van het bereik. SPAN_EXCLUSIVE_EXCLUSIVE houdt de span alleen actief binnen de oorspronkelijke grenzen, SPAN_INCLUSIVE_INCLUSIVE breidt deze uit bij het toevoegen van tekst aan de grenzen. SPAN_EXCLUSIVE_INCLUSIVE en SPAN_INCLUSIVE_EXCLUSIVE bieden gemengd gedrag voor het begin en einde van het bereik.

FlagInvoegen linksInvoegen rechts
SPAN_EXCLUSIVE_EXCLUSIVEsluit niet insluit niet in
SPAN_INCLUSIVE_INCLUSIVEsluit insluit in
SPAN_EXCLUSIVE_INCLUSIVEsluit niet insluit in
SPAN_INCLUSIVE_EXCLUSIVEsluit insluit niet in

De juiste keuze van de flag is kritisch voor Editable-tekst in EditText, waar de gebruiker tekens kan invoegen en verwijderen. Voor alleen-lezen TextView wordt meestal SPAN_EXCLUSIVE_EXCLUSIVE gebruikt — de stijl wordt alleen toegepast op het oorspronkelijke bereik en wordt niet uitgebreid bij programmatische wijzigingen.

Belangrijkste spanklassen in Android SDK

Android SDK biedt meer dan 25 ingebouwde klassen van spans die de meeste tekststylingtaken dekken. Elke klasse implementeert de interface CharacterStyle of ParagraphStyle en accepteert parameters via de constructor. Alle klassen bevinden zich in het pakket android.text.style en zijn beschikbaar zonder extra afhankelijkheden aan te sluiten.

Spans voor kleur en achtergrond

ForegroundColorSpan stelt de tekstkleur in voor het opgegeven bereik, met kleur in int-formaat. BackgroundColorSpan kleurt de achtergrond onder de tekst, handig voor het markeren van zoekopdrachten. AbsoluteSizeSpan stelt de exacte lettergrootte in pixels in, RelativeSizeSpan — een vermenigvuldiger ten opzichte van de basislettergrootte van de tekst in TextView.

Spans voor lettertype

StyleSpan accepteert de constanten Typeface.NORMAL, Typeface.BOLD, Typeface.ITALIC of BOLD_ITALIC en wijzigt het uiterlijk van tekens. UnderlineSpan voegt onderstreping toe, StrikethroughSpan — doorhaling. SuperscriptSpan en SubscriptSpan maken superscript en subscript. TypefaceSpan maakt het mogelijk om een aangepast lettertype in te stellen via een Typeface-object voor een tekstbereik.

Interactieve spans

ClickableSpan is een abstracte klasse voor het maken van klikbare tekstgedeelten. Bij indrukken wordt de methode onClick() aangeroepen. Om klikken te laten werken, moet TextView setMovementMethod(LinkMovementMethod.getInstance()) hebben. URLSpan is een subklasse van ClickableSpan voor hyperlinks met automatisch openen van de browser. ClickableSpan wordt vaak gecombineerd met ForegroundColorSpan om de link visueel te markeren met blauw.

kotlin
val spannable = SpannableString("Open developer.android.com")
spannable.setSpan(
    URLSpan("https://developer.android.com"),
    9, 31, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
spannable.setSpan(
    ForegroundColorSpan(Color.BLUE),
    9, 31, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
textView.text = spannable
textView.movementMethod = LinkMovementMethod.getInstance()

Zonder LinkMovementMethod worden klikken op URLSpan niet verwerkt. MovementMethod is verantwoordelijk voor het onderscheppen van aanraakgebeurtenissen en het zoeken naar ClickableSpan op de aanraakpositie. De gekleurde span maakt de link zichtbaar voor de gebruiker.

SpannableString gebruiken in code

Werken met SpannableString begint met het maken van een instantie uit een tekststring en het achtereenvolgens toepassen van spans via de methode setSpan(). De methode accepteert vier parameters: het span-object, de beginpositie, de eindpositie en de flags. Na het instellen van alle spans wordt het object doorgegeven aan TextView via setText().

Tekstkleur en -grootte

We maken een string waarbij het eerste woord rood en vergroot is. Hiervoor wordt ForegroundColorSpan voor kleur en RelativeSizeSpan voor schaal gebruikt. Beide spans worden onafhankelijk van elkaar op hetzelfde bereik toegepast — de volgorde van setSpan-aanroepen doet er niet toe.

kotlin
val text = "Header: remaining text"
val spannable = SpannableString(text)
val colorSpan = ForegroundColorSpan(Color.RED)
val sizeSpan = RelativeSizeSpan(1.5f)
spannable.setSpan(colorSpan, 0, 9, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
spannable.setSpan(sizeSpan, 0, 9, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
textView.text = spannable

Tekens van positie 0 tot 9 krijgen beide stijlen tegelijk. TextView past automatisch alle spans toe bij het renderen — er zijn geen extra aanroepen nodig. RelativeSizeSpan met een vermenigvuldiger van 1.5f vergroot het lettertype met 50% ten opzichte van de basis.

Combineren met HTML-tags

Html.fromHtml() maakt een Spanned-object uit een HTML-string, maar de set ondersteunde tags is beperkt. SpannableString geeft volledige controle over elk attribuut zonder de beperkingen van HTML. Als HTML moet worden omgezet in spans met het toevoegen van aangepaste stijlen, kan Html.fromHtml() als basis worden gebruikt, waarna wordt aangevuld met spans via setSpan().

kotlin
val htmlText = Html.fromHtml(
    "<b>Important:</b> check the data",
    Html.FROM_HTML_MODE_LEGACY
)
val spannable = SpannableString(htmlText)
spannable.setSpan(
    ForegroundColorSpan(Color.RED),
    0, 6, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
textView.text = spannable

Het resultaat — de tekst „Belangrijk:“ zal vet (uit HTML) en rood (uit de span) zijn. Deze benadering is handig bij het werken met servercontent, waar een deel van de opmaak via HTML wordt ingesteld en een deel programmatisch aan de clientzijde wordt toegevoegd.

Meerdere spans combineren

SpannableString maakt het mogelijk om een onbeperkt aantal spans toe te passen op hetzelfde of overlappende bereik. Het combineren van spans is een belangrijk voordeel ten opzichte van HTML-opmaak, waar geneste tags kunnen conflicteren. Spans zijn onafhankelijk en worden achtereenvolgens toegepast bij het renderen.

Bijvoorbeeld, een tekstgedeelte kan tegelijkertijd vet, rood en klikbaar worden gemaakt. Hiervoor worden drie spans gemaakt — StyleSpan, ForegroundColorSpan en ClickableSpan — en elk wordt toegepast op hetzelfde bereik. De volgorde van toepassing heeft geen invloed op het resultaat, omdat elke span verantwoordelijk is voor zijn eigen teksteigenschap.

Overlapping van spans van verschillende typen

Als spans van verschillende typen gedeeltelijk overlappen, werkt elk onafhankelijk binnen zijn eigen grenzen. ForegroundColorSpan op bereik 0-10 en StyleSpan(BOLD) op bereik 5-15 geven rode vette tekst op het gedeelte 5-10 en alleen vet op 10-15. Er ontstaan geen conflicten, omdat elke span zijn eigen attribuut wijzigt bij het renderen.

Lijst van spans ophalen

De methode getSpans(int start, int end, Class type) retourneert een array van spans die binnen het opgegeven bereik vallen. Dit is handig om te controleren welke stijlen zijn toegepast of om specifieke spans te verwijderen. Met nextSpanTransition() kan worden geïtereerd over de grenzen van spanwijzigingen — dit is de basis van aangepaste TextView-objecten die moeten weten waar de stijl verandert.

SpannableStringBuilder voor tekstconstructie

SpannableStringBuilder is een klasse voor het stapsgewijs bouwen van gestileerde tekst met de mogelijkheid om fragmenten in te voegen, te vervangen en te verwijderen. In tegenstelling tot SpannableString, die uit een kant-en-klare string wordt gemaakt en onveranderlijk is, maakt Builder het mogelijk om tekstgedeelten achtereenvolgens toe te voegen en stijlen onderweg toe te kennen. Dit is de ideale keuze voor samengestelde berichten: logs, chats, nieuwsheaders met dynamische labels.

Builder implementeert de interfaces Spannable en Editable, wat het compatibel maakt met EditText. De gebruiker kan de tekst bewerken en de stijlen blijven behouden en worden correct verschoven bij het invoegen van nieuwe tekens. SpannableString, dat onveranderlijk is, is niet geschikt voor bewerkbare velden.

Keten van bewerkingen

De methode append() retourneert de builder zelf, waardoor een keten van aanroepen kan worden opgebouwd. Na het toevoegen van tekst worden spans toegepast via setSpan(). Posities worden aangegeven ten opzichte van de huidige lengte van de builder. Insert() en replace() zijn ook beschikbaar voor nauwkeurigere controle over de inhoud.

kotlin
val builder = SpannableStringBuilder()
    .append("New ")
    .append("comment")
val blue = ForegroundColorSpan(Color.BLUE)
val gray = ForegroundColorSpan(Color.GRAY)
builder.setSpan(blue, 0, 6, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
builder.setSpan(gray, 6, 17, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
textView.text = builder

De tekst „Nieuw “ is blauw gekleurd en „reactie“ grijs. Bij het invoegen van extra tekens ertussen, zal de span de nieuwe tekst niet beïnvloeden vanwege de EXCLUSIVE-flags. Builder corrigeert automatisch de interne indices bij wijzigingen.

Prestaties en optimalisatie van spans

Het gebruik van een groot aantal spans beïnvloedt de renderingprestaties van TextView. Elke span roept de methode updateDrawState() of updateMeasureState() aan bij elke herrendering. Het wordt aanbevolen om het aantal spans per TextView te beperken tot 50–100 voor comfortabel werken op middensegment apparaten. Spans die de tekstgrootte wijzigen (RelativeSizeSpan, AbsoluteSizeSpan) vereisen een herberekening van de layout bij elke wijziging, wat aanzienlijk duurder is dan spans alleen voor kleur of onderstreping.

TextAppearanceSpan

TextAppearanceSpan maakt het mogelijk om een volledige set stijlen uit een xml-bron android:textAppearance toe te passen met een enkele setSpan()-bewerking. In plaats van drie afzonderlijke spans (kleur, grootte, lettertype) wordt een enkele TextAppearanceSpan met een verwijzing naar de stijl gebruikt. Dit vermindert het aantal objecten en vereenvoudigt het onderhoud — een wijziging van de stijl in de bron wordt automatisch toegepast op alle teksten die deze span gebruiken.

Hergebruik van objecten

Het maken van een nieuw exemplaar van een span voor elke setSpan() leidt tot extra belasting van de garbage collector. Optimaal is het maken van constante objecten van spans als ze herhaaldelijk worden toegepast. Bijvoorbeeld, ForegroundColorSpan(Color.RED) kan worden opgeslagen in een companion object en worden hergebruikt. Echter, spans met toestand (ClickableSpan met verschillende handlers) moeten voor elk geval afzonderlijk worden gemaakt.

Meten en profileren

Voor het diagnosticeren van prestatieproblemen met spans gebruikt u Layout Inspector in Android Studio en de GPU-profiler. Als TextView met een groot aantal spans merkbaar vertraagt bij scrollen, overweeg dan om een deel van de spans te vervangen door statische stijlen via TextAppearanceSpan of het aantal spans te verminderen door attributen te combineren in aangepaste UpdateAppearance-implementaties.

Veelgestelde vragen

Waarin verschilt SpannableString van een gewone String?

String is een onveranderlijke tekenreeks zonder ondersteuning voor stijlen. SpannableString slaat dezelfde tekens op, maar bevat daarnaast een array van Span-objecten met opmaakinformatie. TextView bepaalt het type van de doorgegeven CharSequence en past de spans toe op de corresponderende bereiken bij het renderen. String negeert alle stijlkenmerken en wordt weergegeven als platte tekst.

Hoe verwijder ik alle spans uit SpannableString?

De methode removeSpan(Object span) verwijdert een specifieke span. Voor volledige opschoning roept u getSpans(0, length, Object::class.java) aan, die een array van alle spans retourneert, en verwijdert u vervolgens elke span via removeSpan. Als alternatief maakt u een nieuwe SpannableString(text.toString()) zonder spans. SpannableStringBuilder heeft een methode clear() die zowel de tekst als de spans verwijdert.

Werkt SpannableString in EditText?

SpannableString werkt in EditText, maar voor bewerkbare tekst heeft SpannableStringBuilder de voorkeur, die Editable implementeert. EditText vereist de Editable-interface om wijzigingen bij te houden. Als SpannableString aan EditText wordt doorgegeven, wordt de tekst met stijlen weergegeven, maar bij bewerken converteert Android deze naar Editable, wat een deel van de spans kan resetten.

Kan ik SpannableString gebruiken in Compose?

In Jetpack Compose worden Android SDK-spans niet direct gebruikt. In plaats daarvan biedt Compose AnnotatedString — zijn eigen equivalent van SpannableString met vergelijkbare mogelijkheden: SpanStyle voor stijlen van individuele tekens en ParagraphStyle voor alinea’s. Conversie van SpannableString naar AnnotatedString is mogelijk via buildAnnotatedString met iteratie over de spans.

Hoe maak ik een aangepaste Span?

Maak een klasse die overerft van CharacterStyle en overschrijf de methode updateDrawState(TextPaint tp). In de methode wijzigt u de eigenschappen van TextPaint: kleur, lijndikte, effecten. Voor metrische wijzigingen gebruikt u UpdateLayout of MetricAffectingSpan. Aangepaste spans worden toegepast via setSpan() net als ingebouwde spans.

Samenvatting

  • SpannableString — Android-klasse voor tekststyling via Span-objecten met koppeling aan tekenbereiken
  • CharacterStyle beïnvloedt individuele tekens, ParagraphStyle — hele alinea’s
  • Belangrijkste spans: ForegroundColorSpan, StyleSpan, RelativeSizeSpan, URLSpan, ClickableSpan
  • SpannableStringBuilder — veranderlijke versie voor dynamische tekstconstructie met Editable
  • Combineren van spans is veilig — elke span wijzigt onafhankelijk zijn eigen attribuut
  • Span flags beheren het gedrag van de span bij het invoegen van tekst op grenzen
  • Optimalisatie: gebruik TextAppearanceSpan voor stijlgroepen en beperk het aantal spans tot 100

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook