SpannableString: nedir, stil sınıfları ve nasıl çalışır

Yazar: IT Sectr Yayınlanma: 2026-07-23 Okuma süresi: 10 dk

SpannableString, android.text paketindeki bir Android SDK sınıfıdır ve TextView'de tek bir metin dizesinin farklı bölümlerine birden çok stil uygulamanıza olanak tanır. HTML işaretlemesinin aksine, SpannableString, Span nesneleri düzeyinde çalışarak metnin görsel görünümünü kontrol eder: renk, boyut, yazı tipi, alt çizgi ve etkileşimli öğeler. Google Developers'a göre SpannableString, bağlantıları biçimlendirmek için Android sistem bileşenlerinde kullanılır. Üçüncü taraf kitaplıklar olmadan metin stilize etmenin birincil yoludur.

Önemli Noktalar

  • SpannableString — Span nesneleri aracılığıyla metin stilize etmek için Android sınıfı, oluşturulduktan sonra değişmez
  • Span'lar CharacterStyle (tek tek karakterler) ve ParagraphStyle (tüm paragraflar) olarak ikiye ayrılır
  • ForegroundColorSpan metin rengini değiştirir, StyleSpan kalın ve italikten sorumludur
  • SpannableStringBuilder — Editable desteğiyle dinamik metin oluşturma için değiştirilebilir sürüm
  • Span bayrakları, aralık sınırlarında metin eklenirken veya silinirken span davranışını belirler

SpannableString Nedir?

SpannableString, Spannable arabirimini uygulayan, görsel görüntülemeyi kontrol eden bir dizi Span nesnesiyle birlikte metni depolayan bir Android sınıfıdır. Normal String'in aksine, SpannableString, belirli karakter aralıklarına stil öznitelikleri eklemenize olanak tanır: metnin bir kısmını kırmızı yapmak, bir başlıkta yazı tipi boyutunu artırmak veya bir paragraf içine tıklanabilir bir bağlantı eklemek.

Sınıf android.text paketindedir ve API Level 1'den beri kullanılabilir. SpannableString değişmezdir — bir kez oluşturulduktan sonra yapısı sabitlenir ve metni değiştirmek için yeni bir nesne oluşturulması gerekir. Dinamik düzenleme için, stilleri kaybetmeden karakter ekleme ve silmeyi destekleyen SpannableStringBuilder kullanılır.

CharSequence'dan Farkı

CharSequence, String, StringBuilder ve SpannableString tarafından uygulanan metin verileri için temel arabirimdir. SpannableString ve String arasındaki temel fark, bir alt dizeye isteğe bağlı nesneler ekleme desteğidir. TextView, Spannable arabirimini tanır ve işleme sırasında karşılık gelen metin bölümlerine span nesnelerini uygular. TextView'e normal bir String iletirseniz, hiçbir stil uygulanmaz.

İç Yapı

SpannableString, metni bir char[] dizisi olarak ve span nesnelerini başlangıç ve bitiş konumları hakkında meta verilerle ayrı bir dizi olarak saklar. setSpan(what, start, end, flags) çağrıldığında, what nesnesi aralık bilgisiyle birlikte listeye kaydedilir. İşleme sırasında TextView, görüntülenen aralık içindeki tüm span'ları sırayla uygulayarak updateDrawState ve updateMeasureState yöntemlerini çağırır.

Span Türleri: CharacterStyle ve ParagraphStyle

CharacterStyle, satırlardaki konumlarına bakılmaksızın tek tek karakterleri etkileyen span'lar için temel sınıftır. Buna ForegroundColorSpan (metin rengi), RelativeSizeSpan (göreli boyut), StyleSpan (kalın ve italik), UnderlineSpan (alt çizgi) ve diğerleri dahildir. Karakter span'ları, belirtilen aralıktaki her karaktere ayrı ayrı uygulanır.

ParagraphStyle, tüm paragrafları etkileyen span'lar için bir arabirimdir. En bilinen temsilcisi AlignmentSpan'dır ve tüm paragrafı sola, ortaya veya sağa hizalar. Paragraf span'ları tüm paragrafı kapsamalıdır; aksi takdirde Android bunların uygulanmasını yok sayar. Bu sınırlama, hizalama veya girintinin yalnızca tüm bir metin bloğu için anlamlı olmasından kaynaklanır.

Span Bayrakları

Span bayrakları, aralığının sınırlarında metin eklendiğinde veya silindiğinde span'in davranışını tanımlayan dört sabittir. SPAN_EXCLUSIVE_EXCLUSIVE, span'i yalnızca orijinal sınırlar içinde etkin tutar, SPAN_INCLUSIVE_INCLUSIVE, sınırlara metin eklendiğinde onu genişletir. SPAN_EXCLUSIVE_INCLUSIVE ve SPAN_INCLUSIVE_EXCLUSIVE, aralığın başlangıcı ve sonu için karma davranış sağlar.

