SpannableString — bu Android SDK-nın android.text paketindən olan sinifdir ki, TextView-də bir mətn sətirinin müxtəlif hissələrinə çoxsaylı stillər tətbiq etməyə imkan verir. HTML işarələməsindən fərqli olaraq, SpannableString Span obyektləri səviyyəsində işləyir və mətnin vizual göstərilməsini idarə edir: rəng, ölçü, yazı tərzi, altxətt və interaktiv elementlər. Google Developers məlumatına görə, SpannableString Android-in sistem komponentlərində keçidlərin formatlaşdırılması üçün istifadə olunur. Bu, üçüncü tərəf kitabxanalarını qoşmadan mətnin stilizasiyasının əsas üsuludur.
Əsas məqamlar
SpannableString — bu Spannable interfeysini həyata keçirən Android sinifidir ki, mətni Span obyektləri dəsti ilə birlikdə saxlayır və vizual göstərilməni idarə edir. Adi String-dən fərqli olaraq, SpannableString stil atributlarını konkret simvol diapazonlarına bağlamağa imkan verir: mətnin bir hissəsini qırmızı etmək, başlıqda şrifti böyütmək və ya abzas daxilində kliklənə bilən keçid əlavə etmək.
Sinif android.text paketində yerləşir və API Level 1-dən etibarən mövcuddur. SpannableString dəyişməzdir — yaradıldıqdan sonra onun strukturu sabitlənir və mətnin dəyişdirilməsi yeni obyektin yaradılmasını tələb edir. Dinamik redaktə üçün SpannableStringBuilder istifadə olunur ki, o da stilləri itirmədən simvolların daxil edilməsi və silinməsini dəstəkləyir.
CharSequence — bu mətn məlumatları üçün əsas interfeysdir ki, onu String, StringBuilder və SpannableString həyata keçirir. SpannableString-in String-dən əsas fərqi alt sətirə ixtiyari obyektlərin bağlanmasını dəstəkləməsidir. TextView Spannable interfeysini tanıyır və çəkərkən span obyektlərini mətnin müvafiq hissələrinə tətbiq edir. TextView-ə adi String ötürsəniz, heç bir stil tətbiq olunmayacaq.
SpannableString mətni char[] massivi şəklində və başlanğıc və son mövqe haqqında metadata ilə ayrıca span obyektləri massivini saxlayır. setSpan(what, start, end, flags) çağırışı zamanı what obyekti diapazon haqqında məlumatla birlikdə siyahıda saxlanılır. Çəkmə zamanı TextView göstərilən diapazona düşən bütün spanları ardıcıl olaraq tətbiq edir, updateDrawState və updateMeasureState metodlarını çağırır.
CharacterStyle — sətirlərdəki mövqeyindən asılı olmayaraq ayrı-ayrı simvollara təsir edən spanlar üçün əsas sinifdir. Buraya ForegroundColorSpan (mətn rəngi), RelativeSizeSpan (nisbi ölçü), StyleSpan (qalınlıq və kursiv), UnderlineSpan (altxətt) və digərləri daxildir. Character spanları göstərilən diapazonda hər bir simvola ayrılıqda tətbiq olunur.
ParagraphStyle — bütün abzaslara təsir edən spanlar üçün interfeysdir. Ən məşhur nümayəndəsi AlignmentSpan-dır ki, bütün abzası sol kənara, mərkəzə və ya sağ kənara düzləndirir. Paragraph spanları bütün abzası tam əhatə etməlidir, əks halda Android onların tətbiqini nəzərə almır. Bu məhdudiyyət düzləndirmə və ya abzasın yalnız tam mətn bloku üçün məna kəsb etməsi ilə bağlıdır.
Span flags — bunlar spanın davranışını onun diapazonunun sərhədlərində mətn daxil edilərkən və ya silinərkən təyin edən dörd sabitdir. SPAN_EXCLUSIVE_EXCLUSIVE spanı yalnız ilkin sərhədlər daxilində aktiv qoyur, SPAN_INCLUSIVE_INCLUSIVE onu sərhədlərə mətn əlavə edildikdə genişləndirir. SPAN_EXCLUSIVE_INCLUSIVE və SPAN_INCLUSIVE_EXCLUSIVE diapazonun başlanğıcı və sonu üçün qarışıq davranış verir.
| Flag | Sola əlavə | Sağa əlavə |
|---|---|---|
| SPAN_EXCLUSIVE_EXCLUSIVE | daxil etmir | daxil etmir |
| SPAN_INCLUSIVE_INCLUSIVE | daxil edir | daxil edir |
| SPAN_EXCLUSIVE_INCLUSIVE | daxil etmir | daxil edir |
| SPAN_INCLUSIVE_EXCLUSIVE | daxil edir | daxil etmir |
Düzgün flag seçimi EditText-də Editable mətn üçün kritikdir, çünki istifadəçi simvolları daxil edə və silə bilər. Yalnız oxunan TextView üçün adətən SPAN_EXCLUSIVE_EXCLUSIVE istifadə olunur — stil yalnız ilkin diapazona tətbiq edilir və proqram dəyişikliklərində genişlənmir.
Android SDK mətn stilizasiyası üzrə əksər tapşırıqları əhatə edən 25-dən çox daxili span sinifi təmin edir. Hər bir sinif CharacterStyle və ya ParagraphStyle interfeysini həyata keçirir və parametrləri konstruktor vasitəsilə qəbul edir. Bütün siniflər android.text.style paketində yerləşir və əlavə asılılıqları qoşmadan mövcuddur.
ForegroundColorSpan göstərilən diapazon üçün mətnin rəngini təyin edir, rəngi int formatında qəbul edir. BackgroundColorSpan mətnin altındakı fonu rəngləyir ki, bu da axtarış sorğularının vurğulanması üçün faydalıdır. AbsoluteSizeSpan pikseldə dəqiq şrift ölçüsünü təyin edir, RelativeSizeSpan isə TextView-də əsas mətn ölçüsünə nisbətən çarpandır.
StyleSpan Typeface.NORMAL, Typeface.BOLD, Typeface.ITALIC və ya BOLD_ITALIC sabitlərini qəbul edir və simvolların yazı tərzini dəyişir. UnderlineSpan altxətt əlavə edir, StrikethroughSpan isə üstündən xətt çəkir. SuperscriptSpan və SubscriptSpan yuxarı və aşağı indekslər yaradır. TypefaceSpan mətn diapazonu üçün Typeface obyekti vasitəsilə xüsusi şrift təyin etməyə imkan verir.
ClickableSpan — mətnin kliklənə bilən hissələrini yaratmaq üçün abstrakt sinifdir. Basıldıqda onClick() metodu çağırılır. Kliklərin işləməsi üçün TextView setMovementMethod(LinkMovementMethod.getInstance()) təyin etməlidir. URLSpan — brauzerin avtomatik açılması ilə hiperkeçidlər üçün ClickableSpan alt sinifidir. ClickableSpan tez-tez ForegroundColorSpan ilə birləşdirilir ki, keçidi mavi rənglə vizual olaraq vurğulasın.
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 üzərində kliklər işlənməyəcək. MovementMethod toxunma hadisələrinin kəsilməsinə və toxunma nöqtəsində ClickableSpan axtarışına cavabdehdir. Rəngli span keçidi istifadəçi üçün görünən edir.
SpannableString ilə iş mətn sətirindən nümunənin yaradılması və setSpan() metodu vasitəsilə spanların ardıcıl tətbiqi ilə başlayır. Metod dörd parametr qəbul edir: span obyekti, başlanğıc mövqe, son mövqe və flaglar. Bütün spanlar qurulduqdan sonra obyekt setText() vasitəsilə TextView-ə ötürülür.
İlk sözün qırmızı rəngdə və böyüdülmüş ölçüdə olduğu bir sətir yaradaq. Bunun üçün rəng üçün ForegroundColorSpan və miqyas üçün RelativeSizeSpan istifadə olunur. Hər iki span eyni diapazona bir-birindən asılı olmayaraq tətbiq edilir — setSpan çağırış sırasının əhəmiyyəti yoxdur.
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-cı mövqedən 9-cu mövqeyə qədər simvollar hər iki stili eyni anda alır. TextView çəkmə zamanı bütün spanları avtomatik tətbiq edir — əlavə çağırış tələb olunmur. 1.5f çarpanı olan RelativeSizeSpan şrift ölçüsünü bazaya nisbətən 50% artırır.
Html.fromHtml() HTML sətirindən Spanned obyekti yaradır, lakin dəstəklənən teqlər dəsti məhduddur. SpannableString HTML məhdudiyyətləri olmadan hər bir atribut üzərində tam nəzarət verir. HTML-i spanlara çevirib sonra xüsusi stillər əlavə etmək tələb olunarsa, Html.fromHtml() əsas kimi istifadə edilə bilər, sonra setSpan() vasitəsilə spanlarla tamamlana bilər.
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
Nəticə — “Vacib:” mətni HTML-dən qalın və spandan qırmızı olacaq. Bu yanaşma, formatlaşdırmanın bir hissəsinin HTML ilə, digər hissəsinin isə müştəri tərəfindən proqram vasitəsilə əlavə edildiyi server məzmunu ilə işləyərkən əlverişlidir.
SpannableString eyni və ya üst-üstə düşən diapazona məhdudiyyətsiz sayda span tətbiq etməyə imkan verir. Spanların birləşdirilməsi HTML işarələməsindən qabaqcıl üstünlükdür, burada iç-içə teqlər münaqişə yarada bilər. Spanlar müstəqildir və çəkmə zamanı ardıcıl olaraq tətbiq olunur.
Məsələn, mətnin bir hissəsini eyni anda qalın, qırmızı və kliklənə bilən etmək olar. Bunun üçün üç span — StyleSpan, ForegroundColorSpan və ClickableSpan yaradılır və hər biri eyni diapazona tətbiq edilir. Tətbiq qaydası nəticəyə təsir etmir, çünki hər span öz xarakteristikasına cavabdehdir.
Müxtəlif növ spanlar qismən üst-üstə düşərsə, hər biri öz sərhədləri daxilində müstəqil işləyir. 0–10 diapazonunda ForegroundColorSpan və 5–15 diapazonunda StyleSpan(BOLD) 5–10 hissəsində qalın qırmızı mətn, 10–15 hissəsində isə yalnız qalın mətn verəcək. Heç bir münaqişə yaranmır, çünki hər span çəkmə zamanı öz atributunu dəyişir.
getSpans(int start, int end, Class type) metodu göstərilən diapazona düşən spanların massivini qaytarır. Bu, hansı stillərin artıq tətbiq edildiyini yoxlamaq və ya konkret spanları silmək üçün faydalıdır. nextSpanTransition() ilə spanların dəyişmə sərhədləri boyunca iterasiya etmək olar — bu, stilin harada dəyişdiyini bilməli olan xüsusi TextView siniflərinin işinin əsasını təşkil edir.
SpannableStringBuilder — fraqmentlərin daxil edilməsi, dəyişdirilməsi və silinməsi imkanı ilə stilləşdirilmiş mətnin addım-addım qurulması üçün sinifdir. Hazır sətirdən yaradılan və dəyişməz olan SpannableString-dən fərqli olaraq, Builder mətn hissələrini ardıcıl olaraq əlavə etməyə və onlara stillər təyin etməyə imkan verir. Bu, mürəkkəb mesajlar üçün ideal seçimdir: loglar, söhbətlər, dinamik etiketli xəbər başlıqları.
Builder Spannable və Editable interfeyslərini həyata keçirir ki, bu da onu EditText ilə uyğun edir. İstifadəçi mətni redaktə edə bilər, stillər saxlanılır və yeni simvollar daxil edildikdə düzgün şəkildə yerdəyişir. Dəyişməz olan SpannableString redaktə olunan sahələr üçün uyğun deyil.
append() metodu builder-in özünü qaytarır ki, bu da çağırışlar zənciri qurmağa imkan verir. Mətn əlavə edildikdən sonra setSpan() vasitəsilə spanlar tətbiq edilir. Mövqelər builder-in cari uzunluğuna nisbətən göstərilir. Insert() və replace() məzmun üzərində daha dəqiq nəzarət üçün də mövcuddur.
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 ” mətni mavi, “şərh” isə boz rəngdədir. Onların arasına əlavə simvollar daxil edildikdə, EXCLUSIVE flagları sayəsində span yeni mətnə təsir etmir. Builder dəyişiklik zamanı daxili indeksləri avtomatik korrektə edir.
Çox sayda spanın istifadəsi TextView-in çəkmə performansına təsir edir. Hər span hər yenidənçəkmədə updateDrawState() və ya updateMeasureState() metodunu çağırır. Orta seqment cihazlarında rahat iş üçün bir TextView-də spanların sayını 50–100 arasında məhdudlaşdırmaq tövsiyə olunur. Mətn ölçüsünü dəyişən spanlar (RelativeSizeSpan, AbsoluteSizeSpan) hər dəyişiklikdə layout-un yenidən hesablanmasını tələb edir ki, bu da yalnız rəng və ya altxətt spanlarından qat-qat bahalıdır.
TextAppearanceSpan bir setSpan() əməliyyatı ilə android:textAppearance xml-resursundan bütün stillər dəstini tətbiq etməyə imkan verir. Üç ayrı span (rəng, ölçü, şrift) əvəzinə stila istinad edən bir TextAppearanceSpan istifadə olunur. Bu, obyektlərin sayını azaldır və dəstəyi sadələşdirir — resursda stilin dəyişdirilməsi avtomatik olaraq bu spandan istifadə edən bütün mətnlərə tətbiq olunur.
Hər setSpan() üçün yeni span nümunəsinin yaradılması zibil yığıcıya əlavə yük yaradır. Optimal olaraq, spanlar çox dəfə tətbiq olunarsa, sabit obyektlər yaratmaq məsləhətdir. Məsələn, ForegroundColorSpan(Color.RED) companion object-də saxlanıla və təkrar istifadə oluna bilər. Lakin vəziyyəti olan spanlar (müxtəlif işləyicilərlə ClickableSpan) hər hal üçün ayrıca yaradılmalıdır.
Span performansı ilə bağlı problemlərin diaqnostikası üçün Android Studio-da Layout Inspector və GPU profilçisindən istifadə edin. Çox sayda spanı olan TextView sürüşdürmə zamanı nəzərəçarpacaq dərəcədə yavaşlayırsa, spanların bir hissəsini TextAppearanceSpan vasitəsilə statik stillərlə əvəz etməyi və ya atributları xüsusi UpdateAppearance reallaşdırmalarında birləşdirməklə spanların sayını azaltmağı nəzərdən keçirin.
Tez-tez verilən suallar
String — stilləri dəstəkləməyən dəyişməz simvol ardıcıllığıdır. SpannableString eyni simvolları saxlayır, lakin əlavə olaraq formatlaşdırma haqqında məlumatı olan Span obyektləri massivini ehtiva edir. TextView ötürülən CharSequence növünü təyin edir və çəkmə zamanı spanları müvafiq diapazonlara tətbiq edir. String istənilən stil atributlarını nəzərə almır və düz mətn kimi göstərilir.
removeSpan(Object span) metodu konkret spanı silir. Tam təmizləmə üçün getSpans(0, length, Object::class.java) çağırın ki, bütün spanların massivini qaytarır, sonra hər birini removeSpan vasitəsilə silin. Alternativ olaraq spansız yeni SpannableString(text.toString()) yaradın. SpannableStringBuilder-in clear() metodu həm mətni, həm də spanları silir.
SpannableString EditText-də işləyir, lakin redaktə olunan mətn üçün Editable interfeysini həyata keçirən SpannableStringBuilder daha üstündür. EditText dəyişiklikləri izləmək üçün Editable interfeysi tələb edir. SpannableString-i EditText-ə ötürsəniz, mətn stillərlə göstəriləcək, lakin redaktə zamanı Android onu Editable-ə çevirəcək ki, bu da spanların bir hissəsini sıfırlaya bilər.
Jetpack Compose-də Android SDK spanları birbaşa istifadə olunmur. Bunun əvəzinə Compose AnnotatedString təmin edir — SpannableString-in oxşar imkanlarla öz analoqu: ayrı-ayrı simvollar üçün SpanStyle və abzaslar üçün ParagraphStyle. SpannableString-in AnnotatedString-ə çevrilməsi spanlar üzrə iterasiya ilə buildAnnotatedString vasitəsilə mümkündür.
CharacterStyle-dən miras alan sinif yaradın və updateDrawState(TextPaint tp) metodunu dəyişdirin. Metod daxilində TextPaint xassələrini dəyişin: rəng, xətt qalınlığı, effektlər. Metrik dəyişikliklər üçün UpdateLayout və ya MetricAffectingSpan istifadə edin. Xüsusi spanlar daxili spanlar kimi setSpan() vasitəsilə tətbiq olunur.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun