TextMeasurer: bu nədir və Compose-da mətn ölçülməsi necə işləyir

Müəllif: IT Sectr Dərc olunub: 2026-07-25 Oxuma vaxtı: 8 dəq

TextMeasurer — ekranda faktiki render edilmədən əvvəl mətnin ölçülərini ölçmək üçün nəzərdə tutulmuş Jetpack Compose API-sidir. Android View-da Paint.measureText vasitəsilə klassik yanaşmadan fərqli olaraq, TextMeasurer üslub və məhdudiyyətləri nəzərə alaraq mətnin enini, hündürlüyünü və sətir metrikalarını əldə etmək üçün Compose-native üsul təqdim edir. Android Developers Documentation (2025) məlumatına görə, TextMeasurer fərdi Layout komponentlərində, animasiya edilmiş başlıqlarda və mətn ölçüsünün digər elementlərin yerləşdirilməsinə təsir etdiyi adaptiv UI elementlərində fəal şəkildə istifadə olunur.

Əsas məqamlar

  • TextMeasurer — render etmədən əvvəl mətni ölçmək üçün Compose API-si.
  • measure() metodu sətir və simvol metrikaları ilə TextLayoutResult qaytarır.
  • API üslub, şrift, ölçü və konteyner məhdudiyyətlərini piksel olaraq nəzərə alır.
  • TextMeasurer tək sətir və çoxsətirli mətnin ölçülməsini dəstəkləyir.
  • Ölçmə nəticəsi xüsusi düzülüş və mətn animasiyası üçün istifadə olunur.

Jetpack Compose-da TextMeasurer nədir?

TextMeasurer — ekranda birbaşa render etmədən Compose-da mətni ölçməyə imkan verən androidx.compose.ui.text paketindən funksional interfeysdir. O, Compose mətn mühərrikinin bir hissəsidir və Skia-dan render üçün istifadə edən Paragraph API səviyyəsində işləyir.

TextMeasurer-in əsas təyinatı ilkin ölçmədir. Compose-da mətnin ölçüsü adətən Composable artıq Layout-da yerləşdirildikdən sonra müəyyən edilir. Lakin bəzi ssenarilərdə mətnin enini kompozisiyadan əvvəl bilmək lazımdır: məsələn, sətrin konteynerə sığıb-sığmadığını müəyyən etmək və ya mətnin uzunluğuna əsasən düymənin ölçüsünü hesablamaq.

TextMeasurer bu problemi measure() metodu ilə həll edir. O, TextMeasureRequest (mətn, üslub, məhdudiyyətlər) qəbul edir və TextLayoutResult (metrikalar, sətirlər, simvollar) qaytarır. Bu, proqramçıya bir kadr gecikməsi olmadan mətn haqqında bütün məlumatları sinxron şəkildə əldə etməyə imkan verir.

TextMeasurer-dən mətn ölçüsünün valideyn komponentinin ölçüsünə təsir etdiyi hallarda, animasiya edilmiş mətn keçidləri yaradarkən və ya mətnin digər elementlərlə yanaş olduğu xüsusi Layout-ları tətbiq edərkən istifadə edin.

TextMeasurer necə işləyir

TextMeasurer API-si iki əsas varlıqdan ibarətdir: rememberTextMeasurer() (nümunənin yaradılması) və measure() (ölçmənin başladılması). Nümunə komponentin bütün həyat dövrü üçün bir dəfə yaradılır və bütün ölçmələr üçün təkrar istifadə olunur.

kotlin
val textMeasurer = rememberTextMeasurer()

val result = textMeasurer.measure(
    text = "Hello, Compose!",
    style = MaterialTheme.typography.bodyLarge,
    constraints = Constraints(maxWidth = 200, maxHeight = 50)
)

// nəticənin eni, nəticənin hündürlüyü, sətirlərin sayı

constraints parametri mətnin yerləşməli olduğu maksimum en və hündürlüyü müəyyən edir. Mətn enə sığmazsa, növbəti sətrə keçirilir. Ölçmə nəticəsində sətirlərin sayını, hər simvolun mövqeyini, hər sətrin enini və mətnin ümumi ölçüsünü əldə edə biləcəyiniz TextLayoutResult var.

TextMeasurer UI axınında sinxron işləyir və yenidən kompozisiyaya səbəb olmur. Bununla belə, müxtəlif üslublarla mətnin tez-tez ölçülməsi yük yarada bilər — buna görə də nümunə remember vasitəsilə yaradılır və təkrar istifadə olunur.

Tək sətirli mətnin ölçülməsi

