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

Compose'un kurallarından biri de çocuklarınızı yalnızca bir kez ölçmenizdir. alt öğelerin iki kez ölçülmesi çalışma zamanı istisnasına yol açar. Ancak, çocuğunuzla ilgili bazı bilgilere ihtiyaç duyduğunuzda emin olmanız gerekir.

Doğal nitelik, çocukları gerçekte ölçülmeden önce sorgulamanızı sağlar.

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, minimum/maksimum değer nedir? içeriğinizi doğru şekilde boyayabiliyor musunuz?

Ö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 öğesinin şöyle olmasını istiyoruz: uzun Text ve ince (width = 1.dp).

@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 önizlersek Divider öğesinin tüm ekrana genişlediğini ve istediğimiz şey bu değil:

Yan yana duran iki metin öğesi, aralarında ayırıcı var. Ancak ayırıcı metnin alt kısmına doğru 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 alt öğe sayısını dikkate alabilirsiniz. Yinelemeli olduğu için Row ve çocuklar minIntrinsicHeight.

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
        )
        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 yan yana iki metin öğesi

Row composable'ın minIntrinsicHeight değeri maksimum değere ulaşacak Alt varlıklarından minIntrinsicHeight tanesi. 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ı en yüksek değer olacaktır minIntrinsicHeight/Text. Daha sonra Divider, height özelliğini şu değere kadar genişletecek: Row tarafından sağlanan height kısıtlaması.

Özel düzenlarınızdaki iç öğeler

Özel Layout veya layout değiştiricisi oluştururken doğal ölçümler yaklaşık değerlere göre otomatik olarak hesaplanır. Dolayısıyla, hesaplamalar tüm düzenlerde doğru olmayabilir. Bu API'ler çeşitli seçenekler sunar. kullanabilirsiniz.

Özel Layout öğenizin yerleşik ölçümlerini belirtmek için minIntrinsicWidth, minIntrinsicHeight, maxIntrinsicWidth ve ve maxIntrinsicHeight MeasurePolicy arayüzü gibi düşünülebilir.

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

ziyaret edin.