Compose düzenlerindeki içsel ölçümler

Oluşturma kurallarının birinde, çocuklarınızın ölçümünü yalnızca bir kez yapmanız gerektiği belirtilir. Çocukları iki kez ölçtüğünüzde çalışma zamanında istisna oluşur. Bununla birlikte, çocuklarınızla ilgili bazı bilgileri ölçmeden önce bilmeniz gereken durumlar vardır.

İçsel özellikler, çocuklar ölçülmeden önce sorgu yapmanıza olanak tanır.

Bir bileşen için intrinsicWidth veya intrinsicHeight değerini isteyebilirsiniz:

  • (min|max)IntrinsicWidth: Bu genişliğe göre, içeriğinizi düzgün şekilde boyayabileceğiniz minimum/maksimum genişlik nedir?
  • (min|max)IntrinsicHeight: Bu yükseklik göz önüne alındığında, içeriğinizi düzgün şekilde boyayabilmeniz için minimum/maksimum yükseklik nedir?

Örneğin, sonsuz height içeren bir Text öğesinin minIntrinsicHeight özelliğini sorarsanız Text öğesinin height değerini, metin tek bir satıra çizilmiş gibi döndürür.

Yerleşik özelliklerin kullanımı

Ekranda şu şekilde bir ayırıcıyla ayrılmış iki metin gösteren bir kompozisyon oluşturmak istediğimizi varsayalım:

Aralarında dikey bir ayırıcı bulunan, yan yana iki metin öğesi

Bunu nasıl yapabiliriz? İçinde olabildiğince genişleyen iki Text ve ortasında bir Divider bulunan bir Row olabilir. Divider öğesinin, en uzun Text ve ince (width = 1.dp) kadar uzun olmasını istiyoruz.

@Composable
fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) {
    Row(modifier = modifier) {
        Text(
            modifier = Modifier
                .weight(1f)
                .padding(start = 4.dp)
                .wrapContentWidth(Alignment.Start),
            text = text1
        )
        HorizontalDivider(
            color = Color.Black,
            modifier = Modifier.fillMaxHeight().width(1.dp)
        )
        Text(
            modifier = Modifier
                .weight(1f)
                .padding(end = 4.dp)
                .wrapContentWidth(Alignment.End),

            text = text2
        )
    }
}

Bunu önizlediğimizde Divider öğesinin ekranın tamamına genişlediğini görürüz. İstediğimiz bu değildir:

Yan yana iki metin öğesi, aralarında ayırıcı var ancak ayırıcı, metnin alt kısmının altına kadar uzanıyor

Bunun nedeni, Row'ün her çocuğu ayrı ayrı ölçmesi ve Text'ün yüksekliğinin Divider'yi kısıtlamak için kullanılamamasıdır. Divider'ün, mevcut alanı belirli bir yükseklikle doldurmasını istiyoruz. Bunun için height(IntrinsicSize.Min) değiştiricisini kullanabiliriz .

height(IntrinsicSize.Min), alt öğelerinin minimum doğal yükseklikleri kadar yüksek olması için boyutlarını ayarlar. Yinelenen bir sorgu olduğu için Row ve alt öğeleri minIntrinsicHeight sorgulanır.

Bu kodu kodumuza uyguladığınızda, beklendiği gibi çalışacaktır:

@Composable
fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) {
    Row(modifier = modifier.height(IntrinsicSize.Min)) {
        Text(
            modifier = Modifier
                .weight(1f)
                .padding(start = 4.dp)
                .wrapContentWidth(Alignment.Start),
            text = text1
        )
        HorizontalDivider(
            color = Color.Black,
            modifier = Modifier.fillMaxHeight().width(1.dp)
        )
        Text(
            modifier = Modifier
                .weight(1f)
                .padding(end = 4.dp)
                .wrapContentWidth(Alignment.End),

            text = text2
        )
    }
}

// @Preview
@Composable
fun TwoTextsPreview() {
    MaterialTheme {
        Surface {
            TwoTexts(text1 = "Hi", text2 = "there")
        }
    }
}

Önizlemeyle:

Aralarında dikey bir ayırıcı bulunan, yan yana iki metin öğesi

Row composable'ın minIntrinsicHeight, alt öğelerinin maksimum minIntrinsicHeight tanesi olacak. Divider öğesinin minIntrinsicHeight değeri, herhangi bir kısıtlama sağlanmadığında yer kaplamadığı için 0 olur. Text minIntrinsicHeight değeri, belirli bir width belirtilen metin olur. Bu nedenle, Row öğesinin height kısıtlaması, Text değerlerinin maksimum minIntrinsicHeight değeri olur. Divider, height değerini Row tarafından verilen height kısıtlamasına göre genişletir.

Özel düzenlerinizdeki içsel öğeler

Özel bir Layout veya layout değiştirici oluştururken, doğal ölçümler yaklaşık değerlere göre otomatik olarak hesaplanır. Bu nedenle, hesaplamalar tüm düzenlerde doğru olmayabilir. Bu API'ler, bu varsayılanları geçersiz kılma seçenekleri sunar.

Özel Layout'ünüzün doğal ölçümlerini belirtmek için MeasurePolicy arayüzünü oluştururken minIntrinsicWidth, minIntrinsicHeight, maxIntrinsicWidth ve maxIntrinsicHeight öğelerini geçersiz kılın.

@Composable
fun MyCustomComposable(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    Layout(
        content = content,
        modifier = modifier,
        measurePolicy = object : MeasurePolicy {
            override fun MeasureScope.measure(
                measurables: List<Measurable>,
                constraints: Constraints
            ): MeasureResult {
                // Measure and layout here
                // ...
            }

            override fun IntrinsicMeasureScope.minIntrinsicWidth(
                measurables: List<IntrinsicMeasurable>,
                height: Int
            ): Int {
                // Logic here
                // ...
            }

            // Other intrinsics related methods have a default value,
            // you can override only the methods that you need.
        }
    )
}

Özel layout değiştiricinizi oluştururken LayoutModifier arayüzündeki ilgili yöntemleri geçersiz kılın.

fun Modifier.myCustomModifier(/* ... */) = this then object : LayoutModifier {

    override fun MeasureScope.measure(
        measurable: Measurable,
        constraints: Constraints
    ): MeasureResult {
        // Measure and layout here
        // ...
    }

    override fun IntrinsicMeasureScope.minIntrinsicWidth(
        measurable: IntrinsicMeasurable,
        height: Int
    ): Int {
        // Logic here
        // ...
    }

    // Other intrinsics related methods have a default value,
    // you can override only the methods that you need.
}