SpannableString adalah kelas Android SDK dari paket android.text yang memungkinkan penerapan beberapa gaya ke berbagai bagian dari satu string teks di TextView. Tidak seperti markup HTML, SpannableString bekerja pada tingkat objek Span, mengelola tampilan visual teks: warna, ukuran, jenis huruf, garis bawah, dan elemen interaktif. Menurut Google Developers, SpannableString digunakan dalam komponen sistem Android untuk memformat tautan. Ini adalah cara utama menata teks tanpa menghubungkan pustaka pihak ketiga.
Poin Utama
SpannableString adalah kelas Android yang mengimplementasikan antarmuka Spannable, menyimpan teks bersama dengan kumpulan objek Span yang mengelola tampilan visual. Tidak seperti String biasa, SpannableString memungkinkan penempelan atribut gaya ke rentang karakter tertentu: membuat bagian teks menjadi merah, memperbesar font di judul, atau menambahkan tautan yang dapat diklik di dalam paragraf.
Kelas ini berada dalam paket android.text dan tersedia sejak API Level 1. SpannableString tidak dapat diubah — setelah dibuat, strukturnya ditetapkan, dan penggantian teks memerlukan pembuatan objek baru. Untuk pengeditan dinamis digunakan SpannableStringBuilder, yang mendukung penyisipan dan penghapusan karakter tanpa kehilangan gaya.
CharSequence adalah antarmuka dasar untuk data teks, yang diimplementasikan oleh String, StringBuilder, dan SpannableString. Perbedaan utama antara SpannableString dan String terletak pada dukungan untuk menempelkan objek arbitrer ke substring. TextView mengenali antarmuka Spannable dan saat rendering menerapkan objek span ke bagian teks yang sesuai. Jika String biasa diberikan ke TextView, tidak ada gaya yang akan diterapkan.
SpannableString menyimpan teks sebagai larik char[] dan larik terpisah dari objek span dengan metadata tentang posisi awal dan akhir. Saat memanggil setSpan(what, start, end, flags), objek what disimpan dalam daftar bersama informasi tentang rentang. Saat rendering, TextView secara berurutan menerapkan semua span yang berada dalam rentang yang ditampilkan, memanggil metode updateDrawState dan updateMeasureState.
CharacterStyle adalah kelas dasar untuk span yang memengaruhi karakter individu terlepas dari posisinya dalam baris. Ini termasuk ForegroundColorSpan (warna teks), RelativeSizeSpan (ukuran relatif), StyleSpan (tebal dan miring), UnderlineSpan (garis bawah) dan lainnya. Character-span diterapkan pada setiap karakter dalam rentang yang ditentukan secara individual.
ParagraphStyle adalah antarmuka untuk span yang memengaruhi seluruh paragraf. Perwakilan paling terkenal adalah AlignmentSpan, yang meratakan seluruh paragraf ke kiri, tengah, atau kanan. Paragraph-span harus mencakup seluruh paragraf, jika tidak Android mengabaikan penerapannya. Pembatasan ini terkait dengan fakta bahwa perataan atau indentasi hanya masuk akal untuk seluruh blok teks.
Span flags adalah empat konstanta yang menentukan perilaku span saat menyisipkan atau menghapus teks pada batas rentangnya. SPAN_EXCLUSIVE_EXCLUSIVE menjaga span tetap aktif hanya di dalam batas asli, SPAN_INCLUSIVE_INCLUSIVE memperluasnya saat menambahkan teks ke batas. SPAN_EXCLUSIVE_INCLUSIVE dan SPAN_INCLUSIVE_EXCLUSIVE memberikan perilaku campuran untuk awal dan akhir rentang.
| Flag | Sisip Kiri | Sisip Kanan |
|---|---|---|
| SPAN_EXCLUSIVE_EXCLUSIVE | tidak termasuk | tidak termasuk |
| SPAN_INCLUSIVE_INCLUSIVE | termasuk | termasuk |
| SPAN_EXCLUSIVE_INCLUSIVE | tidak termasuk | termasuk |
| SPAN_INCLUSIVE_EXCLUSIVE | termasuk | tidak termasuk |
Pemilihan flag yang tepat sangat penting untuk teks Editable di EditText, di mana pengguna dapat menyisipkan dan menghapus karakter. Untuk TextView hanya baca biasanya digunakan SPAN_EXCLUSIVE_EXCLUSIVE — gaya hanya diterapkan pada rentang asli dan tidak meluas dengan perubahan terprogram.
Android SDK menyediakan lebih dari 25 kelas bawaan span yang mencakup sebagian besar tugas penataan teks. Setiap kelas mengimplementasikan antarmuka CharacterStyle atau ParagraphStyle dan menerima parameter melalui konstruktor. Semua kelas berada dalam paket android.text.style dan tersedia tanpa menghubungkan dependensi tambahan.
ForegroundColorSpan mengatur warna teks untuk rentang yang ditentukan, menerima warna dalam format int. BackgroundColorSpan mewarnai latar belakang di bawah teks, berguna untuk menyorot kueri pencarian. AbsoluteSizeSpan mengatur ukuran font yang tepat dalam piksel, RelativeSizeSpan — pengali relatif terhadap ukuran dasar teks di TextView.
StyleSpan menerima konstanta Typeface.NORMAL, Typeface.BOLD, Typeface.ITALIC atau BOLD_ITALIC dan mengubah tampilan karakter. UnderlineSpan menambahkan garis bawah, StrikethroughSpan — coretan. SuperscriptSpan dan SubscriptSpan membuat superskrip dan subskrip. TypefaceSpan memungkinkan pengaturan font khusus melalui objek Typeface untuk rentang teks.
ClickableSpan adalah kelas abstrak untuk membuat bagian teks yang dapat diklik. Saat ditekan, metode onClick() dipanggil. Agar klik berfungsi, TextView harus memiliki setMovementMethod(LinkMovementMethod.getInstance()). URLSpan adalah subkelas ClickableSpan untuk hyperlink dengan pembukaan browser otomatis. ClickableSpan sering dikombinasikan dengan ForegroundColorSpan untuk menyorot tautan secara visual dengan warna biru.
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()
Tanpa LinkMovementMethod, klik pada URLSpan tidak akan diproses. MovementMethod bertanggung jawab untuk mencegat peristiwa sentuh dan mencari ClickableSpan di posisi sentuhan. Span berwarna membuat tautan terlihat oleh pengguna.
Bekerja dengan SpannableString dimulai dengan membuat instance dari string teks dan menerapkan span secara berurutan melalui metode setSpan(). Metode ini menerima empat parameter: objek span, posisi awal, posisi akhir, dan flag. Setelah mengatur semua span, objek diberikan ke TextView melalui setText().
Kita akan membuat string di mana kata pertama akan berwarna merah dan berukuran lebih besar. Untuk ini digunakan ForegroundColorSpan untuk warna dan RelativeSizeSpan untuk skala. Kedua span diterapkan ke rentang yang sama secara independen satu sama lain — urutan pemanggilan setSpan tidak penting.
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
Karakter dari posisi 0 hingga 9 akan mendapatkan kedua gaya secara bersamaan. TextView secara otomatis menerapkan semua span saat rendering — tidak diperlukan panggilan tambahan. RelativeSizeSpan dengan pengali 1.5f akan meningkatkan ukuran font sebesar 50% relatif terhadap dasar.
Html.fromHtml() membuat objek Spanned dari string HTML, tetapi kumpulan tag yang didukung terbatas. SpannableString memberikan kontrol penuh atas setiap atribut tanpa batasan HTML. Jika diperlukan untuk mengonversi HTML menjadi span dengan penambahan gaya kustom, dapat menggunakan Html.fromHtml() sebagai dasar, kemudian melengkapi dengan span melalui setSpan().
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
Hasilnya — teks "Penting:" akan tebal (dari HTML) dan merah (dari span). Pendekatan ini nyaman saat bekerja dengan konten server, di mana sebagian format diatur melalui HTML, dan sebagian ditambahkan secara terprogram di sisi klien.
SpannableString memungkinkan penerapan jumlah span yang tidak terbatas pada rentang yang sama atau tumpang tindih. Menggabungkan span adalah keunggulan utama dibandingkan markup HTML, di mana tag bersarang dapat bertentangan. Span independen dan diterapkan secara berurutan saat rendering.
Misalnya, bagian teks dapat dibuat sekaligus tebal, merah, dan dapat diklik. Untuk ini, tiga span dibuat — StyleSpan, ForegroundColorSpan, dan ClickableSpan — dan masing-masing diterapkan ke rentang yang sama. Urutan penerapan tidak mempengaruhi hasil, karena setiap span bertanggung jawab atas karakteristik teksnya sendiri.
Jika span dari berbagai jenis sebagian tumpang tindih, masing-masing bekerja secara independen dalam batasnya. ForegroundColorSpan pada rentang 0-10 dan StyleSpan(BOLD) pada rentang 5-15 akan memberikan teks merah tebal pada bagian 5-10 dan hanya tebal pada 10-15. Tidak ada konflik yang muncul, karena setiap span mengubah atributnya sendiri saat rendering.
Metode getSpans(int start, int end, Class type) mengembalikan larik span yang berada dalam rentang yang ditentukan. Ini berguna untuk memeriksa gaya apa yang telah diterapkan atau untuk menghapus span tertentu. Dengan nextSpanTransition() dapat diiterasi pada batas perubahan span — ini adalah dasar kerja TextView kustom yang perlu tahu di mana gaya berubah.
SpannableStringBuilder adalah kelas untuk membangun teks bergaya langkah demi langkah dengan kemampuan menyisipkan, mengganti, dan menghapus fragmen. Tidak seperti SpannableString, yang dibuat dari string jadi dan tidak dapat diubah, Builder memungkinkan penambahan bagian teks secara berurutan dan pemberian gaya saat itu juga. Ini adalah pilihan ideal untuk pesan gabungan: log, obrolan, judul berita dengan label dinamis.
Builder mengimplementasikan antarmuka Spannable dan Editable, yang membuatnya kompatibel dengan EditText. Pengguna dapat mengedit teks, dan gaya dipertahankan dan bergeser dengan benar saat menyisipkan karakter baru. SpannableString, karena tidak dapat diubah, tidak cocok untuk bidang yang dapat diedit.
Metode append() mengembalikan builder itu sendiri, memungkinkan pembangunan rantai panggilan. Setelah menambahkan teks, span diterapkan melalui setSpan(). Posisi ditunjukkan relatif terhadap panjang builder saat ini. Insert() dan replace() juga tersedia untuk kontrol yang lebih tepat atas konten.
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
Teks "Baru " diwarnai biru, dan "komentar" diwarnai abu-abu. Saat menyisipkan karakter tambahan di antara mereka, span tidak akan mempengaruhi teks baru berkat flag EXCLUSIVE. Builder secara otomatis mengoreksi indeks internal saat modifikasi.
Penggunaan span dalam jumlah besar mempengaruhi kinerja rendering TextView. Setiap span memanggil metode updateDrawState() atau updateMeasureState() pada setiap render ulang. Disarankan untuk membatasi jumlah span per TextView hingga 50–100 untuk kenyamanan kerja pada perangkat segmen menengah. Span yang mengubah ukuran teks (RelativeSizeSpan, AbsoluteSizeSpan) memerlukan perhitungan ulang layout setiap kali berubah, yang secara signifikan lebih mahal daripada span hanya untuk warna atau garis bawah.
TextAppearanceSpan memungkinkan penerapan seluruh rangkaian gaya dari sumber xml android:textAppearance dengan satu operasi setSpan(). Alih-alih tiga span terpisah (warna, ukuran, font) digunakan satu TextAppearanceSpan dengan referensi ke gaya. Ini mengurangi jumlah objek dan menyederhanakan pemeliharaan — perubahan gaya dalam sumber secara otomatis diterapkan ke semua teks yang menggunakan span ini.
Membuat instance span baru untuk setiap setSpan() menyebabkan beban tambahan pada pengumpul sampah. Optimal untuk membuat objek konstan span jika diterapkan berulang kali. Misalnya, ForegroundColorSpan(Color.RED) dapat disimpan dalam companion object dan digunakan kembali. Namun, span dengan status (ClickableSpan dengan penangan berbeda) harus dibuat secara individual untuk setiap kasus.
Untuk mendiagnosis masalah kinerja span, gunakan Layout Inspector di Android Studio dan profiler GPU. Jika TextView dengan banyak span terasa lambat saat scroll, pertimbangkan untuk mengganti sebagian span dengan gaya statis melalui TextAppearanceSpan atau mengurangi jumlah span dengan menggabungkan atribut dalam implementasi UpdateAppearance kustom.
Pertanyaan yang Sering Diajukan
String adalah urutan karakter yang tidak dapat diubah tanpa dukungan gaya. SpannableString menyimpan karakter yang sama, tetapi tambahan berisi larik objek Span dengan informasi format. TextView menentukan jenis CharSequence yang diberikan dan menerapkan span ke rentang yang sesuai saat rendering. String mengabaikan atribut gaya apa pun dan ditampilkan sebagai teks biasa.
Metode removeSpan(Object span) menghapus span tertentu. Untuk pembersihan lengkap, panggil getSpans(0, length, Object::class.java), yang mengembalikan larik semua span, lalu hapus masing-masing melalui removeSpan. Alternatifnya, buat SpannableString baru(text.toString()) tanpa span. SpannableStringBuilder memiliki metode clear() yang menghapus teks dan span.
SpannableString berfungsi di EditText, tetapi untuk teks yang dapat diedit lebih baik menggunakan SpannableStringBuilder yang mengimplementasikan Editable. EditText memerlukan antarmuka Editable untuk melacak perubahan. Jika SpannableString diberikan ke EditText, teks akan ditampilkan dengan gaya, tetapi saat diedit Android mengonversinya menjadi Editable, yang dapat mereset sebagian span.
Di Jetpack Compose, span Android SDK tidak digunakan secara langsung. Sebagai gantinya, Compose menyediakan AnnotatedString — padanan SpannableString miliknya sendiri dengan kemampuan serupa: SpanStyle untuk gaya karakter individu dan ParagraphStyle untuk paragraf. Konversi SpannableString ke AnnotatedString dimungkinkan melalui buildAnnotatedString dengan iterasi pada span.
Buat kelas yang mewarisi CharacterStyle dan timpa metode updateDrawState(TextPaint tp). Di dalam metode, ubah properti TextPaint: warna, ketebalan garis, efek. Untuk perubahan metrik gunakan UpdateLayout atau MetricAffectingSpan. Span kustom diterapkan melalui setSpan() seperti span bawaan.
Ringkasan
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is