I have a very particular case where we have two Co...
# compose-android
f
I have a very particular case where we have two ComposeViews in a single screen, and the list is being selected instead of the navbar in Talkback. I think the issue is the ComposeView component — a similar implementation using Compose is not having this issue. Has anyone seen a similar issue when working with Compose?
Copy code
class SecondActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)

        findViewById<ComposeView>(R.id.home_content_compose_view).setContent {
            MyApplicationTheme { HomeListContent() }
        }

        findViewById<ComposeView>(R.id.bottom_bar_compose_view).setContent {
            MyApplicationTheme { FloatingBottomBar() }
        }
    }
}

@Composable
private fun HomeListContent() {
    val context = LocalContext.current
    var searchQuery by remember { mutableStateOf("") }

    Column(
        modifier = Modifier
            .fillMaxSize()
            // Edge-to-edge device: reserve room for the status bar (top) and
            // gesture/nav bar (bottom), same fixed-dp approach as MainActivity.
            .padding(top = 100.dp, bottom = 100.dp)
            .background(Color(0xFF121212)),
    ) {
        OutlinedTextField(
            value = searchQuery,
            onValueChange = { searchQuery = it },
            modifier = Modifier
                .fillMaxWidth()
                .padding(16.dp),
            placeholder = { Text("Hi there", color = Color.Gray) },
            leadingIcon = {
                Icon(imageVector = Icons.Default.Search, contentDescription = null, tint = Color.Gray)
            },
            shape = RoundedCornerShape(50),
            colors = OutlinedTextFieldDefaults.colors(
                unfocusedContainerColor = Color(0xFF222222),
                focusedContainerColor = Color(0xFF222222),
                unfocusedBorderColor = Color.Transparent,
                focusedBorderColor = Color.Transparent,
                focusedTextColor = Color.White,
                unfocusedTextColor = Color.White,
            ),
            singleLine = true,
        )

        LazyColumn(
            modifier = Modifier.fillMaxSize(),
            contentPadding = PaddingValues(start = 16.dp, end = 16.dp),
        ) {
            items(30) { index ->
                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(80.dp)
                        .padding(bottom = 12.dp)
                        .clip(RoundedCornerShape(12.dp))
                        .background(Color(0xFF222222))
                        .clickable {
                            Toast.makeText(context, "Item $index tapped", Toast.LENGTH_SHORT).show()
                        },
                    contentAlignment = Alignment.Center,
                ) {
                    Text(text = "Item $index", color = Color.White)
                }
            }
        }
    }
}

@Composable
private fun FloatingBottomBar() {
    Row(
        modifier = Modifier
            .clip(RoundedCornerShape(50))
            .background(Color(0xFF2A2A2A))
            .padding(horizontal = 24.dp, vertical = 12.dp)
            .semantics { isTraversalGroup = true },
        horizontalArrangement = Arrangement.spacedBy(32.dp),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        BottomBarNavItem(icon = Icons.Default.Home, label = "Home")
        BottomBarNavItem(icon = Icons.Default.Notifications, label = "Notification")
        BottomBarNavItem(icon = Icons.Default.AccountCircle, label = "Settings")
    }
}

@Composable
private fun BottomBarNavItem(icon: ImageVector, label: String) {
    val context = LocalContext.current
    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier
            .clickable { Toast.makeText(context, "$label tapped", Toast.LENGTH_SHORT).show() }
            .semantics(mergeDescendants = true) {},
    ) {
        Icon(imageVector = icon, contentDescription = null, tint = Color.White)
        Text(text = label, color = Color.White, fontSize = 10.sp)
    }
}
Copy code
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="<http://schemas.android.com/apk/res/android>"
    xmlns:app="<http://schemas.android.com/apk/res-auto>"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FF121212">

    <FrameLayout
        android:id="@+id/home_content_container"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent">

        <androidx.compose.ui.platform.ComposeView
            android:id="@+id/home_content_compose_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>

    <FrameLayout
        android:id="@+id/bottom_bar_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="300dp"
        android:elevation="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent">

        <androidx.compose.ui.platform.ComposeView
            android:id="@+id/bottom_bar_compose_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </FrameLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
Apparently two Compose views on the same screen don't share their a11y tree, so they generate two different trees and mess up TalkBack. :/ There's an issue tracker that was deprioritized that might fix it: issuetracker.google.com/issues/347038246