Oluşturma düzenlerindeki doğuştan ölçümler

Oluşturma kurallarından biri, çocuklarınızı yalnızca bir kez ölçmeniz gerektiğidir. Çocukların iki kez ölçülmesi, çalışma zamanı istisnaları oluşturur. Bununla birlikte, ölçüm yapmadan önce çocuklarınızla ilgili bazı bilgilere ihtiyaç duyduğunuz zamanlar olur.

Intrinsics, çocukları gerçekten ölçülmeden önce sorgulamanıza olanak tanır.

Bir besteden intrinsicWidth veya intrinsicHeight isteyebilirsiniz:

  • (min|max)IntrinsicWidth: Bu yükseklik dikkate alındığında, içeriğinizi düzgün bir şekilde boyayabileceğiniz minimum/maksimum genişlik ne kadardır?
  • (min|max)IntrinsicHeight: Bu genişlik dikkate alındığında, içeriğinizi düzgün bir şekilde boyayabileceğiniz minimum/maksimum yükseklik nedir?

Örneğin, sonsuz width değerine sahip bir Text öğesinin minIntrinsicHeight sorusunu sorarsanız Text metninin height değerini, tek bir satır gibi çizilmiş gibi döndürür.

İçsel beceriler iş başında

Ekranda, aşağıdaki gibi bir ayırıcıyla ayrılmış iki metin gösteren bir kombinasyon oluşturmak istediğimizi varsayalım:

Aralarında dikey ayırıcı bulunan iki metin öğesi

Bunu nasıl yapabiliriz? İçinde iki Text bulunan ve mümkün olduğunca genişletilen bir Row ve ortada bir Divider bulunabilir. Bölen'in en uzun Text ve ince (width = 1.dp) kadar yüksek olmasını isteriz.

@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
        )
        Divider(
            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, Ayırıcı'nın tüm ekrana genişlediğini görürüz ve istediğimiz bu değildir:

Ayırıcı yardımıyla iki metin öğesi yan yana

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

height(IntrinsicSize.Min), çocuklarının minimum fiziksel yüksekliği kadar yüksek olmasına zorlanır. Yinelendiği için Row ve alt öğelerini minIntrinsicHeight sorgulayacak.

Kodun bu şekilde kullanılması, beklenen şekilde ç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
        )
        Divider(
            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 ayırıcı bulunan iki metin öğesi

Row bestesinin minIntrinsicHeight alt öğeleri maksimum minIntrinsicHeight olacaktır. Herhangi bir kısıtlama sağlanmazsa Divider öğesinin minIntrinsicHeight değeri 0 olur; Text minIntrinsicHeight, belirli bir width verilen metnin minIntrinsicHeight değeri olur. Bu nedenle, Row öğesinin height kısıtlaması, Text öğesinin maksimum minIntrinsicHeight değerini alır. Ardından Divider, height özelliğini Row tarafından sağlanan height kısıtlamasına genişletir.

Özel düzenlerinizdeki içsel bilgiler

Özel bir Layout veya layout değiştiricisi oluşturulurken iç ölçümler, yaklaşık değerler temel alınarak 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 metriğinizin iç mekan ölçümlerini belirtmek için, oluştururken MeasurePolicy arayüzünün minIntrinsicWidth, minIntrinsicHeight, maxIntrinsicWidth ve maxIntrinsicHeight değerlerini 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.
}