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

Oluşturma kurallarının birinde, çocuklarınızı yalnızca bir kez ölçmeniz gerektiği belirtilir. Çocukları iki kez ölçmek, çalışma zamanında istisna oluşturur. Ancak, çocuğunuzla ilgili bazı bilgilere ihtiyaç duyduğunuzda emin olmanız gerekir.

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

Bir composable için intrinsicWidth veya intrinsicHeight isteyebilirsiniz:

  • (min|max)IntrinsicWidth: Bu genişlik göz önüne alındığında, minimum/maksimum ne kadar uyumlu?
  • (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 sayıda Text özelliğine sahip minIntrinsicHeight hakkında soru sorarsanız height, metin sanki bir çerçeve içinde çizilmiş gibi Text için height döndürür Tek satır.

Yerleşik özellikleri uygulama

Sayfadaki iki metni görüntüleyen bir composable oluşturmak istediğimizi gibi bir ayırıcıyla ayrılmış ekran görürsünüz:

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

Bunu nasıl yapabiliriz? İçinde iki Text bulunan ve şu şekilde genişleyen bir Row'imiz olabilir: ortada bir Divider var. 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 önizlersek Divider öğesinin tüm ekrana genişlediğini ve istediğimiz şey bu değil:

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 her çocuğu ayrı ayrı ve çocuğun yüksekliğini Divider değerini kısıtlamak için Text kullanılamaz. Doldurulmasını Divider istiyoruz belirlenen bir yükseklikteki kullanılabilir alan. Bunun için, height(IntrinsicSize.Min) değiştiricisi .

height(IntrinsicSize.Min), çocuklarının en az boyunda minimum doğal yükseklikleridir. 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 bileşeninin minIntrinsicHeight, alt öğelerinin maksimum minIntrinsicHeight değeri olacaktır. Divider öğesinin Hiçbir kısıtlama olmadığında yer kaplamadığı için minIntrinsicHeight değeri 0'dır verilen; Text minIntrinsicHeight, belirli bir width. Bu nedenle, Row öğesinin height kısıtlaması, Text değerlerinin maksimum minIntrinsicHeight değeri olur. Daha sonra Divider, height özelliğini şu değere kadar genişletecek: Row tarafından sağlanan height kısıtlaması.

Ö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 ilgili yöntemleri geçersiz kılın LayoutModifier arayüzünde.

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.
}