BayrakSola EklemeSağa Ekleme
SPAN_EXCLUSIVE_EXCLUSIVEdahil etmezdahil etmez
SPAN_INCLUSIVE_INCLUSIVEdahil ederdahil eder
SPAN_EXCLUSIVE_INCLUSIVEdahil etmezdahil eder
SPAN_INCLUSIVE_EXCLUSIVEdahil ederdahil etmez

Doğru bayrağı seçmek, kullanıcının karakter ekleyip silebildiği EditText içindeki Editable metin için kritiktir. Salt okunur TextView için genellikle SPAN_EXCLUSIVE_EXCLUSIVE kullanılır — stil yalnızca orijinal aralığa uygulanır ve programatik değişikliklerle genişlemez.

Android SDK'daki Ana Span Sınıfları

Android SDK, çoğu metin stilize etme görevini kapsayan 25'ten fazla yerleşik span sınıfı sağlar. Her sınıf, CharacterStyle veya ParagraphStyle arabirimini uygular ve yapıcısı aracılığıyla parametreleri kabul eder. Tüm sınıflar android.text.style paketindedir ve ek bağımlılık olmadan kullanılabilir.

Renk ve Arka Plan Span'ları

ForegroundColorSpan, belirtilen bir aralık için metin rengini ayarlar ve int biçiminde bir renk kabul eder. BackgroundColorSpan, metnin arkasındaki arka planı boyar, arama sonuçlarını vurgulamak için kullanışlıdır. AbsoluteSizeSpan piksel cinsinden tam yazı tipi boyutunu ayarlar, RelativeSizeSpan TextView'deki temel metin boyutuna göre bir çarpan uygular.

Yazı Tipi Span'ları

StyleSpan, Typeface.NORMAL, Typeface.BOLD, Typeface.ITALIC veya BOLD_ITALIC sabitlerini kabul eder ve karakterlerin yazı tipini değiştirir. UnderlineSpan alt çizgi ekler, StrikethroughSpan üstü çizili ekler. SuperscriptSpan ve SubscriptSpan üst simge ve alt simge oluşturur. TypefaceSpan, bir metin aralığı için bir Typeface nesnesi aracılığıyla özel yazı tipi ayarlamaya olanak tanır.

Etkileşimli Span'lar

ClickableSpan, tıklanabilir metin bölümleri oluşturmak için soyut bir sınıftır. Dokunulduğunda onClick() yöntemi çağrılır. Tıklamaların çalışması için TextView'de setMovementMethod(LinkMovementMethod.getInstance()) bulunmalıdır. URLSpan, otomatik tarayıcı açma ile köprüler için ClickableSpan'in bir alt sınıfıdır. ClickableSpan, bağlantıyı mavi renkte görsel olarak vurgulamak için genellikle ForegroundColorSpan ile birleştirilir.

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()

LinkMovementMethod olmadan, URLSpan üzerindeki tıklamalar işlenmez. MovementMethod, dokunma olaylarını yakalamaktan ve dokunma konumunda ClickableSpan'i bulmaktan sorumludur. Renk span'i, bağlantıyı kullanıcıya görünür kılar.

Kod İçinde SpannableString Kullanımı

SpannableString ile çalışmak, bir metin dizesinden bir örnek oluşturarak ve setSpan() yöntemi aracılığıyla sırayla span'ları uygulayarak başlar. Yöntem dört parametre alır: span nesnesi, başlangıç konumu, bitiş konumu ve bayraklar. Tüm span'ları ayarladıktan sonra nesne, setText() aracılığıyla TextView'e iletilir.

Metin Rengi ve Boyutu

İlk kelimenin kırmızı ve büyütülmüş olduğu bir dize oluşturalım. Bunun için renk için ForegroundColorSpan ve ölçek için RelativeSizeSpan kullanırız. Her iki span da bağımsız olarak aynı aralığa uygulanır — setSpan çağrılarının sırası önemli değildir.

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

0'dan 9'a kadar olan karakterler her iki stili aynı anda alır. TextView, işleme sırasında tüm span'ları otomatik olarak uygular — ek çağrı gerekmez. 1.5f çarpanlı RelativeSizeSpan, tabana göre yazı tipi boyutunu %50 artırır.

HTML Etiketleriyle Birleştirme