Ən sadə ssenari — valideyn konteynerinin ölçüsünü müəyyən etmək üçün təksətirli mətnin enini ölçməkdir. Məsələn, eni etiketin uzunluğundan asılı olan düymə üçün.

kotlin
val textMeasurer = rememberTextMeasurer()
var label by remember { mutableStateOf("Submit") }

val textResult = remember(label) {
    textMeasurer.measure(
        text = label,
        style = MaterialTheme.typography.labelLarge,
        constraints = Constraints(maxWidth = 1000, maxHeight = 100)
    )
}

Box(
    modifier = Modifier
        .width(textResult.size.width.dp)
        .height(40.dp)
        .background(Color.Blue)
        .clickable { onClick() }
) {
    Text(text = label, style = MaterialTheme.typography.labelLarge)
}

Bu nümunədə remember(label) ölçmənin yalnız mətn dəyişdikdə yenidən başlamasına zəmanət verir. Constraints sətirin keçirilməsinin qarşısını almaq üçün böyük maxWidth (1000) ilə təyin edilmişdir — faktiki məhdudiyyət mətnin eninə bərabər olacaqdır. Box-ın eni ölçülmüş mətn eninə təyin edilir ki, bu da „mətn ölçüsünə uyğun düymə" effekti verir.

Diqqət: nəticədən eni .dp vasitəsilə dp-ə çevirmək lazımdır, çünki TextMeasurer piksel olaraq ölçüləri qaytarır, Modifier.width isə Dp gözləyir. Dəqiqlik üçün density və LocalDensity.current istifadə edin.

Çoxsətirli mətnin ölçülməsi

Çoxsətirli mətn üçün TextMeasurer yalnız ümumi hündürlüyü deyil, həm də sətirlərin sayını və hər simvolun mövqeyini abzas daxilində müəyyən etməyə imkan verir. Bu, xüsusi mətn sahələri, çatlar və ya redaktorlar yaradarkən lazımdır.

Çoxsətirli mətn üçün TextLayoutResult-un əsas xüsusiyyətləri: lineCount (sətirlərin sayı), getLineTop(index) (sətrin başlanğıcının Y koordinatı), getLineBottom(index) (sonun Y koordinatı), getLineWidth(index) (sətrin eni). Onları birləşdirərək interfeys elementlərini mətn sətirlərinə nisbətən dəqiq yerləşdirə bilərsiniz.

kotlin
val textMeasurer = rememberTextMeasurer()
val result = textMeasurer.measure(
    text = "Long multiline text that needs to be measured before layout",
    style = MaterialTheme.typography.bodyMedium,
    constraints = Constraints(maxWidth = 150, maxHeight = 300)
)

val linesCount = result.lineCount
val firstLineWidth = result.getLineWidth(0)
val totalHeight = result.size.height

getLineWidth(lineIndex) metodu göstərilən sətrin enini piksel olaraq qaytarır. Sətir konteynerin sərhədinə çatmazsa, bu maxWidth-dən az ola bilər. Hər sətrin enini bilərək, justifikasiya effektini əl ilə həyata keçirə və ya qısa sətirlərin yanında inline elementlər yerləşdirə bilərsiniz.

Müəyyən bir simvolun mövqeyini əldə etmək üçün left, top, right, bottom koordinatları ilə Rect qaytaran getBoundingBox(offset) istifadə edin. Bu, xüsusi mətn sahələrində kursorun yerləşdirilməsi və ya animasiya ilə mətn diapazonunun vurğulanması üçün faydalıdır.

Xüsusi komponentlərdə TextMeasurer

TextMeasurer-in ən güclü tətbiq ssenarisi — mətnin digər elementlərlə yanaşı olduğu və ölçülərinin qarşılıqlı asılı olduğu xüsusi Layout komponentləridir. Məsələn, "İkon + mətn" vidjeti, burada ikon bütün bloka deyil, mətnin ilk sətirinə nisbətən mərkəzləşdirilməlidir.

Standart Row-da ikon bütün Row-un hündürlüyünə görə mərkəzləşdirilir ki, bu da mətn 3 sətir, ikon isə bir sətir tutduqda təbii görünmür. TextMeasurer ilə ilk sətri ölçmək və ikonu məhz ona nisbətən düzləndirmək olar.

kotlin
val textMeasurer = rememberTextMeasurer()

