• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.compose.animation.scene.demo
18 
19 import androidx.compose.material3.LocalContentColor
20 import androidx.compose.material3.LocalTextStyle
21 import androidx.compose.runtime.Composable
22 import androidx.compose.runtime.remember
23 import androidx.compose.ui.Modifier
24 import androidx.compose.ui.draw.drawBehind
25 import androidx.compose.ui.graphics.ColorProducer
26 import androidx.compose.ui.layout.Layout
27 import androidx.compose.ui.text.TextLayoutResult
28 import androidx.compose.ui.text.TextMeasurer
29 import androidx.compose.ui.text.TextStyle
30 import androidx.compose.ui.text.drawText
31 import androidx.compose.ui.text.style.TextOverflow
32 
33 /**
34  * A text whose measures can be cached outside composition using [textMeasurer].
35  *
36  * Important: DO NOT USE THIS IN PRODUCTION CODE. You should always use the Text() or BasicText()
37  * composables instead. This was introduced only to optimize the SceneTransitionLayout benchmarks
38  * and make their frame time metrics more stable.
39  */
40 @Composable
41 fun CachedText(
42     text: String,
43     textMeasurer: TextMeasurer,
44     modifier: Modifier = Modifier,
45     style: TextStyle = LocalTextStyle.current,
46     overflow: TextOverflow = TextOverflow.Clip,
47     softWrap: Boolean = true,
48     maxLines: Int = Int.MAX_VALUE,
49     color: ColorProducer? = null,
50 ) {
51     val lastLayoutResult = remember {
52         object {
53             var value: TextLayoutResult? = null
54         }
55     }
56 
57     val localColor = if (color != null) null else LocalContentColor.current
58     Layout(
59         modifier =
60             modifier.drawBehind {
61                 val textLayoutResult =
62                     lastLayoutResult.value ?: error("draw happened before layout")
63                 val color =
64                     color?.let { it() }
65                         ?: localColor
66                         ?: error("localColor should not be null when color is null")
67                 drawText(textLayoutResult, color)
68             }
69     ) { _, constraints ->
70         val layoutResult =
71             textMeasurer.measure(text, style, overflow, softWrap, maxLines, constraints).also {
72                 lastLayoutResult.value = it
73             }
74         layout(layoutResult.size.width, layoutResult.size.height) {}
75     }
76 }
77