diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-03-16 22:48:32 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2023-03-16 22:48:32 +0000 |
commit | 5c52e350f924e5e7b0d110a5ea342c5fd6b249f0 (patch) | |
tree | e8a55bda1ffeb7472fcaad0385c2e07873d47a06 | |
parent | 8b6d82fa81cf938a709c55cc97db95c16f0d5715 (diff) | |
parent | 1b33968f14a21185a5b29b2cc0785125dbbd9066 (diff) | |
download | support-5c52e350f924e5e7b0d110a5ea342c5fd6b249f0.tar.gz |
Merge "Fix NPE in AndroidView when in a SubcomposeLayout" into snap-temp-L01600000959187804
2 files changed, 49 insertions, 1 deletions
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt index 71f542b250b..925bd713b52 100644 --- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt +++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt @@ -18,6 +18,7 @@ package androidx.compose.ui.layout import android.annotation.SuppressLint import android.os.Build +import android.view.View import android.widget.FrameLayout import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints @@ -52,6 +53,7 @@ import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.asAndroidBitmap +import androidx.compose.ui.layout.RootMeasurePolicy.measure import androidx.compose.ui.platform.AndroidOwnerExtraAssertionsRule import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.LocalDensity @@ -71,6 +73,7 @@ import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp +import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.zIndex import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest @@ -2351,6 +2354,40 @@ class SubcomposeLayoutTest { .assertExists() } + // Regression test of b/271156218 + @Test + fun deactivatingDeeplyNestedAndroidViewDoesNotCauseRemeasure() { + var showContent by mutableStateOf(true) + val state = SubcomposeLayoutState(SubcomposeSlotReusePolicy(1)) + rule.setContent { + SubcomposeLayout( + state = state, + modifier = Modifier.fillMaxSize() + ) { constraints -> + val content = if (showContent) { + subcompose(0) { + Box { + AndroidView(::View, Modifier.fillMaxSize().testTag("AndroidView")) + } + } + } else emptyList() + + val placeables = measure(content, constraints) + layout(100, 100) { + placeables.placeChildren() + } + } + } + + rule.onNodeWithTag("AndroidView").assertExists() + + rule.runOnIdle { showContent = false } + rule.onNodeWithTag("AndroidView").assertIsNotDisplayed() + + rule.runOnIdle { showContent = true } + rule.onNodeWithTag("AndroidView").assertExists() + } + private fun composeItems( state: SubcomposeLayoutState, items: MutableState<List<Int>> diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt index 258b7171ea5..bd6bf08f5f6 100644 --- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt +++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt @@ -204,7 +204,7 @@ internal open class AndroidViewHolder( override fun onDeactivate() { reset() - removeView(view) + removeAllViewsInLayout() } override fun onRelease() { @@ -212,6 +212,13 @@ internal open class AndroidViewHolder( } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + if (view?.parent !== this) { + setMeasuredDimension( + MeasureSpec.getSize(widthMeasureSpec), + MeasureSpec.getSize(heightMeasureSpec) + ) + return + } view?.measure(widthMeasureSpec, heightMeasureSpec) setMeasuredDimension(view?.measuredWidth ?: 0, view?.measuredHeight ?: 0) lastWidthMeasureSpec = widthMeasureSpec @@ -339,6 +346,10 @@ internal open class AndroidViewHolder( measurables: List<Measurable>, constraints: Constraints ): MeasureResult { + if (childCount == 0) { + return layout(constraints.minWidth, constraints.minHeight) {} + } + if (constraints.minWidth != 0) { getChildAt(0).minimumWidth = constraints.minWidth } |