Html.fromHtml(), bir HTML dizesinden Spanned nesnesi oluşturur, ancak desteklenen etiket kümesi sınırlıdır. SpannableString, HTML sınırlamaları olmadan her öznitelik üzerinde tam kontrol sağlar. HTML'yi span'lara dönüştürmeniz ve ardından özel stiller eklemeniz gerekiyorsa, Html.fromHtml()'ı temel olarak kullanabilir ve ardından setSpan() aracılığıyla span'larla tamamlayabilirsiniz.

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

Sonuç — “Önemli:” metni (HTML'den) kalın ve (span'den) kırmızı olacaktır. Bu yaklaşım, biçimlendirmenin bir kısmının HTML'de belirtildiği ve bir kısmının istemci tarafında programlı olarak eklendiği sunucu içeriğiyle çalışırken kullanışlıdır.

Birden Çok Span'in Birleştirilmesi

SpannableString, aynı veya çakışan aralığa sınırsız sayıda span uygulamaya olanak tanır. Span'ları birleştirmek, iç içe etiketlerin çakışabileceği HTML işaretlemesine göre önemli bir avantajdır. Span'lar bağımsızdır ve işleme sırasında sırayla uygulanır.

Örneğin, bir metin bölümünü aynı anda kalın, kırmızı ve tıklanabilir yapabilirsiniz. Bunu yapmak için üç span oluşturun — StyleSpan, ForegroundColorSpan ve ClickableSpan — ve her birini aynı aralığa uygulayın. Uygulama sırası sonucu etkilemez, çünkü her span kendi metin özniteliğinden sorumludur.

Farklı Türdeki Span'lerin Çakışması

Farklı türdeki span'ler kısmen çakışırsa, her biri kendi sınırları içinde bağımsız olarak çalışır. 0–10 aralığındaki ForegroundColorSpan ve 5–15 aralığındaki StyleSpan(BOLD), 5–10 bölümünde kalın kırmızı metin ve 10–15'te yalnızca kalın metin verecektir. Her span işleme sırasında kendi özniteliğini değiştirdiğinden hiçbir çakışma oluşmaz.

Span Listesini Alma

getSpans(int start, int end, Class type) yöntemi, belirtilen aralık içindeki span'ların bir dizisini döndürür. Bu, hangi stillerin zaten uygulandığını kontrol etmek veya belirli span'ları kaldırmak için kullanışlıdır. nextSpanTransition() ile span değişim sınırları üzerinde yineleme yapabilirsiniz — bu, stilin nerede değiştiğini bilmesi gereken özel TextView uygulamalarının temelidir.

Metin Oluşturmak İçin SpannableStringBuilder

SpannableStringBuilder, parçaları ekleme, değiştirme ve silme yeteneğiyle stillendirilmiş metnin adım adım oluşturulması için bir sınıftır. Hazır bir dizeden oluşturulan ve değişmez olan SpannableString'in aksine, Builder metin parçalarını sırayla eklemeye ve anında stiller atamaya olanak tanır. Bu, bileşik mesajlar için idealdir: günlükler, sohbetler, dinamik etiketli haber başlıkları.

Builder, Spannable ve Editable arabirimlerini uygulayarak onu EditText ile uyumlu hale getirir. Kullanıcı metni düzenleyebilir ve stiller korunur ve yeni karakterler eklendiğinde doğru şekilde kaydırılır. SpannableString, değişmez olduğu için düzenlenebilir alanlar için uygun değildir.

Yöntem Zincirleme

append() yöntemi, yöntem zincirlemeye izin vererek oluşturucunun kendisini döndürür. Metin eklendikten sonra, span'lar setSpan() aracılığıyla uygulanır. Konumlar, geçerli oluşturucu uzunluğuna göre belirtilir. Daha kesin içerik kontrolü için Insert() ve replace() de mevcuttur.

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

“Yeni ” metni mavi, “yorum” metni gri renklidir. Aralarına ek karakterler eklendiğinde, EXCLUSIVE bayrakları sayesinde span yeni metni etkilemez. Builder, değişiklik sırasında iç dizinleri otomatik olarak ayarlar.

Span Performansı ve Optimizasyonu

Çok sayıda span kullanmak TextView'ün işleme performansını etkiler. Her span, her yeniden çizimde updateDrawState() veya updateMeasureState() yöntemini çağırır. Orta sınıf cihazlarda rahat performans için TextView başına span sayısının 50–100 ile sınırlandırılması önerilir. Metin boyutunu değiştiren span'lar (RelativeSizeSpan, AbsoluteSizeSpan), her değişiklikte düzen yeniden hesaplaması gerektirir ve bu, yalnızca renk veya alt çizgi span'larından önemli ölçüde daha pahalıdır.

TextAppearanceSpan

