如何在Compose中打印AndroidView的语义树?

qyyhg6bp  于 2023-06-20  发布在  Android
关注(0)|答案(1)|浏览(122)

我有一个包含简单TextViewAndroidView组合。
我想打印AndroidView的语义树,包括TextView的完整树。
当我尝试下面的printToLog时,它不包括TextView节点,并且AssertionError测试失败(见下文)。
如何将TextView节点包含到树中?

@OptIn(ExperimentalCoroutinesApi::class)
class AndroidViewTester {
    
    @get:Rule
    val composeRule = createComposeRule()

    @Before
    fun setUp() {
        composeRule.setContent {
            AndroidViewExample()
        }
    }

    @Composable
    fun AndroidViewExample() {
        val text by remember { mutableStateOf("TextView text") }
        Column(
            modifier = Modifier
                .fillMaxSize()
                .semantics(false) { contentDescription = "Column" }
        ) {
            Text("Composable text")
            MyTextView(text)
        }
    }

    @Composable
    fun MyTextView(text: String) {
        AndroidView(
            factory = { context ->
                TextView(context).apply {
                    setText(text)
                }
            },
            update = { view ->
                (view as TextView).append(" $text")
            },
            modifier = Modifier
                .fillMaxSize()
                .semantics(mergeDescendants = false) {
                    contentDescription = "My Android View"
                }
        )
    }

测试

@Test
    fun AndroidViewSemanticsTest() = runTest {
            composeRule.onAllNodes(isRoot(), useUnmergedTree = true)
                .printToLog("Print Root", maxDepth = 10)

            composeRule.onNode(hasText("TextView text"))
                .assertExists()
        /** java.lang.AssertionError: Failed: assertExists.
            Reason: Expected exactly '1' node but could not find any node that satisfies:
            (Text + EditableText contains 'TextView text' (ignoreCase: false))
         */
        }
}

printToLog输出

Printing with useUnmergedTree = 'true'                 
Node #1 at (l=0.0, t=220.0, r=1080.0, b=2208.0)px      
 |-Node #2 at (l=0.0, t=220.0, r=1080.0, b=2208.0)px   
   ContentDescription = '[Column]'                     
    |-Node #3 at (l=0.0, t=220.0, r=286.0, b=272.0)px  
    | Text = '[Composable text]'                       
    | Actions = [GetTextLayoutResult]                  
    |-Node #4 at (l=0.0, t=272.0, r=1080.0, b=2208.0)px
      ContentDescription = '[My Android View]'         
      MergeDescendants = 'true'
oalqel3c

oalqel3c1#

我试了一个简单的例子。

@Composable
    fun MyTextView() {
        AndroidView(
            factory = { context ->
                TextView(context).apply {
                    text = "TextView text"
                }
            }
        )
    }

    @Test
    fun debug() {
        composeTestRule.setContent {
            MyTextView()
        }

        composeTestRule.onRoot().printToLog("debug-androidView")
    }
Printing with useUnmergedTree = 'false'
Node #1 at (l=0.0, t=238.0, r=235.0, b=291.0)px
|-Node #2 at (l=0.0, t=238.0, r=235.0, b=291.0)px
MergeDescendants = 'true'

似乎AndroidView不提供任何语义。在Modifier.semantics范围内,我发现了一个set方法。

@Composable
    fun MyTextView() {
        AndroidView(
            factory = { context ->
                TextView(context).apply {
                    text = "TextView text"
                }
            },
            modifier = Modifier.semantics {
                this[SemanticsPropertyKey("Text")] = "TextView text"
            }
        )
    }
Printing with useUnmergedTree = 'false'
Node #1 at (l=0.0, t=238.0, r=235.0, b=291.0)px
|-Node #2 at (l=0.0, t=238.0, r=235.0, b=291.0)px
Text = 'TextView text'
MergeDescendants = 'true'

AssertcomposeTestRule.onNodeWithText("TextView text").assertExists()仍然失败。
然后,我意识到已经有一个text字段。

modifier = Modifier.semantics(false) {
    this.text = AnnotatedString("TextView text")
}

它似乎是一个默认的SemanticsProperty。

var SemanticsPropertyReceiver.text: AnnotatedString
    get() = throwSemanticsGetNotSupported()
    set(value) { set(SemanticsProperties.Text, listOf(value)) }
val Text = SemanticsPropertyKey<List<AnnotatedString>>(
        name = "Text",
        mergePolicy = { parentValue, childValue ->
            parentValue?.toMutableList()?.also { it.addAll(childValue) } ?: childValue
        }
    )

也使用了名称“Text”,但类型不同(List<AnnotatedString>而不是String)。

相关问题