Layout(
    content = {
        Icon(imageVector = Icons.Default.Star, contentDescription = null)
        Text(text = "Burada çoxsətirli mətn")
    },
    measurePolicy = { measurables, constraints ->
        val textMeasurable = measurables[1]
        val textPlaceable = textMeasurable.measure(constraints)
        val iconPlaceable = measurables[0].measure(constraints)

        val firstLineHeight = textMeasurer.measure(
            text = "Sample",
            style = MaterialTheme.typography.bodyMedium,
            constraints = Constraints(maxWidth = 2000, maxHeight = 100)
        ).size.height

        layout(width = textPlaceable.width + iconPlaceable.width,
               height = maxOf(textPlaceable.height, iconPlaceable.height)) {
            iconPlaceable.placeRelative(0, (firstLineHeight - iconPlaceable.height) / 2)
            textPlaceable.placeRelative(iconPlaceable.width, 0)
        }
    }
)

Bu nümunədə TextMeasurer vasitəsilə ilk sətrin ölçülməsi ikonun mövqeyini müəyyən edir. TextMeasurer olmadan ikon çoxsətirli mətnin bütün hündürlüyünə görə mərkəzləşərdi ki, bu da vizual olaraq düzgün deyil. Bu nümunə çatlarda, kontakt siyahılarında və məlumat kartlarında geniş istifadə olunur.

Performans məsləhətləri

TextMeasurer — UI axınında işləyən sinxron API-dir. Həddindən artıq istifadə edildikdə, xüsusilə zəif cihazlarda böyük həcmdə mətn ölçərkən kadr itkisinə səbəb ola bilər.

Birinci qayda — nəticəni keşləyin. Həmişə measure() çağırışını mətn və üslubdan asılılıqlarla remember-ə sarın. Heç vaxt measure()-i CompositionLocal daxilində və ya recomposition-un istiqamətlərində çağırmayın.

İkinci qayda — maxWidth və maxHeight-i məhdudlaşdırın. maxWidth = Constraints.Infinity təyin etsəniz, TextMeasurer sətirləri keçirə bilməyəcək və mətn ekrandan kənara çıxacaq. Həmişə realistik məhdudiyyətlər təyin edin, xüsusilə çoxsətirli mətn üçün.

Üçüncü — eyni parametrlərlə təkrar ölçmədən çəkinin. Mətn və üslub dəyişməyibsə, measure() nəticəsi eyni olacaq. Asinxron ssenarilər üçün ölçməni Deferred və ya LaunchedEffect ilə birləşdirin.

Tez-tez verilən suallar

TextMeasurer Compose-da onSizeChanged-dən nə ilə fərqlənir?

TextMeasurer mətni render etmədən əvvəl ölçür, onSizeChanged isə sonra. TextMeasurer mətn ölçüsü valideynin layoutuna təsir etdikdə lazımdır; onSizeChanged kompozisiyadan sonra reaktiv məntiq üçün uyğundur.

SpannableString-i TextMeasurer vasitəsilə ölçmək olar?

Bəli, TextMeasurer.measure() inline üslublar, keçidlər və rənglərlə SpannableString-i əhatə edən AnnotatedString qəbul edir. Bütün spanlar ölçmə zamanı nəzərə alınır.

Niyə TextMeasurer ölçünü dp ilə deyil, piksel olaraq qaytarır?

TextMeasurer Skia-render səviyyəsində işləyir, burada bütün ölçülər pikseldir. LocalDensity.current vasitəsilə çevirin: density.run { width.toDp() }.

Şrift yüklənməzdən əvvəl mətni necə ölçmək olar?

TextMeasurer xüsusi şrift yüklənənə qədər FontFamily.Default istifadə edir. Dəqiq ölçmə üçün FontResource vasitəsilə yüklənməni gözləyin və async/await istifadə edin.

TextMeasurer LazyColumn siyahılarının performansına təsir edirmi?

LazyColumn-un hər elementində mətnin ölçülməsi zəif cihazlarda FPS-i aşağı sala bilər. Optimallaşdırma: nəticəni remember vasitəsilə keşləyin və mətn ölçüsünü məhdudlaşdırın.

Nəticə

  • TextMeasurer — render etmədən əvvəl mətni ölçmək üçün Compose API-si, TextLayoutResult qaytarır.
  • measure() metodu mətni, üslubu və pikseldə Constraints qəbul edir.
  • Nümunə rememberTextMeasurer() vasitəsilə yaradılır və təkrar istifadə olunur.
  • Təksətirli mətn üçün nəticə konteynerin adaptiv eni üçün istifadə olunur.
  • Çoxsətirli mətn üçün — lineCount, getLineWidth() və getBoundingBox() tam mənzərəni verir.
  • Xüsusi Layout-larda TextMeasurer elementləri düzləndirməyə mətnin ilk sətirinə görə imkan verir.
  • Nəticəni remember vasitəsilə keşləyin və recomposition-un isti yollarında ölçmədən çəkinin.

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.

Layihəni müzakirə et

Həm də oxuyun