TextAppearanceSpan, tek bir setSpan() çağrısıyla android:textAppearance XML kaynağından tüm stil kümesini uygulamaya olanak tanır. Üç ayrı span (renk, boyut, yazı tipi) yerine, bir stil referansına sahip tek bir TextAppearanceSpan kullanılır. Bu, nesne sayısını azaltır ve bakımı basitleştirir — kaynaktaki stili değiştirmek, bu span'i kullanan tüm metinlere otomatik olarak uygulanır.

Nesne Yeniden Kullanımı

Her setSpan() için yeni bir span örneği oluşturmak, çöp toplayıcıya ek yük bindirir. Tekrar tekrar kullanılıyorlarsa sabit span nesneleri oluşturmak idealdir. Örneğin, ForegroundColorSpan(Color.RED) bir companion nesnesinde saklanabilir ve yeniden kullanılabilir. Ancak, durumlu span'lar (farklı işleyicilere sahip ClickableSpan) her durum için ayrı ayrı oluşturulmalıdır.

Ölçüm ve Profil Oluşturma

Span performans sorunlarını teşhis etmek için Android Studio'da Layout Inspector ve GPU profilleyicisini kullanın. Çok sayıda span içeren bir TextView kaydırma sırasında belirgin şekilde yavaşlıyorsa, TextAppearanceSpan aracılığıyla bazı span'ları statik stillerle değiştirmeyi veya özel UpdateAppearance uygulamalarında öznitelikleri birleştirerek span sayısını azaltmayı düşünün.

Sıkça Sorulan Sorular

SpannableString normal String'den nasıl farklıdır?

String, stil desteği olmayan değişmez bir karakter dizisidir. SpannableString aynı karakterleri depolar ancak ek olarak biçimlendirme bilgilerine sahip bir dizi Span nesnesi içerir. TextView, iletilen CharSequence'ın türünü belirler ve işleme sırasında karşılık gelen aralıklara span'ları uygular. String, tüm stil özniteliklerini yok sayar ve düz metin olarak görüntülenir.

SpannableString'den tüm span'lar nasıl kaldırılır?

removeSpan(Object span) yöntemi belirli bir span'i kaldırır. Tam temizlik için, tüm span'ların bir dizisini döndüren getSpans(0, length, Object::class.java) öğesini çağırın ve ardından her birini removeSpan aracılığıyla kaldırın. Alternatif olarak, span'sız yeni bir SpannableString(text.toString()) oluşturun. SpannableStringBuilder, hem metni hem de span'ları kaldıran bir clear() yöntemine sahiptir.

SpannableString EditText'te çalışır mı?

SpannableString EditText'te çalışır, ancak düzenlenebilir metin için Editable'ı uygulayan SpannableStringBuilder tercih edilir. EditText, değişiklikleri izlemek için Editable arabirimini gerektirir. SpannableString'i EditText'e iletirseniz, metin stillerle görüntülenir, ancak düzenleme sırasında Android onu Editable'a dönüştürür ve bu da bazı span'ları sıfırlayabilir.

SpannableString Compose'da kullanılabilir mi?

Jetpack Compose'da, Android SDK span'ları doğrudan kullanılmaz. Bunun yerine Compose, benzer yeteneklere sahip SpannableString'in kendi eşdeğeri olan AnnotatedString'i sağlar: tek tek karakter stilleri için SpanStyle ve paragraflar için ParagraphStyle. SpannableString'i AnnotatedString'e dönüştürme, span'lar üzerinde yineleme yapan buildAnnotatedString aracılığıyla mümkündür.

Özel bir Span nasıl oluşturulur?

CharacterStyle öğesini genişleten bir sınıf oluşturun ve updateDrawState(TextPaint tp) yöntemini geçersiz kılın. Yöntemin içinde TextPaint özelliklerini değiştirin: renk, çizgi kalınlığı, efektler. Metrik değişiklikler için UpdateLayout veya MetricAffectingSpan kullanın. Özel span'lar, yerleşik span'lar gibi setSpan() aracılığıyla uygulanır.

Özet

  • SpannableString — karakter aralığı bağlamayla Span nesneleri aracılığıyla metin stilize etmek için Android sınıfı
  • CharacterStyle tek tek karakterleri etkiler, ParagraphStyle tüm paragrafları etkiler
  • Ana span'lar: ForegroundColorSpan, StyleSpan, RelativeSizeSpan, URLSpan, ClickableSpan
  • SpannableStringBuilder — Editable ile dinamik metin oluşturma için değiştirilebilir sürüm
  • Span'ları birleştirme güvenlidir — her span kendi özniteliğini bağımsız olarak değiştirir
  • Span bayrakları, sınırlarda metin eklenirken span davranışını kontrol eder
  • Optimizasyon: stil grupları için TextAppearanceSpan kullanın ve span'ları 100 ile sınırlayın

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun