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şlik göz önüne alındığında, içeriğinizi düzgün şekilde boyayabilmeniz için 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 değerini sorarsanız metin tek bir satırda çizilmiş gibi Text öğesinin height değerini 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, en uzun Text kadar uzun ve ince (width = 1.dp) olsun.

@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 yöntemi kodumuza uyguladığımızda kodumuz beklendiği gibi çalışı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 bileşeninin minIntrinsicHeight, alt öğelerinin maksimum minIntrinsicHeight değeri olacaktır. Hiçbir kısıtlama verilmezse Divider öğesinin minIntrinsicHeight değeri 0 olur çünkü alan kaplamaz. Text minIntrinsicHeight değeri, belirli bir width değerine sahip metnin değeri 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üzenler için doğru olmayabilir. Bu API'ler, bu varsayılanları geçersiz kılma seçenekleri sunar.

Özel Layout öğenizin 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.
}