avatar_aang
avatar_aang

Reputation: 160

Scrollable ComposeView in XML ConstraintLayout: scroll position jumping on state change

I have a ComposeView that is constrained to another View in an XML ConstraintLayout. The ComposeView houses a Column with VerticalScroll. Whenever you are scrolled to the bottom of the column and change the state of something (eg. toggle a switch), the scroll position jumps to hide the bottom of the column. The jump is equivalent to the height of the view that the ComposeView is constrained to. It does not seem to matter whether it is constrained to the top or bottom of the other view. Has anyone encountered this?

I tried using rememberNestedScrollInteropConnection to no avail.

Here is a mock of the issue to reproduce:

fragment_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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">

    <TextView
        android:id="@+id/hello"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:background="#12978C"
        android:text="Hello World!"
        android:textAlignment="center"
        app:layout_constraintBottom_toTopOf="@+id/compose"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.compose.ui.platform.ComposeView
        android:id="@+id/compose"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/hello"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

MainFragment.kt

class MainFragment: Fragment() {
    private lateinit var binding: FragmentMainBinding

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) =
        FragmentMainBinding.inflate(
            inflater, container, false
        ).apply {
            binding = this
        }.root

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.compose.setContent {
            val state = remember { List(25) { false }.toMutableStateList() }
                Column(
                    Modifier.verticalScroll(rememberScrollState())
                ) {
                    for (i in 0..24) {
                        Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center) {
                            Text(i.toString(), fontWeight = FontWeight.Bold)
                            Spacer(Modifier.width(15.dp))
                            Switch(state[i], { state[i] = it })
                        }
                    }
                }
        }
    }
}

Upvotes: 1

Views: 144

Answers (0)

Related Questions